Merge
authorjwilhelm
Fri, 11 Nov 2016 16:44:36 +0100
changeset 42560 95af45781076
parent 42559 f71b844f33d1 (current diff)
parent 41945 31f5023200d4 (diff)
child 42561 84b1f0f39cb0
Merge
jdk/make/GenerateClasslist.gmk
jdk/src/java.base/share/classes/jdk/internal/module/ConfigurableModuleFinder.java
jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java
jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java
jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java
jdk/src/java.base/share/native/include/jvmti.h
jdk/src/java.base/share/native/libjava/StackFrameInfo.c
jdk/src/java.base/windows/native/libnet/icmp.h
jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java
jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java
jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.html
jdk/test/java/lang/module/ModuleReader/MultiReleaseJarTest.java
jdk/test/java/net/URLPermission/nstest/lookup.sh
jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/MyResources_ja_JP.properties
jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThowableHelper.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/EditPad.java
langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ExternalEditor.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIDefaultExecutionControl.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIExecutionControl.java
langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIInitiator.java
langtools/test/jdk/jshell/EditorPadTest.java
langtools/test/jdk/jshell/JDILaunchingExecutionControlTest.java
langtools/test/jdk/jshell/JDIListeningExecutionControlTest.java
langtools/test/jdk/jshell/JDIListeningLocalhostExecutionControlTest.java
langtools/test/jdk/jshell/UserJDIUserRemoteTest.java
langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java
langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java
langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java
langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java
langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java
langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java
langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java
langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java
langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java
nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CompositeOperation.java
--- a/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 65477538bec32963dc41153d89c4417eb46c45fc jdk-9+139
 0875007901f7d364a08220b052f0c81003e9c8c5 jdk-9+140
 9aadd2163b568d76f8969ad2fb404a63733da359 jdk-9+141
+df0e03e3ca0ed1307793017dfc1a054c8726131c jdk-9+142
+d62173b931bf5b6bffc6e80a9060bb2e8b8efc75 jdk-9+143
--- a/.hgtags-top-repo	Mon Nov 14 11:15:43 2016 +0100
+++ b/.hgtags-top-repo	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 7dcf453eacae79ee86a6bcc75fd0b546fc99b48a jdk-9+139
 a5815c6098a241d3a1df64d22b84b3524e4a77df jdk-9+140
 f64afae7f1a5608e438585bbf0bc23785e69cba0 jdk-9+141
+2b3e5caafe3594ea507c37675c4d3086f415dc64 jdk-9+142
+1fc62b1c629fb80fdaa639d3b59452a184f0d705 jdk-9+143
--- a/common/autoconf/flags.m4	Mon Nov 14 11:15:43 2016 +0100
+++ b/common/autoconf/flags.m4	Fri Nov 11 16:44:36 2016 +0100
@@ -280,7 +280,7 @@
     else
       # Default works for linux, might work on other platforms as well.
       SHARED_LIBRARY_FLAGS='-shared'
-      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1'
+      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1'
       SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
       SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
@@ -305,7 +305,7 @@
       # Default works for linux, might work on other platforms as well.
       PICFLAG='-fPIC'
       SHARED_LIBRARY_FLAGS='-shared'
-      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN[$]1'
+      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN[$]1'
       SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Wl,-soname=[$]1'
       SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=[$]1'
@@ -315,7 +315,7 @@
     C_FLAG_REORDER='-xF'
     CXX_FLAG_REORDER='-xF'
     SHARED_LIBRARY_FLAGS="-G"
-    SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN[$]1'
+    SET_EXECUTABLE_ORIGIN='-R\$$ORIGIN[$]1'
     SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
     SET_SHARED_LIBRARY_NAME='-h [$]1'
     SET_SHARED_LIBRARY_MAPFILE='-M[$]1'
@@ -759,6 +759,10 @@
         # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing
         $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing"
         ;;
+      s390 )
+        $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer -mbackchain -march=z10"
+        $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing"
+        ;;
       * )
         $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer"
         $2CFLAGS_JDK="${$2CFLAGS_JDK} -fno-strict-aliasing"
@@ -940,6 +944,10 @@
       # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
       $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mcpu=power7 -mtune=power8"
     fi
+  elif test "x$OPENJDK_$1_CPU" = xs390x; then
+    if test "x$OPENJDK_$1_OS" = xlinux; then
+      $2JVM_CFLAGS="[$]$2JVM_CFLAGS -mbackchain -march=z10"
+    fi
   fi
 
   if test "x$OPENJDK_$1_CPU_ENDIAN" = xlittle; then
@@ -999,6 +1007,7 @@
 
   # Setup some hard coded includes
   $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK \
+      -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
       -I${JDK_TOPDIR}/src/java.base/share/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_$1_OS_TYPE/native/include \
--- a/common/autoconf/generated-configure.sh	Mon Nov 14 11:15:43 2016 +0100
+++ b/common/autoconf/generated-configure.sh	Fri Nov 11 16:44:36 2016 +0100
@@ -5093,7 +5093,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1477108079
+DATE_WHEN_GENERATED=1478524503
 
 ###############################################################################
 #
@@ -49070,7 +49070,7 @@
     else
       # Default works for linux, might work on other platforms as well.
       SHARED_LIBRARY_FLAGS='-shared'
-      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1'
+      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN$1'
       SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1'
       SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1'
@@ -49095,7 +49095,7 @@
       # Default works for linux, might work on other platforms as well.
       PICFLAG='-fPIC'
       SHARED_LIBRARY_FLAGS='-shared'
-      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$$$ORIGIN$1'
+      SET_EXECUTABLE_ORIGIN='-Wl,-rpath,\$$ORIGIN$1'
       SET_SHARED_LIBRARY_ORIGIN="-Wl,-z,origin $SET_EXECUTABLE_ORIGIN"
       SET_SHARED_LIBRARY_NAME='-Wl,-soname=$1'
       SET_SHARED_LIBRARY_MAPFILE='-Wl,-version-script=$1'
@@ -49105,7 +49105,7 @@
     C_FLAG_REORDER='-xF'
     CXX_FLAG_REORDER='-xF'
     SHARED_LIBRARY_FLAGS="-G"
-    SET_EXECUTABLE_ORIGIN='-R\$$$$ORIGIN$1'
+    SET_EXECUTABLE_ORIGIN='-R\$$ORIGIN$1'
     SET_SHARED_LIBRARY_ORIGIN="$SET_EXECUTABLE_ORIGIN"
     SET_SHARED_LIBRARY_NAME='-h $1'
     SET_SHARED_LIBRARY_MAPFILE='-M$1'
@@ -49840,6 +49840,10 @@
         # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing
         CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
         ;;
+      s390 )
+        COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer -mbackchain -march=z10"
+        CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
+        ;;
       * )
         COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer"
         CFLAGS_JDK="${CFLAGS_JDK} -fno-strict-aliasing"
@@ -50122,6 +50126,10 @@
       # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
       JVM_CFLAGS="$JVM_CFLAGS -mcpu=power7 -mtune=power8"
     fi
+  elif test "x$OPENJDK_TARGET_CPU" = xs390x; then
+    if test "x$OPENJDK_TARGET_OS" = xlinux; then
+      JVM_CFLAGS="$JVM_CFLAGS -mbackchain -march=z10"
+    fi
   fi
 
   if test "x$OPENJDK_TARGET_CPU_ENDIAN" = xlittle; then
@@ -50270,6 +50278,7 @@
 
   # Setup some hard coded includes
   COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK \
+      -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
       -I${JDK_TOPDIR}/src/java.base/share/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_TARGET_OS_TYPE/native/include \
@@ -50655,6 +50664,10 @@
         # on ppc we don't prevent gcc to omit frame pointer but do prevent strict aliasing
         OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing"
         ;;
+      s390 )
+        OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer -mbackchain -march=z10"
+        OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing"
+        ;;
       * )
         OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -fno-omit-frame-pointer"
         OPENJDK_BUILD_CFLAGS_JDK="${OPENJDK_BUILD_CFLAGS_JDK} -fno-strict-aliasing"
@@ -50937,6 +50950,10 @@
       # Use Power8, this is the first CPU to support PPC64 LE with ELFv2 ABI.
       OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mcpu=power7 -mtune=power8"
     fi
+  elif test "x$OPENJDK_BUILD_CPU" = xs390x; then
+    if test "x$OPENJDK_BUILD_OS" = xlinux; then
+      OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -mbackchain -march=z10"
+    fi
   fi
 
   if test "x$OPENJDK_BUILD_CPU_ENDIAN" = xlittle; then
@@ -51085,6 +51102,7 @@
 
   # Setup some hard coded includes
   OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK \
+      -I\$(SUPPORT_OUTPUTDIR)/modules_include/java.base \
       -I${JDK_TOPDIR}/src/java.base/share/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS/native/include \
       -I${JDK_TOPDIR}/src/java.base/$OPENJDK_BUILD_OS_TYPE/native/include \
--- a/common/autoconf/spec.gmk.in	Mon Nov 14 11:15:43 2016 +0100
+++ b/common/autoconf/spec.gmk.in	Fri Nov 11 16:44:36 2016 +0100
@@ -265,6 +265,10 @@
 BUNDLES_OUTPUTDIR=$(BUILD_OUTPUT)/bundles
 TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
 MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
+
+# By default, output javadoc directly into image
+JAVADOC_OUTPUTDIR = $(DOCS_IMAGE_DIR)
+
 # This does not get overridden in a bootcycle build
 CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
 BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
@@ -784,11 +788,12 @@
 SYMBOLS_IMAGE_DIR=$(IMAGES_OUTPUTDIR)/$(SYMBOLS_IMAGE_SUBDIR)
 
 # Interim image
+INTERIM_JMODS_DIR := $(SUPPORT_OUTPUTDIR)/interim-jmods
 INTERIM_IMAGE_DIR := $(SUPPORT_OUTPUTDIR)/interim-image
 
 # Docs image
 DOCS_IMAGE_SUBDIR := docs
-DOCS_IMAGE_DIR := $(IMAGES_OUTPUTDIR)/$(DOCS_IMAGE_SUBDIR)
+DOCS_IMAGE_DIR = $(IMAGES_OUTPUTDIR)/$(DOCS_IMAGE_SUBDIR)
 
 # Macosx bundles directory definitions
 JDK_MACOSX_BUNDLE_SUBDIR=jdk-bundle
--- a/corba/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/corba/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 8c9da7fc5b07c606afd571c7012441b77dda83b2 jdk-9+139
 9f3fc931bc230f44f2a58d75f7f6360af98bb113 jdk-9+140
 b32f998da32b488ec7c4e9dbb3c750841b48e74d jdk-9+141
+408c9c621938ca028e20bced0459f815de47eba8 jdk-9+142
+6211236ef15ec796806357608b1dd1b70c258ece jdk-9+143
--- a/hotspot/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -544,3 +544,5 @@
 08492e67bf3226784dab3bf9ae967382ddbc1af5 jdk-9+139
 fec31089c2ef5a12dd64f401b0bf2e00f56ee0d0 jdk-9+140
 160a00bc6ed0af1fdf8418fc65e6bddbbc0c536d jdk-9+141
+7b48d63dfd6b8e2657288de3d7b1f153dee02d7e jdk-9+142
+d87d5d430c42342f0320ca7f5cbe0cbd1f9d62ba jdk-9+143
--- a/hotspot/make/gensrc/GensrcJvmti.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/make/gensrc/GensrcJvmti.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -135,14 +135,14 @@
 # Copy jvmti.h to include dir
 
 # The file is the same regardless of jvm variant. Only let one do the copy.
-#ifeq ($(JVM_VARIANT), $(firstword $(JVM_VARIANTS)))
-#  $(eval $(call SetupCopyFiles, COPY_JVMTI_H, \
-#      DEST := $(SUPPORT_OUTPUTDIR)/modules_include/java.base, \
-#      FILES := $(JVMTI_OUTPUTDIR)/jvmti.h, \
-#  ))
+ifeq ($(JVM_VARIANT), $(firstword $(JVM_VARIANTS)))
+  $(eval $(call SetupCopyFiles, COPY_JVMTI_H, \
+      DEST := $(SUPPORT_OUTPUTDIR)/modules_include/java.base, \
+      FILES := $(JVMTI_OUTPUTDIR)/jvmti.h, \
+  ))
 
-#  TARGETS += $(COPY_JVMTI_H)
-#endif
+  TARGETS += $(COPY_JVMTI_H)
+endif
 
 ################################################################################
 # Create trace files in gensrc/tracefiles
--- a/hotspot/make/symbols/symbols-unix	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/make/symbols/symbols-unix	Fri Nov 11 16:44:36 2016 +0100
@@ -125,7 +125,6 @@
 JVM_GetProtectionDomain
 JVM_GetSimpleBinaryName
 JVM_GetStackAccessControlContext
-JVM_GetStackTraceElements
 JVM_GetSystemPackage
 JVM_GetSystemPackages
 JVM_GetTemporaryDirectory
@@ -135,6 +134,8 @@
 JVM_HoldsLock
 JVM_IHashCode
 JVM_InitProperties
+JVM_InitStackTraceElement
+JVM_InitStackTraceElementArray
 JVM_InternString
 JVM_Interrupt
 JVM_InvokeMethod
@@ -178,7 +179,6 @@
 JVM_StopThread
 JVM_SupportsCX8
 JVM_SuspendThread
-JVM_ToStackTraceElement
 JVM_TotalMemory
 JVM_UnloadLibrary
 JVM_WaitForReferencePendingList
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Fri Nov 11 16:44:36 2016 +0100
@@ -2175,6 +2175,14 @@
   const char* str = holder->external_name();
   oop classname = StringTable::intern((char*) str, CHECK);
   java_lang_StackTraceElement::set_declaringClass(element(), classname);
+  java_lang_StackTraceElement::set_declaringClassObject(element(), holder->java_mirror());
+
+  oop loader = holder->class_loader();
+  if (loader != NULL) {
+    oop loader_name = java_lang_ClassLoader::name(loader);
+    if (loader_name != NULL)
+      java_lang_StackTraceElement::set_classLoaderName(element(), loader_name);
+  }
 
   // The method can be NULL if the requested class version is gone
   Symbol* sym = !method.is_null() ? method->name() : holder->constants()->symbol_at(cpref);
@@ -3433,6 +3441,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::name_offset = -1;
 int  java_lang_ClassLoader::unnamedModule_offset = -1;
 
 ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
@@ -3453,6 +3462,9 @@
   compute_optional_offset(parallelCapable_offset,
     k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
 
+  compute_offset(name_offset,
+    k1, vmSymbols::name_name(), vmSymbols::string_signature());
+
   compute_offset(unnamedModule_offset,
     k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
 
@@ -3464,6 +3476,11 @@
   return loader->obj_field(parent_offset);
 }
 
+oop java_lang_ClassLoader::name(oop loader) {
+  assert(is_instance(loader), "loader must be oop");
+  return loader->obj_field(name_offset);
+}
+
 bool java_lang_ClassLoader::isAncestor(oop loader, oop cl) {
   assert(is_instance(loader), "loader must be oop");
   assert(cl == NULL || is_instance(cl), "cl argument must be oop");
@@ -3619,12 +3636,14 @@
 int java_lang_System::static_out_offset;
 int java_lang_System::static_err_offset;
 int java_lang_System::static_security_offset;
-int java_lang_StackTraceElement::declaringClass_offset;
 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_StackTraceElement::classLoaderName_offset;
+int java_lang_StackTraceElement::declaringClass_offset;
+int java_lang_StackTraceElement::classOrLoaderModuleClassName_offset;
 int java_lang_StackFrameInfo::_declaringClass_offset;
 int java_lang_StackFrameInfo::_memberName_offset;
 int java_lang_StackFrameInfo::_bci_offset;
@@ -3669,6 +3688,14 @@
   element->obj_field_put(moduleVersion_offset, value);
 }
 
+void java_lang_StackTraceElement::set_classLoaderName(oop element, oop value) {
+  element->obj_field_put(classLoaderName_offset, value);
+}
+
+void java_lang_StackTraceElement::set_declaringClassObject(oop element, oop value) {
+  element->obj_field_put(classOrLoaderModuleClassName_offset, value);
+}
+
 // Support for java_lang_StackFrameInfo
 void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
   element->obj_field_put(_declaringClass_offset, value);
@@ -3784,6 +3811,8 @@
   java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
 
   // java_lang_StackTraceElement
+  java_lang_StackTraceElement::classOrLoaderModuleClassName_offset= java_lang_StackTraceElement::hc_classOrLoaderModuleClassName_offset* x + header;
+  java_lang_StackTraceElement::classLoaderName_offset = java_lang_StackTraceElement::hc_classLoaderName_offset * x + header;
   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;
@@ -3985,10 +4014,14 @@
 
   // java.lang.StackTraceElement
 
-  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass, "Ljava/lang/String;");
-  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName, "Ljava/lang/String;");
-  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement,   fileName, "Ljava/lang/String;");
-  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber, "I");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classOrLoaderModuleClassName, "Ljava/lang/Object;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, classLoaderName, "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleName,      "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, moduleVersion,   "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, declaringClass,  "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, methodName,      "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, fileName,        "Ljava/lang/String;");
+  CHECK_OFFSET("java/lang/StackTraceElement", java_lang_StackTraceElement, lineNumber,      "I");
 
   // java.lang.ref.Reference
 
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp	Fri Nov 11 16:44:36 2016 +0100
@@ -1225,6 +1225,7 @@
   static bool offsets_computed;
   static int parent_offset;
   static int parallelCapable_offset;
+  static int name_offset;
   static int unnamedModule_offset;
 
  public:
@@ -1234,6 +1235,7 @@
   static ClassLoaderData* loader_data(oop loader);
 
   static oop parent(oop loader);
+  static oop name(oop loader);
   static bool isAncestor(oop loader, oop cl);
 
   // Support for parallelCapable field
@@ -1291,14 +1293,18 @@
 class java_lang_StackTraceElement: AllStatic {
  private:
   enum {
-    hc_moduleName_offset = 0,
-    hc_moduleVersion_offset = 1,
-    hc_declaringClass_offset = 2,
-    hc_methodName_offset = 3,
-    hc_fileName_offset   = 4,
-    hc_lineNumber_offset = 5
+    hc_classOrLoaderModuleClassName_offset = 0,
+    hc_classLoaderName_offset      = 1,
+    hc_moduleName_offset           = 2,
+    hc_moduleVersion_offset        = 3,
+    hc_declaringClass_offset       = 4,
+    hc_methodName_offset           = 5,
+    hc_fileName_offset             = 6,
+    hc_lineNumber_offset           = 7
   };
 
+  static int classOrLoaderModuleClassName_offset;
+  static int classLoaderName_offset;
   static int moduleName_offset;
   static int moduleVersion_offset;
   static int declaringClass_offset;
@@ -1307,12 +1313,14 @@
   static int lineNumber_offset;
 
   // Setters
+  static void set_classLoaderName(oop element, oop value);
   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);
   static void set_lineNumber(oop element, int value);
+  static void set_declaringClassObject(oop element, oop value);
 
  public:
   // Create an instance of StackTraceElement
--- a/hotspot/src/share/vm/prims/jvm.cpp	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Fri Nov 11 16:44:36 2016 +0100
@@ -503,16 +503,27 @@
 JVM_END
 
 
-JVM_ENTRY(void, JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray stackTrace))
-  JVMWrapper("JVM_GetStackTraceElements");
+// java.lang.StackTraceElement //////////////////////////////////////////////
+
+
+JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable))
+  JVMWrapper("JVM_InitStackTraceElementArray");
   Handle exception(THREAD, JNIHandles::resolve(throwable));
-  objArrayOop st = objArrayOop(JNIHandles::resolve(stackTrace));
+  objArrayOop st = objArrayOop(JNIHandles::resolve(elements));
   objArrayHandle stack_trace(THREAD, st);
   // Fill in the allocated stack trace
   java_lang_Throwable::get_stack_trace_elements(exception, stack_trace, CHECK);
 JVM_END
 
 
+JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo))
+  JVMWrapper("JVM_InitStackTraceElement");
+  Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo));
+  Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(element));
+  java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD);
+JVM_END
+
+
 // java.lang.StackWalker //////////////////////////////////////////////////////
 
 
@@ -566,13 +577,6 @@
                                    start_index, frames_array_h, THREAD);
 JVM_END
 
-JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack))
-  JVMWrapper("JVM_ToStackTraceElement");
-  Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(frame));
-  Handle stack_trace_element(THREAD, JNIHandles::resolve_non_null(stack));
-  java_lang_StackFrameInfo::to_stack_trace_element(stack_frame_info, stack_trace_element, THREAD);
-JVM_END
-
 // java.lang.Object ///////////////////////////////////////////////
 
 
--- a/hotspot/src/share/vm/prims/jvm.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/hotspot/src/share/vm/prims/jvm.h	Fri Nov 11 16:44:36 2016 +0100
@@ -189,8 +189,14 @@
 JNIEXPORT void JNICALL
 JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
 
+/*
+ * java.lang.StackTraceElement
+ */
 JNIEXPORT void JNICALL
-JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements);
+JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable);
+
+JNIEXPORT void JNICALL
+JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo);
 
 /*
  * java.lang.StackWalker
@@ -212,9 +218,6 @@
                   jint frame_count, jint start_index,
                   jobjectArray frames);
 
-JNIEXPORT void JNICALL
-JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement);
-
 /*
  * java.lang.Thread
  */
--- a/jaxp/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 8991d71c5316bde259e6a417c1199b008ca3cdf0 jdk-9+139
 8d100cb9b04819b5bd09f33c7fd5b8628d1a456f jdk-9+140
 037c095ba0c345edbeaaab52fda913a76c3930c0 jdk-9+141
+bdafa0cc34a97a2f8db4847a4efd34b407943591 jdk-9+142
+ce81d03ad7320dca3d673374c1a33bc0efd9136a jdk-9+143
--- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -746,42 +746,18 @@
             // scan XMLDecl
             try {
                 if (fEntityScanner.skipString(xmlDecl)) {
-                    fMarkupDepth++;
-                    // NOTE: special case where document starts with a PI
-                    //       whose name starts with "xml" (e.g. "xmlfoo")
-                    if (XMLChar.isName(fEntityScanner.peekChar())) {
-                        fStringBuffer.clear();
-                        fStringBuffer.append("xml");
-                        while (XMLChar.isName(fEntityScanner.peekChar())) {
-                            fStringBuffer.append((char)fEntityScanner.scanChar(null));
-                        }
-                        String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
-                        //this function should fill the data.. and set the fEvent object to this event.
-                        fContentBuffer.clear() ;
-                        scanPIData(target, fContentBuffer);
-                        //REVISIT:where else we can set this value to 'true'
-                        fEntityManager.fCurrentEntity.mayReadChunks = true;
-                        //return PI event since PI was encountered
-                        return XMLEvent.PROCESSING_INSTRUCTION ;
+                    if (fEntityScanner.peekChar() == ' ') {
+                        fMarkupDepth++;
+                        scanXMLDeclOrTextDecl(false);
+                    } else {
+                        // PI, reset position
+                        fEntityManager.fCurrentEntity.position = 0;
                     }
-                    // standard XML declaration
-                    else {
-                        scanXMLDeclOrTextDecl(false);
-                        //REVISIT:where else we can set this value to 'true'
-                        fEntityManager.fCurrentEntity.mayReadChunks = true;
-                        return XMLEvent.START_DOCUMENT;
-                    }
-                } else{
-                    //REVISIT:where else we can set this value to 'true'
-                    fEntityManager.fCurrentEntity.mayReadChunks = true;
-                    //In both case return the START_DOCUMENT. ony difference is that first block will
-                    //cosume the XML declaration if any.
-                    return XMLEvent.START_DOCUMENT;
                 }
 
-
                 //START_OF_THE_DOCUMENT
-
+                fEntityManager.fCurrentEntity.mayReadChunks = true;
+                return XMLEvent.START_DOCUMENT;
 
             }
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLEventReader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -46,7 +46,10 @@
  */
 public interface XMLEventReader extends Iterator {
   /**
-   * Get the next XMLEvent
+   * Gets the next XMLEvent. The initial event is
+   * {@link javax.xml.stream.events.StartDocument StartDocument}.
+   *
+   * @return the next XMLEvent
    * @see XMLEvent
    * @throws XMLStreamException if there is an error with the underlying XML.
    * @throws java.util.NoSuchElementException iteration has no more elements.
@@ -58,12 +61,15 @@
    * Returns true if there are more events and false otherwise.
    * @return true if the event reader has more events, false otherwise
    */
+  @Override
   public boolean hasNext();
 
   /**
    * Check the next XMLEvent without reading it from the stream.
    * Returns null if the stream is at EOF or has no more XMLEvents.
    * A call to peek() will be equal to the next return of next().
+   *
+   * @return the next XMLEvent
    * @see XMLEvent
    * @throws XMLStreamException
    */
@@ -73,6 +79,8 @@
    * Reads the content of a text-only element. Precondition:
    * the current event is START_ELEMENT. Postcondition:
    * The current event is the corresponding END_ELEMENT.
+   *
+   * @return the text of the element
    * @throws XMLStreamException if the current event is not a START_ELEMENT
    * or if a non text element is encountered
    */
@@ -85,6 +93,8 @@
    * be used when processing element-only content because
    * the parser is not able to recognize ignorable whitespace if
    * the DTD is missing or not interpreted.
+   *
+   * @return a START_ELEMENT or END_ELEMENT
    * @throws XMLStreamException if anything other than space characters are encountered
    */
   public XMLEvent nextTag() throws XMLStreamException;
--- a/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/src/java.xml/share/classes/javax/xml/stream/XMLStreamReader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,7 +28,6 @@
 
 package javax.xml.stream;
 
-import java.io.Reader;
 import javax.xml.namespace.NamespaceContext;
 import javax.xml.namespace.QName;
 
@@ -37,19 +36,26 @@
  *  It is designed to be the lowest level and most efficient way to
  *  read XML data.
  *
- * <p> The XMLStreamReader is designed to iterate over XML using
+ * <p>
+ * The XMLStreamReader is designed to iterate over XML using
  * next() and hasNext().  The data can be accessed using methods such as getEventType(),
  * getNamespaceURI(), getLocalName() and getText();
  *
- * <p> The <a href="#next()">next()</a> method causes the reader to read the next parse event.
- * The next() method returns an integer which identifies the type of event just read.
- * <p> The event type can be determined using <a href="#getEventType()">getEventType()</a>.
- * <p> Parsing events are defined as the XML Declaration, a DTD,
+ * <p>
+ * An XMLStreamReader instance is created with an initial event type START_DOCUMENT.
+ * At any moment in time, it has a current event that the methods of the interface
+ * access and may load the next event through the {@link #next() next()} method.
+ * The current event type can be determined by {@link #getEventType getEventType()}, and
+ * the next returned by the {@link #next() next()} method.
+ *
+ * <p>
+ * Parsing events are defined as the XML Declaration, a DTD,
  * start tag, character data, white space, end tag, comment,
  * or processing instruction.  An attribute or namespace event may be encountered
  * at the root level of a document as the result of a query operation.
  *
- * <p>For XML 1.0 compliance an XML processor must pass the
+ * <p>
+ * For XML 1.0 compliance an XML processor must pass the
  * identifiers of declared unparsed entities, notation declarations and their
  * associated identifiers to the application.  This information is
  * provided through the property API on this interface.
@@ -63,7 +69,8 @@
  * These properties can only be accessed during a DTD event and
  * are defined to return null if the information is not available.
  *
- * <p>The following table describes which methods are valid in what state.
+ * <p>
+ * The following table describes which methods are valid in what state.
  * If a method is called in an invalid state the method will throw a
  * java.lang.IllegalStateException.
  *
@@ -502,8 +509,10 @@
   //  public void recycle() throws XMLStreamException;
 
   /**
-   * Returns an integer code that indicates the type
-   * of the event the cursor is pointing to.
+   * Returns an integer code that indicates the type of the event the cursor is
+   * pointing to. The initial event type is {@link #START_DOCUMENT}.
+   *
+   * @return the type of the current event
    */
   public int getEventType();
 
@@ -590,6 +599,8 @@
   /**
    * Returns the offset into the text character array where the first
    * character (of this text event) is stored.
+   *
+   * @return the starting position of the text in the character array
    * @throws java.lang.IllegalStateException if this state is not
    * a valid text state.
    */
@@ -598,6 +609,8 @@
   /**
    * Returns the length of the sequence of characters for this
    * Text event within the text character array.
+   *
+   * @return the length of the text
    * @throws java.lang.IllegalStateException if this state is not
    * a valid text state.
    */
@@ -610,9 +623,11 @@
   public String getEncoding();
 
   /**
-   * Return true if the current event has text, false otherwise
+   * Return a boolean indicating whether the current event has text.
    * The following events have text:
    * CHARACTERS,DTD ,ENTITY_REFERENCE, COMMENT, SPACE
+   *
+   * @return true if the event has text, false otherwise
    */
   public boolean hasText();
 
@@ -623,6 +638,7 @@
    * location and null for the publicId and systemId.
    * The location information is only valid until next() is
    * called.
+   * @return the location of the cursor
    */
   public Location getLocation();
 
@@ -647,8 +663,10 @@
   public String getLocalName();
 
   /**
-   * returns true if the current event has a name (is a START_ELEMENT or END_ELEMENT)
-   * returns false otherwise
+   * returns a boolean indicating whether the current event has a name
+   * (is a START_ELEMENT or END_ELEMENT).
+   *
+   * @return true if the event has a name, false otherwise
    */
   public boolean hasName();
 
--- a/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/test/javax/xml/jaxp/functional/javax/xml/parsers/ptests/SAXParserTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,20 +24,16 @@
 package javax.xml.parsers.ptests;
 
 import static javax.xml.parsers.ptests.ParserTestConst.XML_DIR;
-import static jaxp.library.JAXPTestUtilities.USER_DIR;
 import static jaxp.library.JAXPTestUtilities.tryRunWithTmpPermission;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FilePermission;
 import java.io.IOException;
 import java.util.PropertyPermission;
 
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 
-import jaxp.library.JAXPTestUtilities;
-
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
@@ -189,8 +185,7 @@
      */
     @Test(expectedExceptions = { SAXException.class, IOException.class }, dataProvider = "parser-provider")
     public void testParse09(SAXParser saxparser) throws Exception {
-        JAXPTestUtilities.tryRunWithTmpPermission(() -> saxparser.parse(" ", new DefaultHandler()),
-                new FilePermission(USER_DIR + " ", "read"));
+        saxparser.parse("no-such-file", new DefaultHandler());
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import javax.xml.catalog.CatalogFeatures;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+/*
+ * @test
+ * @bug 8151154
+ * @run testng/othervm catalog.CatalogInvalidPathTest
+ * @summary Verifies that the CatalogFeatures' builder throws
+ *          IllegalArgumentException on invalid file inputs.
+ *          This test was splitted from CatalogTest.java due to
+ *          JDK-8168968, it has to only run without SecurityManager
+ *          because an ACE will be thrown for invalid path.
+ */
+public class CatalogInvalidPathTest {
+    /*
+       DataProvider: for testing the verification of file paths by
+                     the CatalogFeatures builder
+     */
+    @DataProvider(name = "invalidPaths")
+    public Object[][] getFiles() {
+        return new Object[][]{
+            {null},
+            {""},
+            {"file:a/b\\c"},
+            {"file:/../../.."},
+            {"c:/te:t"},
+            {"c:/te?t"},
+            {"c/te*t"},
+            {"in|valid.txt"},
+            {"shema:invalid.txt"},
+        };
+    }
+
+    @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class)
+    public void testFileInput(String file) {
+        CatalogFeatures features = CatalogFeatures.builder()
+            .with(CatalogFeatures.Feature.FILES, file)
+            .build();
+    }
+}
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,18 +23,16 @@
 package catalog;
 
 import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
-import static jaxp.library.JAXPTestUtilities.getSystemProperty;
 import static jaxp.library.JAXPTestUtilities.setSystemProperty;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FilePermission;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.nio.file.Paths;
-import java.util.PropertyPermission;
+
 import javax.xml.XMLConstants;
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogException;
@@ -57,7 +55,6 @@
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
-import jaxp.library.JAXPTestUtilities;
 
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
@@ -73,7 +70,7 @@
 
 /*
  * @test
- * @bug 8081248 8144966 8146606 8146237 8151154 8150969 8151162 8152527 8154220 8163232
+ * @bug 8081248 8144966 8146606 8146237 8150969 8151162 8152527 8154220 8163232
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng/othervm -DrunSecMngr=true catalog.CatalogTest
  * @run testng/othervm catalog.CatalogTest
@@ -459,21 +456,6 @@
         Catalog catalog = CatalogManager.catalog(features, catalogFile);
     }
 
-    /**
-     * @bug 8151154
-     * Verifies that the CatalogFeatures' builder throws IllegalArgumentException
-     * on invalid file inputs.
-     * @param file the file path
-     */
-    @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class)
-    public void testFileInput(String file) {
-        JAXPTestUtilities.runWithTmpPermission(() -> {
-            CatalogFeatures features = CatalogFeatures.builder()
-                .with(CatalogFeatures.Feature.FILES, file)
-                .build();
-        }, new FilePermission("/../../..", "read"), new FilePermission("c:\\te:t", "read"),
-                new FilePermission("c:\\te?t", "read"), new PropertyPermission("user.dir", "read"));
-    }
 
     /**
      * @bug 8146237
@@ -736,24 +718,6 @@
         };
     }
 
-    /*
-       DataProvider: for testing the verification of file paths by
-                     the CatalogFeatures builder
-     */
-    @DataProvider(name = "invalidPaths")
-    public Object[][] getFiles() {
-        return new Object[][]{
-            {null},
-            {""},
-            {"file:a/b\\c"},
-            {"file:/../../.."},
-            {"c:/te:t"},
-            {"c:/te?t"},
-            {"c/te*t"},
-            {"in|valid.txt"},
-            {"shema:invalid.txt"},
-        };
-    }
 
     /*
        DataProvider: provides test name, expected string, the catalog, and XML
--- a/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/BugTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxp/test/javax/xml/jaxp/unittest/stream/XMLStreamReaderTest/BugTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -24,17 +24,20 @@
 package stream.XMLStreamReaderTest;
 
 import java.io.StringReader;
+import javax.xml.stream.XMLEventReader;
 
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamReader;
 
 import org.testng.Assert;
+import org.testng.annotations.DataProvider;
 import org.testng.annotations.Listeners;
 import org.testng.annotations.Test;
 
 /*
  * @test
+ * @bug 8069098
  * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
  * @run testng/othervm -DrunSecMngr=true stream.XMLStreamReaderTest.BugTest
  * @run testng/othervm stream.XMLStreamReaderTest.BugTest
@@ -43,11 +46,70 @@
 @Listeners({jaxp.library.BasePolicy.class})
 public class BugTest {
 
-    @Test
-    public static void test1() throws Exception {
-        XMLInputFactory xif = XMLInputFactory.newInstance(); // new
-                                                             // com.sun.xml.stream.ZephyrParserFactory();
-        XMLStreamReader r = xif.createXMLStreamReader(new StringReader("<foo/>"));
-        Assert.assertEquals(XMLStreamConstants.START_DOCUMENT, r.getEventType());
+    /**
+     * Verifies that the initial event of an XMLStreamReader instance is
+     * START_DOCUMENT.
+     *
+     * @param xml the xml input
+     * @param type1 the type of the 1st event
+     * @param type2 the type of the 2nd event
+     * @throws Exception if the test fails to run properly
+     */
+    @Test(dataProvider = "xmls")
+    public static void test1(String xml, int type1, int type2) throws Exception {
+       XMLInputFactory factory = XMLInputFactory.newFactory();
+
+       XMLStreamReader reader = factory.createXMLStreamReader(new StringReader(xml));
+       int type1stEvent = reader.getEventType();
+       int type2ndEvent = reader.next();
+       System.out.println("First event: " + type1stEvent);
+       System.out.println("2nd event: " + type2ndEvent);
+       Assert.assertEquals(type1, type1stEvent);
+       Assert.assertEquals(type2, type2ndEvent);
+    }
+
+
+    /**
+     * Verifies that the initial event of an XMLEventReader instance is
+     * START_DOCUMENT. XMLEventReader depends on XMLStreamReader.
+     *
+     * @param xml the xml input
+     * @param type1 the type of the 1st event
+     * @param type2 the type of the 2nd event
+     * @throws Exception if the test fails to run properly
+     */
+    @Test(dataProvider = "xmls")
+    public static void test2(String xml, int type1, int type2) throws Exception {
+       XMLInputFactory factory = XMLInputFactory.newFactory();
+
+       XMLEventReader reader = factory.createXMLEventReader(new StringReader(xml));
+       int type1stEvent = reader.nextEvent().getEventType();
+       int type2ndEvent = reader.nextEvent().getEventType();
+       System.out.println("First event: " + type1stEvent);
+       System.out.println("2nd event: " + type2ndEvent);
+       Assert.assertEquals(type1, type1stEvent);
+       Assert.assertEquals(type2, type2ndEvent);
+    }
+
+    /*
+       DataProvider: for testing beginning event type
+       Data: xml, 1st event type, 2nd event type
+     */
+    @DataProvider(name = "xmls")
+    public Object[][] getXMLs() {
+
+        return new Object[][]{
+            {"<?xml version='1.0'?><foo/>",
+                XMLStreamConstants.START_DOCUMENT, XMLStreamConstants.START_ELEMENT},
+            {"<foo/>",
+                XMLStreamConstants.START_DOCUMENT, XMLStreamConstants.START_ELEMENT},
+            {"<?xml version='1.0'?>"
+                + "<?xml-stylesheet href=\"bar.xsl\" type=\"text/xsl\"?>" +
+                    "<foo/>",
+                XMLStreamConstants.START_DOCUMENT, XMLStreamConstants.PROCESSING_INSTRUCTION},
+            {"<?xml-stylesheet href=\"bar.xsl\" type=\"text/xsl\"?>" +
+                    "<foo/>",
+                XMLStreamConstants.START_DOCUMENT, XMLStreamConstants.PROCESSING_INSTRUCTION},
+        };
     }
 }
--- a/jaxws/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/jaxws/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -387,3 +387,5 @@
 7a7aadf3c4500cc273c889aa1172d4fe3844bb6b jdk-9+139
 9004617323fe99cbe4fad48f373cb2ed4fc50aa6 jdk-9+140
 b2c18f755228d1d19a86cd7d5fa1abb6b1495dfb jdk-9+141
+59101416d90160cfcb4f45dfbccaec15e2c27a29 jdk-9+142
+1c988e708a06257119d54d8a57e99e3b0f37ff18 jdk-9+143
--- a/jdk/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 5518ac2f2ead5e594bd983f2047178136aafdfd0 jdk-9+139
 e93b7ea559759f036c9f69fd2ddaf47bb4e98385 jdk-9+140
 8d752af5f61d41f226adf2cda72a20faa9ad620a jdk-9+141
+6ce43dd8e954b452f330dd7a412df5107f7e1923 jdk-9+142
+8dbc8594f9d5149bf1c22221272284609408227a jdk-9+143
--- a/jdk/make/GenerateClasslist.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-#
-# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-################################################################################
-# Generate classlist
-################################################################################
-
-default: all
-
-include $(SPEC)
-include MakeBase.gmk
-include Tools.gmk
-include JarArchive.gmk
-
-################################################################################
-# Create a jar with our generator class. Using a jar is intentional since it
-# will load more classes
-
-$(eval $(call SetupJarArchive, CLASSLIST_JAR, \
-    SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
-    INCLUDES := build/tools/classlist, \
-    JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \
-))
-
-TARGETS += $(CLASSLIST_JAR)
-
-################################################################################
-
-CLASSLIST_FILE := $(SUPPORT_OUTPUTDIR)/classlist/classlist
-
-JLI_TRACE_FILE := $(SUPPORT_OUTPUTDIR)/classlist/jli_trace.out
-
-# If an external buildjdk has been supplied, we don't build a separate interim
-# image, so just use the external build jdk instead.
-ifeq ($(EXTERNAL_BUILDJDK), true)
-  INTERIM_IMAGE_DIR := $(BUILD_JDK)
-endif
-
-$(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
-	$(call MakeDir, $(@D))
-	$(call LogInfo, Generating lib/classlist)
-	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
-	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
-	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
-	    build.tools.classlist.HelloClasslist \
-	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
-
-TARGETS += $(CLASSLIST_FILE)
-
-################################################################################
-
-all: $(TARGETS)
--- a/jdk/make/copy/Copy-java.base.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/copy/Copy-java.base.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,6 @@
 #
 TARGETS += \
     $(INCLUDE_DST_DIR)/jni.h \
-    $(INCLUDE_DST_DIR)/jvmti.h \
     $(INCLUDE_DST_DIR)/jvmticmlr.h \
     $(INCLUDE_DST_DIR)/classfile_constants.h \
     $(INCLUDE_DST_OS_DIR)/jni_md.h \
--- a/jdk/make/data/tzdata/VERSION	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/data/tzdata/VERSION	Fri Nov 11 16:44:36 2016 +0100
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2016g
+tzdata2016h
--- a/jdk/make/data/tzdata/asia	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/data/tzdata/asia	Fri Nov 11 16:44:36 2016 +0100
@@ -2567,11 +2567,6 @@
 # From Paul Eggert (2015-03-03):
 # http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
 # says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00.  This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # From Hannah Kreitem (2016-03-09):
 # http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2581,7 +2576,21 @@
 #
 # From Paul Eggert (2016-03-12):
 # Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
@@ -2610,9 +2619,10 @@
 Rule Palestine	2012	2014	-	Mar	lastThu	24:00	1:00	S
 Rule Palestine	2012	only	-	Sep	21	1:00	0	-
 Rule Palestine	2013	only	-	Sep	Fri>=21	0:00	0	-
-Rule Palestine	2014	max	-	Oct	Fri>=21	0:00	0	-
+Rule Palestine	2014	2015	-	Oct	Fri>=21	0:00	0	-
 Rule Palestine	2015	only	-	Mar	lastFri	24:00	1:00	S
 Rule Palestine	2016	max	-	Mar	lastSat	1:00	1:00	S
+Rule Palestine	2016	max	-	Oct	lastSat	1:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
@@ -2762,45 +2772,31 @@
 # People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
 # as that zone has agreed with the Tamil areas since our cutoff date of 1970.
 
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
 #
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators.  In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then  it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources.  I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources.  Our old abbreviation "LKT" is
+# even worse.  For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
 			5:19:32	-	MMT	1906        # Moratuwa Mean Time
-			5:30	-	IST	1942 Jan  5
-			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16  2:00
-			5:30	-	IST	1996 May 25  0:00
-			6:30	-	LKT	1996 Oct 26  0:30
-			6:00	-	LKT	2006 Apr 15  0:30
-			5:30	-	IST
+			5:30	-	+0530	1942 Jan  5
+			5:30	0:30	+0530/+06 1942 Sep
+			5:30	1:00	+0530/+0630 1945 Oct 16  2:00
+			5:30	-	+0530	1996 May 25  0:00
+			6:30	-	+0630	1996 Oct 26  0:30
+			6:00	-	+06	2006 Apr 15  0:30
+			5:30	-	+0530
 
 # Syria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
--- a/jdk/make/data/tzdata/australasia	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/data/tzdata/australasia	Fri Nov 11 16:44:36 2016 +0100
@@ -373,7 +373,13 @@
 # commencing at 2.00 am on Sunday 1st November, 2015 and ending at
 # 3.00 am on Sunday 17th January, 2016.
 
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am....  Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
 # For now, guess DST from 02:00 the first Sunday in November to
 # 03:00 the third Sunday in January.  Although ad hoc, it matches
 # transitions since late 2014 and seems more likely to match future
--- a/jdk/make/data/tzdata/europe	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/data/tzdata/europe	Fri Nov 11 16:44:36 2016 +0100
@@ -1931,7 +1931,7 @@
 # Amsterdam mean time.
 
 # The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/idl/idl.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -3450,22 +3450,24 @@
 
 # Turkey
 
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time.  I am not sure
-# what happened before that.  One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+#    no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf  - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf  - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf  - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf  - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf  - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf  - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf  - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf  - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf  - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2  - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2  - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
 
 # From Steffen Thorsen (2007-03-09):
 # Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3574,10 +3576,10 @@
 Rule	Turkey	1983	only	-	Oct	 2	0:00	0	-
 Rule	Turkey	1985	only	-	Apr	20	0:00	1:00	S
 Rule	Turkey	1985	only	-	Sep	28	0:00	0	-
-Rule	Turkey	1986	1990	-	Mar	lastSun	2:00s	1:00	S
-Rule	Turkey	1986	1990	-	Sep	lastSun	2:00s	0	-
-Rule	Turkey	1991	2006	-	Mar	lastSun	1:00s	1:00	S
-Rule	Turkey	1991	1995	-	Sep	lastSun	1:00s	0	-
+Rule	Turkey	1986	1993	-	Mar	lastSun	1:00s	1:00	S
+Rule	Turkey	1986	1995	-	Sep	lastSun	1:00s	0	-
+Rule	Turkey	1994	only	-	Mar	20	1:00s	1:00	S
+Rule	Turkey	1995	2006	-	Mar	lastSun	1:00s	1:00	S
 Rule	Turkey	1996	2006	-	Oct	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Istanbul	1:55:52 -	LMT	1880
--- a/jdk/make/data/tzdata/northamerica	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/data/tzdata/northamerica	Fri Nov 11 16:44:36 2016 +0100
@@ -47,8 +47,32 @@
 # was the result of his proposals at the Convention of Railroad Trunk Lines
 # in New York City (1869-10).  His 1870 proposal was based on Washington, DC,
 # but in 1872-05 he moved the proposed origin to Greenwich.
-# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
-# and the most of the country soon followed suit.
+
+# From Paul Eggert (2016-09-21):
+# Dowd's proposal left many details unresolved, such as where to draw
+# lines between time zones.  The key individual who made time zones
+# work in the US was William Frederick Allen - railway engineer,
+# managing editor of the Travelers' Guide, and secretary of the
+# General Time Convention, a railway standardization group.  Allen
+# spent months in dialogs with scientific and railway leaders,
+# developed a workable plan to institute time zones, and presented it
+# to the General Time Convention on 1883-04-11, saying that his plan
+# meant "local time would be practically abolished" - a plus for
+# railway scheduling.  By the next convention on 1883-10-11 nearly all
+# railroads had agreed and it took effect on 1883-11-18 at 12:00.
+# That Sunday was called the "day of two noons", as the eastern parts
+# of the new zones observed noon twice.  Allen witnessed the
+# transition in New York City, writing:
+#
+#   I heard the bells of St. Paul's strike on the old time.  Four
+#   minutes later, obedient to the electrical signal from the Naval
+#   Observatory ... the time-ball made its rapid descent, the chimes
+#   of old Trinity rang twelve measured strokes, and local time was
+#   abandoned, probably forever.
+#
+# Most of the US soon followed suit.  See:
+# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56.
+# http://dx.doi.org/10.2307/3105430
 
 # From Paul Eggert (2005-04-16):
 # That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
--- a/jdk/make/gendata/GendataBreakIterator.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/gendata/GendataBreakIterator.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -55,7 +55,6 @@
 $(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, \
--- a/jdk/make/mapfiles/libjava/mapfile-vers	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/mapfiles/libjava/mapfile-vers	Fri Nov 11 16:44:36 2016 +0100
@@ -140,7 +140,6 @@
 		Java_java_lang_Double_doubleToRawLongBits;
 		Java_java_lang_Float_intBitsToFloat;
 		Java_java_lang_Float_floatToRawIntBits;
-                Java_java_lang_StackFrameInfo_toStackTraceElement0;
                 Java_java_lang_StackStreamFactory_checkStackWalkModes;
                 Java_java_lang_StackStreamFactory_00024AbstractStackWalker_callStackWalk;
                 Java_java_lang_StackStreamFactory_00024AbstractStackWalker_fetchStackFrames;
@@ -215,6 +214,8 @@
 		Java_java_lang_SecurityManager_currentLoadedClass0;
 		Java_java_lang_SecurityManager_getClassContext;
 		Java_java_lang_Shutdown_halt0;
+                Java_java_lang_StackTraceElement_initStackTraceElement;
+                Java_java_lang_StackTraceElement_initStackTraceElements;
 		Java_java_lang_String_intern;
 		Java_java_lang_StringCoding_err;
 		Java_java_lang_StringUTF16_isBigEndian;
@@ -227,7 +228,6 @@
 		Java_java_lang_System_setOut0;
 		Java_java_lang_Thread_registerNatives;
 		Java_java_lang_Throwable_fillInStackTrace;
-                Java_java_lang_Throwable_getStackTraceElements;
 		Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2;
 		Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
 		Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2;
--- a/jdk/make/mapfiles/libjava/reorder-sparc	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/mapfiles/libjava/reorder-sparc	Fri Nov 11 16:44:36 2016 +0100
@@ -78,7 +78,7 @@
 text: .text%JNU_GetEnv;
 text: .text%Java_java_io_UnixFileSystem_checkAccess;
 text: .text%Java_java_lang_reflect_Array_newArray;
-text: .text%Java_java_lang_Throwable_getStackTraceElements;
+text: .text%Java_java_lang_StackTraceElement_initStackTraceElements;
 text: .text%throwFileNotFoundException;
 text: .text%JNU_NotifyAll;
 # Test LoadFrame
--- a/jdk/make/mapfiles/libjava/reorder-sparcv9	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/mapfiles/libjava/reorder-sparcv9	Fri Nov 11 16:44:36 2016 +0100
@@ -74,7 +74,7 @@
 text: .text%JNU_GetEnv;
 text: .text%Java_java_io_UnixFileSystem_checkAccess;
 text: .text%Java_java_lang_reflect_Array_newArray;
-text: .text%Java_java_lang_Throwable_getStackTraceElements;
+text: .text%Java_java_lang_StackTraceElement_initStackTraceElements;
 text: .text%throwFileNotFoundException: OUTPUTDIR/io_util.o;
 text: .text%JNU_NotifyAll;
 # Test LoadFrame
--- a/jdk/make/mapfiles/libjava/reorder-x86	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/mapfiles/libjava/reorder-x86	Fri Nov 11 16:44:36 2016 +0100
@@ -78,7 +78,7 @@
 text: .text%Java_sun_reflect_NativeMethodAccessorImpl_invoke0;
 text: .text%Java_java_io_FileInputStream_available;
 text: .text%Java_java_lang_reflect_Array_newArray;
-text: .text%Java_java_lang_Throwable_getStackTraceElements;
+text: .text%Java_java_lang_StackTraceElement_initStackTraceElements;
 text: .text%Java_java_lang_System_identityHashCode;
 text: .text%JNU_NotifyAll;
 # Test LoadFrame
--- a/jdk/make/mapfiles/libsplashscreen/mapfile-vers	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/mapfiles/libsplashscreen/mapfile-vers	Fri Nov 11 16:44:36 2016 +0100
@@ -44,6 +44,7 @@
         SplashSetFileJarName;
         SplashSetScaleFactor;
         SplashGetScaledImageName;
+        SplashGetScaledImgNameMaxPstfixLen;
     local:
         *;
 };
--- a/jdk/make/rmic/Rmic-java.rmi.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/make/rmic/Rmic-java.rmi.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,7 @@
 #
 
 $(eval $(call SetupRMICompilation,RMI_12, \
-    CLASSES := sun.rmi.server.Activation$$$$ActivationSystemImpl \
+    CLASSES := sun.rmi.server.Activation$$ActivationSystemImpl \
         java.rmi.activation.ActivationGroup, \
     CLASSES_DIR := $(CLASSES_DIR)/java.rmi, \
     STUB_CLASSES_DIR := $(STUB_CLASSES_DIR)/java.rmi, \
--- a/jdk/src/java.base/share/classes/java/io/File.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/File.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, 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
@@ -1907,16 +1907,10 @@
             throws IOException
         {
             long n = random.nextLong();
-            if (n == Long.MIN_VALUE) {
-                n = 0;      // corner case
-            } else {
-                n = Math.abs(n);
-            }
 
             // Use only the file name from the supplied prefix
             prefix = (new File(prefix)).getName();
-
-            String name = prefix + Long.toString(n) + suffix;
+            String name = prefix + Long.toUnsignedString(n) + suffix;
             File f = new File(dir, name);
             if (!name.equals(f.getName()) || f.isInvalid()) {
                 if (System.getSecurityManager() != null)
--- a/jdk/src/java.base/share/classes/java/io/FileInputStream.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/FileInputStream.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, 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
@@ -26,7 +26,6 @@
 package java.io;
 
 import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
 import sun.nio.ch.FileChannelImpl;
 
 
@@ -60,7 +59,9 @@
 
     private volatile FileChannel channel;
 
-    private final AtomicBoolean closed = new AtomicBoolean(false);
+    private final Object closeLock = new Object();
+
+    private volatile boolean closed;
 
     /**
      * Creates a <code>FileInputStream</code> by
@@ -313,14 +314,21 @@
      * @spec JSR-51
      */
     public void close() throws IOException {
-        if (!closed.compareAndSet(false, true)) {
-            // if compareAndSet() returns false closed was already true
+        if (closed) {
             return;
         }
+        synchronized (closeLock) {
+            if (closed) {
+                return;
+            }
+            closed = true;
+        }
 
         FileChannel fc = channel;
         if (fc != null) {
-           fc.close();
+            // possible race with getChannel(), benign since
+            // FileChannel.close is final and idempotent
+            fc.close();
         }
 
         fd.closeAll(new Closeable() {
@@ -370,8 +378,10 @@
                 fc = this.channel;
                 if (fc == null) {
                     this.channel = fc = FileChannelImpl.open(fd, path, true, false, this);
-                    if (closed.get()) {
+                    if (closed) {
                         try {
+                            // possible race with close(), benign since
+                            // FileChannel.close is final and idempotent
                             fc.close();
                         } catch (IOException ioe) {
                             throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, 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
@@ -26,7 +26,6 @@
 package java.io;
 
 import java.nio.channels.FileChannel;
-import java.util.concurrent.atomic.AtomicBoolean;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.JavaIOFileDescriptorAccess;
 import sun.nio.ch.FileChannelImpl;
@@ -77,7 +76,9 @@
      */
     private final String path;
 
-    private final AtomicBoolean closed = new AtomicBoolean(false);
+    private final Object closeLock = new Object();
+
+    private volatile boolean closed;
 
     /**
      * Creates a file output stream to write to the file with the
@@ -341,14 +342,21 @@
      * @spec JSR-51
      */
     public void close() throws IOException {
-        if (!closed.compareAndSet(false, true)) {
-            // if compareAndSet() returns false closed was already true
+        if (closed) {
             return;
         }
+        synchronized (closeLock) {
+            if (closed) {
+                return;
+            }
+            closed = true;
+        }
 
         FileChannel fc = channel;
         if (fc != null) {
-           fc.close();
+            // possible race with getChannel(), benign since
+            // FileChannel.close is final and idempotent
+            fc.close();
         }
 
         fd.closeAll(new Closeable() {
@@ -399,8 +407,10 @@
                 fc = this.channel;
                 if (fc == null) {
                     this.channel = fc = FileChannelImpl.open(fd, path, false, true, this);
-                    if (closed.get()) {
+                    if (closed) {
                         try {
+                            // possible race with close(), benign since
+                            // FileChannel.close is final and idempotent
                             fc.close();
                         } catch (IOException ioe) {
                             throw new InternalError(ioe); // should not happen
--- a/jdk/src/java.base/share/classes/java/io/FilePermission.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java	Fri Nov 11 16:44:36 2016 +0100
@@ -173,6 +173,7 @@
     private transient Path npath;       // normalized dir path.
     private transient Path npath2;      // alternative normalized dir path.
     private transient boolean allFiles; // whether this is <<ALL FILES>>
+    private transient boolean invalid;  // whether input path is invalid
 
     // static Strings used by init(int mask)
     private static final char RECURSIVE_CHAR = '-';
@@ -218,11 +219,12 @@
      * A private constructor like a clone, only npath2 is not touched.
      * @param input
      */
-    private FilePermission(FilePermission input) {
-        super(input.getName());
+    private FilePermission(String name, FilePermission input) {
+        super(name);
         this.npath = input.npath;
         this.actions = input.actions;
         this.allFiles = input.allFiles;
+        this.invalid = input.invalid;
         this.recursive = input.recursive;
         this.directory = input.directory;
         this.cpath = input.cpath;
@@ -255,7 +257,12 @@
                     if (input.npath2 == null && !input.allFiles) {
                         Path npath2 = altPath(input.npath);
                         if (npath2 != null) {
-                            FilePermission np = new FilePermission(input);
+                            // Please note the name of the new permission is
+                            // different than the original so that when one is
+                            // added to a FilePermissionCollection it will not
+                            // be merged with the original one.
+                            FilePermission np = new FilePermission(
+                                    input.getName()+"#plus", input);
                             np.npath2 = npath2;
                             return np;
                         }
@@ -266,7 +273,9 @@
                     if (!input.allFiles) {
                         Path npath2 = altPath(input.npath);
                         if (npath2 != null) {
-                            FilePermission np = new FilePermission(input);
+                            // New name, see above.
+                            FilePermission np = new FilePermission(
+                                    input.getName()+"#using", input);
                             np.npath = npath2;
                             return np;
                         }
@@ -318,11 +327,12 @@
                 // Windows. Some JDK codes generate such illegal names.
                 npath = builtInFS.getPath(new File(name).getPath())
                         .normalize();
+                invalid = false;
             } catch (InvalidPathException ipe) {
                 // Still invalid. For compatibility reason, accept it
                 // but make this permission useless.
                 npath = builtInFS.getPath("-u-s-e-l-e-s-s-");
-                this.mask = NONE;
+                invalid = true;
             }
 
             // lastName should always be non-null now
@@ -540,6 +550,12 @@
      */
     boolean impliesIgnoreMask(FilePermission that) {
         if (FilePermCompat.nb) {
+            if (this == that) {
+                return true;
+            }
+            if (this.invalid || that.invalid) {
+                return false;
+            }
             if (allFiles) {
                 return true;
             }
@@ -687,9 +703,13 @@
         FilePermission that = (FilePermission) obj;
 
         if (FilePermCompat.nb) {
+            if (this.invalid || that.invalid) {
+                return false;
+            }
             return (this.mask == that.mask) &&
                     (this.allFiles == that.allFiles) &&
                     this.npath.equals(that.npath) &&
+                    Objects.equals(npath2, that.npath2) &&
                     (this.directory == that.directory) &&
                     (this.recursive == that.recursive);
         } else {
@@ -708,7 +728,8 @@
     @Override
     public int hashCode() {
         if (FilePermCompat.nb) {
-            return Objects.hash(mask, allFiles, directory, recursive, npath);
+            return Objects.hash(
+                    mask, allFiles, directory, recursive, npath, npath2, invalid);
         } else {
             return 0;
         }
--- a/jdk/src/java.base/share/classes/java/lang/Class.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/Class.java	Fri Nov 11 16:44:36 2016 +0100
@@ -485,7 +485,7 @@
      * can be replaced by
      *
      * <pre>{@code
-     * clazz.getConstructor().newInstance()
+     * clazz.getDeclaredConstructor().newInstance()
      * }</pre>
      *
      * The latter sequence of calls is inferred to be able to throw
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -104,9 +104,9 @@
  * 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
- * themselves at their class initialization time by invoking the
- * {@link
+ * <em>{@linkplain #isParallelCapable() parallel capable}</em> class loaders and
+ * are required to register themselves at their class initialization time by
+ * invoking the {@link
  * #registerAsParallelCapable <tt>ClassLoader.registerAsParallelCapable</tt>}
  * method. Note that the <tt>ClassLoader</tt> class is registered as parallel
  * capable by default. However, its subclasses still need to register themselves
@@ -222,6 +222,9 @@
     // must be added *after* it.
     private final ClassLoader parent;
 
+    // class loader name
+    private final String name;
+
     // the unnamed module for this ClassLoader
     private final Module unnamedModule;
 
@@ -331,6 +334,14 @@
     }
 
     private static Void checkCreateClassLoader() {
+        return checkCreateClassLoader(null);
+    }
+
+    private static Void checkCreateClassLoader(String name) {
+        if (name != null && name.isEmpty()) {
+            throw new IllegalArgumentException("name must be non-empty or null");
+        }
+
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkCreateClassLoader();
@@ -338,7 +349,8 @@
         return null;
     }
 
-    private ClassLoader(Void unused, ClassLoader parent) {
+    private ClassLoader(Void unused, String name, ClassLoader parent) {
+        this.name = name;
         this.parent = parent;
         this.unnamedModule
             = SharedSecrets.getJavaLangReflectModuleAccess()
@@ -356,6 +368,27 @@
     }
 
     /**
+     * Creates a new class loader of the specified name and using the
+     * specified parent class loader for delegation.
+     *
+     * @param  name   class loader name; or {@code null} if not named
+     * @param  parent the parent class loader
+     *
+     * @throws IllegalArgumentException if the given name is empty.
+     *
+     * @throws SecurityException
+     *         If a security manager exists and its
+     *         {@link SecurityManager#checkCreateClassLoader()}
+     *         method doesn't allow creation of a new class loader.
+     *
+     * @since  9
+     */
+    protected ClassLoader(String name, ClassLoader parent) {
+        this(checkCreateClassLoader(name), name, parent);
+    }
+
+
+    /**
      * Creates a new class loader using the specified parent class loader for
      * delegation.
      *
@@ -375,9 +408,10 @@
      * @since  1.2
      */
     protected ClassLoader(ClassLoader parent) {
-        this(checkCreateClassLoader(), parent);
+        this(checkCreateClassLoader(), null, parent);
     }
 
+
     /**
      * Creates a new class loader using the <tt>ClassLoader</tt> returned by
      * the method {@link #getSystemClassLoader()
@@ -394,7 +428,31 @@
      *          of a new class loader.
      */
     protected ClassLoader() {
-        this(checkCreateClassLoader(), getSystemClassLoader());
+        this(checkCreateClassLoader(), null, getSystemClassLoader());
+    }
+
+
+    /**
+     * Returns the name of this class loader or {@code null} if
+     * this class loader is not named.
+     *
+     * @apiNote This method is non-final for compatibility.  If this
+     * method is overridden, this method must return the same name
+     * as specified when this class loader was instantiated.
+     *
+     * @return name of this class loader; or {@code null} if
+     * this class loader is not named.
+     *
+     * @since 9
+     */
+    public String getName() {
+        return name;
+    }
+
+    // package-private used by StackTraceElement to avoid
+    // calling the overrideable getName method
+    final String name() {
+        return name;
     }
 
     // -- Class --
@@ -1437,7 +1495,7 @@
     }
 
     /**
-     * Registers the caller as parallel capable.
+     * Registers the caller as {@linkplain #isParallelCapable() parallel capable}.
      * The registration succeeds if and only if all of the following
      * conditions are met:
      * <ol>
@@ -1448,8 +1506,10 @@
      * <p>Note that once a class loader is registered as parallel capable, there
      * is no way to change it back.</p>
      *
-     * @return  true if the caller is successfully registered as
-     *          parallel capable and false if otherwise.
+     * @return  {@code true} if the caller is successfully registered as
+     *          parallel capable and {@code false} if otherwise.
+     *
+     * @see #isParallelCapable()
      *
      * @since   1.7
      */
@@ -1461,6 +1521,22 @@
     }
 
     /**
+     * Returns {@code true} if this class loader is
+     * {@linkplain #registerAsParallelCapable parallel capable}, otherwise
+     * {@code false}.
+     *
+     * @return  {@code true} if this class loader is parallel capable,
+     *          otherwise {@code false}.
+     *
+     * @see #registerAsParallelCapable()
+     *
+     * @since   9
+     */
+    public final boolean isParallelCapable() {
+        return ParallelLoaders.isRegistered(this.getClass());
+    }
+
+    /**
      * Find a resource of the specified name from the search path used to load
      * classes.  This method locates the resource through the system class
      * loader (see {@link #getSystemClassLoader()}).
@@ -1610,6 +1686,9 @@
      * <a href="#builtinLoaders">platform classes</a> are visible to
      * the platform class loader.
      *
+     * @implNote The name of the builtin platform class loader is
+     * {@code "platform"}.
+     *
      * @return  The platform {@code ClassLoader}.
      *
      * @throws  SecurityException
@@ -1663,6 +1742,16 @@
      * this method during startup should take care not to cache the return
      * value until the system is fully initialized.
      *
+     * <p> The name of the built-in system class loader is {@code "app"}.
+     * The class path used by the built-in system class loader is determined
+     * by the system property "{@code java.class.path}" during early
+     * initialization of the VM. If the system property is not defined,
+     * or its value is an empty string, then there is no class path
+     * when the initial module is a module on the application module path,
+     * i.e. <em>a named module</em>. If the initial module is not on
+     * the application module path then the class path defaults to
+     * the current working directory.
+     *
      * @return  The system <tt>ClassLoader</tt> for delegation
      *
      * @throws  SecurityException
--- a/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/StackFrameInfo.java	Fri Nov 11 16:44:36 2016 +0100
@@ -112,11 +112,6 @@
         return toStackTraceElement().toString();
     }
 
-    /**
-     * Fill in the fields of the given StackTraceElement
-     */
-    private native void toStackTraceElement0(StackTraceElement ste);
-
     @Override
     public StackTraceElement toStackTraceElement() {
         StackTraceElement s = ste;
@@ -124,9 +119,7 @@
             synchronized (this) {
                 s = ste;
                 if (s == null) {
-                    s = new StackTraceElement();
-                    toStackTraceElement0(s);
-                    ste = s;
+                    ste = s = StackTraceElement.of(this);
                 }
             }
         }
--- a/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/StackTraceElement.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,7 +25,18 @@
 
 package java.lang;
 
+import jdk.internal.loader.BuiltinClassLoader;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.VM;
+import jdk.internal.module.ModuleHashes;
+
+import java.lang.module.ModuleDescriptor.Version;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Module;
+import java.util.HashSet;
 import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 
 /**
  * An element in a stack trace, as returned by {@link
@@ -40,7 +51,15 @@
  * @author Josh Bloch
  */
 public final class StackTraceElement implements java.io.Serializable {
-    // Normally initialized by VM (public constructor added in 1.5)
+    // This field is set to the compacted String representation used
+    // by StackTraceElement::toString and stored in serial form.
+    //
+    // This field is of Object type. VM initially sets this field to
+    // the Class object of the declaring class to build the compacted string.
+    private Object classOrLoaderModuleClassName;
+
+    // Normally initialized by VM
+    private String classLoaderName;
     private String moduleName;
     private String moduleVersion;
     private String declaringClass;
@@ -72,19 +91,22 @@
      */
     public StackTraceElement(String declaringClass, String methodName,
                              String fileName, int lineNumber) {
-        this(null, null, declaringClass, methodName, fileName, lineNumber);
+        this(null, null, null, declaringClass, methodName, fileName, lineNumber);
     }
 
     /**
      * Creates a stack trace element representing the specified execution
      * point.
      *
+     * @param classLoaderName the class loader name if the class loader of
+     *        the class containing the execution point represented by
+     *        the stack trace is named; otherwise {@code null}
      * @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}
+     *        module; otherwise {@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}
+     *        module that has a version; otherwise {@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
@@ -97,26 +119,30 @@
      *        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,
+    public StackTraceElement(String classLoaderName,
+                             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;
-        this.lineNumber     = lineNumber;
+        this.classLoaderName = classLoaderName;
+        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;
+        this.lineNumber      = lineNumber;
     }
 
-
-    /**
-     * Creates an empty stack frame element to be filled in by Throwable.
+    /*
+     * Private constructor for the factory methods to create StackTraceElement
+     * for Throwable and StackFrameInfo
      */
-    StackTraceElement() { }
+    private StackTraceElement() {}
 
     /**
      * Returns the name of the source file containing the execution point
@@ -178,6 +204,21 @@
     }
 
     /**
+     * Returns the name of the class loader of the class containing the
+     * execution point represented by this stack trace element.
+     *
+     * @return the name of the class loader of the class containing the execution
+     *         point represented by this stack trace element; {@code null}
+     *         if the class loader is not named.
+     *
+     * @since 9
+     * @see java.lang.ClassLoader#getName()
+     */
+    public String getClassLoaderName() {
+        return classLoaderName;
+    }
+
+    /**
      * Returns the fully qualified name of the class containing the
      * execution point represented by this stack trace element.
      *
@@ -220,38 +261,83 @@
      * examples may be regarded as typical:
      * <ul>
      * <li>
-     *   {@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 "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.
+     *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Main.java:101)}"
+     * - See the description below.
+     * </li>
+     * <li>
+     *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Main.java)}"
+     * - The line number is unavailable.
+     * </li>
+     * <li>
+     *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Unknown Source)}"
+     * - Neither the file name nor the line number is available.
+     * </li>
+     * <li>
+     *     "{@code com.foo.loader/foo@9.0/com.foo.Main.run(Native Method)}"
+     * - The method containing the execution point is a native method.
+     * </li>
+     * <li>
+     *     "{@code com.foo.loader//com.foo.bar.App.run(App.java:12)}"
+     * - The class of the execution point is defined in the unnamed module of
+     * the class loader named {@code com.foo.loader}.
+     * </li>
+     * <li>
+     *     "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}"
+     * - The class of the execution point is defined in {@code acme} module
+     * loaded by by a built-in class loader such as the application class loader.
+     * </li>
      * <li>
-     *   {@code "MyClass.mash(my.module@9.0/MyClass.java)"} - As above, but the
-     *   line number is unavailable.
-     * <li>
-     *   {@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(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.
+     *     "{@code MyClass.mash(MyClass.java:9)}"
+     * - {@code MyClass} class is on the application class path.
+     * </li>
      * </ul>
-     * If the execution point is not in a named module, {@code "my.module@9.0/"}
-     * will be omitted from the above.
+     *
+     * <p> The first example shows a stack trace element consisting of
+     * three elements, each separated by {@code "/"} followed with
+     * the source file name and the line number of the source line
+     * containing the execution point.
+     *
+     * The first element "{@code com.foo.loader}" is
+     * the name of the class loader.  The second element "{@code foo@9.0}"
+     * is the module name and version.  The third element is the method
+     * containing the execution point; "{@code com.foo.Main"}" is the
+     * fully-qualified class name and "{@code run}" is the name of the method.
+     * "{@code Main.java}" is the source file name and "{@code 101}" is
+     * the line number.
+     *
+     * <p> If a class is defined in an <em>unnamed module</em>
+     * then the second element is omitted as shown in
+     * "{@code com.foo.loader//com.foo.bar.App.run(App.java:12)}".
+     *
+     * If the class loader is a <a href="ClassLoader.html#builtinLoaders">
+     * built-in class loader</a> or is not named then the first element
+     * and its following {@code "/"} are omitted as shown in
+     * "{@code acme@2.1/org.acme.Lib.test(Lib.java:80)}".
+     * If the first element is omitted and the module is an unnamed module,
+     * the second element and its following {@code "/"} are also omitted
+     * as shown in "{@code MyClass.mash(MyClass.java:9)}".
      *
      * @see    Throwable#printStackTrace()
      */
     public String toString() {
-        String mid = "";
-        if (moduleName != null) {
-            mid = moduleName;
-            if (moduleVersion != null)
-                mid += "@" + moduleVersion;
-            mid += "/";
+        String s = buildLoaderModuleClassName();
+        if (s == null) {
+            // all elements will be included
+            s = "";
+            if (classLoaderName != null && !classLoaderName.isEmpty()) {
+                s += classLoaderName + "/";
+            }
+            if (moduleName != null && !moduleName.isEmpty()) {
+                s += moduleName;
+
+                if (moduleVersion != null && !moduleVersion.isEmpty()) {
+                    s += "@" + moduleVersion;
+                }
+            }
+            s = s.isEmpty() ? declaringClass : s + "/" + declaringClass;
         }
-        return getClassName() + "." + methodName + "(" + mid +
+
+        return s + "." + methodName + "(" +
              (isNativeMethod() ? "Native Method)" :
               (fileName != null && lineNumber >= 0 ?
                fileName + ":" + lineNumber + ")" :
@@ -264,12 +350,14 @@
      * point as this instance.  Two stack trace elements {@code a} and
      * {@code b} are equal if and only if:
      * <pre>{@code
-     *     equals(a.getFileName(), b.getFileName()) &&
-     *     a.getLineNumber() == b.getLineNumber()) &&
+     *     equals(a.getClassLoaderName(), b.getClassLoaderName()) &&
      *     equals(a.getModuleName(), b.getModuleName()) &&
      *     equals(a.getModuleVersion(), b.getModuleVersion()) &&
      *     equals(a.getClassName(), b.getClassName()) &&
      *     equals(a.getMethodName(), b.getMethodName())
+     *     equals(a.getFileName(), b.getFileName()) &&
+     *     a.getLineNumber() == b.getLineNumber()
+     *
      * }</pre>
      * where {@code equals} has the semantics of {@link
      * java.util.Objects#equals(Object, Object) Objects.equals}.
@@ -285,9 +373,10 @@
         if (!(obj instanceof StackTraceElement))
             return false;
         StackTraceElement e = (StackTraceElement)obj;
-        return e.declaringClass.equals(declaringClass) &&
+        return Objects.equals(classLoaderName, e.classLoaderName) &&
             Objects.equals(moduleName, e.moduleName) &&
             Objects.equals(moduleVersion, e.moduleVersion) &&
+            e.declaringClass.equals(declaringClass) &&
             e.lineNumber == lineNumber &&
             Objects.equals(methodName, e.methodName) &&
             Objects.equals(fileName, e.fileName);
@@ -298,6 +387,7 @@
      */
     public int hashCode() {
         int result = 31*declaringClass.hashCode() + methodName.hashCode();
+        result = 31*result + Objects.hashCode(classLoaderName);
         result = 31*result + Objects.hashCode(moduleName);
         result = 31*result + Objects.hashCode(moduleVersion);
         result = 31*result + Objects.hashCode(fileName);
@@ -305,5 +395,157 @@
         return result;
     }
 
+
+    /**
+     * Build the compacted String representation to be returned by
+     * toString method from the declaring Class object.
+     */
+    synchronized String buildLoaderModuleClassName() {
+        if (classOrLoaderModuleClassName == null)
+            return null;
+
+        if (classOrLoaderModuleClassName instanceof Class) {
+            Class<?> cls = (Class<?>)classOrLoaderModuleClassName;
+            classOrLoaderModuleClassName = toLoaderModuleClassName(cls);
+        }
+        return (String)classOrLoaderModuleClassName;
+    }
+
+    /**
+     * Returns <loader>/<module>/<fully-qualified-classname> string
+     * representation of the given class.
+     * <p>
+     * If the module is a non-upgradeable JDK module then omit
+     * its version string.
+     * <p>
+     * If the loader has no name, or if the loader is one of the built-in
+     * loaders (`boot`, `platform`, or `app`) then drop the first element
+     * (`<loader>/`).
+     * <p>
+     * If the first element has been dropped and the module is unnamed
+     * then drop the second element (`<module>/`).
+     * <p>
+     * If the first element is not dropped and the module is unnamed
+     * then drop `<module>`.
+     */
+    private static String toLoaderModuleClassName(Class<?> cls) {
+        ClassLoader loader = cls.getClassLoader0();
+        Module m = cls.getModule();
+
+        // First element - class loader name
+        // Call package-private ClassLoader::name method
+        String s = "";
+        if (loader != null && loader.name() != null &&
+                !(loader instanceof BuiltinClassLoader)) {
+            s = loader.name() + "/";
+        }
+
+        // Second element - module name and version
+        if (m != null && m.isNamed()) {
+            s += m.getName();
+            // Include version if it is a user module or upgradeable module
+            //
+            // If it is JDK non-upgradeable module which is recorded
+            // in the hashes in java.base, omit the version.
+            if (!isHashedInJavaBase(m)) {
+                Optional<Version> ov = m.getDescriptor().version();
+                if (ov.isPresent()) {
+                    String version = "@" + ov.get().toString();
+                    s += version;
+                }
+            }
+        }
+
+        // fully-qualified class name
+        return s.isEmpty() ? cls.getName() : s + "/" + cls.getName();
+    }
+
+    /**
+     * Returns true if the module is hashed with java.base.
+     * <p>
+     * This method returns false when running on the exploded image
+     * since JDK modules are not hashed. They have no Version attribute
+     * and so "@<version>" part will be omitted anyway.
+     */
+    private static boolean isHashedInJavaBase(Module m) {
+        // return true if module system is not initialized as the code
+        // must be in java.base
+        if (!VM.isModuleSystemInited())
+            return true;
+
+        return Layer.boot() == m.getLayer() && HashedModules.contains(m);
+    }
+
+    /*
+     * Finds JDK non-upgradeable modules, i.e. the modules that are
+     * included in the hashes in java.base.
+     */
+    private static class HashedModules {
+        static Set<String> HASHED_MODULES = hashedModules();
+
+        static Set<String> hashedModules() {
+            Module javaBase = Layer.boot().findModule("java.base").get();
+            Optional<ModuleHashes> ohashes =
+                SharedSecrets.getJavaLangModuleAccess()
+                             .hashes(javaBase.getDescriptor());
+
+            if (ohashes.isPresent()) {
+                Set<String> names = new HashSet<>(ohashes.get().names());
+                names.add("java.base");
+                return names;
+            }
+
+            return Set.of();
+        }
+
+        static boolean contains(Module m) {
+            return HASHED_MODULES.contains(m.getName());
+        }
+    }
+
+
+    /*
+     * Returns an array of StackTraceElements of the given depth
+     * filled from the backtrace of a given Throwable.
+     */
+    static StackTraceElement[] of(Throwable x, int depth) {
+        StackTraceElement[] stackTrace = new StackTraceElement[depth];
+        for (int i = 0; i < depth; i++) {
+            stackTrace[i] = new StackTraceElement();
+        }
+
+        // VM to fill in StackTraceElement
+        initStackTraceElements(stackTrace, x);
+
+        // ensure the proper StackTraceElement initialization
+        for (StackTraceElement ste : stackTrace) {
+            ste.buildLoaderModuleClassName();
+        }
+        return stackTrace;
+    }
+
+    /*
+     * Returns a StackTraceElement from a given StackFrameInfo.
+     */
+    static StackTraceElement of(StackFrameInfo sfi) {
+        StackTraceElement ste = new StackTraceElement();
+        initStackTraceElement(ste, sfi);
+
+        ste.buildLoaderModuleClassName();
+        return ste;
+    }
+
+    /*
+     * Sets the given stack trace elements with the backtrace
+     * of the given Throwable.
+     */
+    private static native void initStackTraceElements(StackTraceElement[] elements,
+                                                      Throwable x);
+    /*
+     * Sets the given stack trace element with the given StackFrameInfo
+     */
+    private static native void initStackTraceElement(StackTraceElement element,
+                                                     StackFrameInfo sfi);
+
     private static final long serialVersionUID = 6992337162326171013L;
 }
--- a/jdk/src/java.base/share/classes/java/lang/Throwable.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,7 +24,6 @@
  */
 
 package java.lang;
-import jdk.internal.misc.VM;
 
 import  java.io.*;
 import  java.util.*;
@@ -826,11 +825,7 @@
         // backtrace if this is the first call to this method
         if (stackTrace == UNASSIGNED_STACK ||
             (stackTrace == null && backtrace != null) /* Out of protocol state */) {
-            stackTrace = new StackTraceElement[depth];
-            for (int i = 0; i < depth; i++) {
-                stackTrace[i] = new StackTraceElement();
-            }
-            getStackTraceElements(stackTrace);
+            stackTrace = StackTraceElement.of(this, depth);
         } else if (stackTrace == null) {
             return UNASSIGNED_STACK;
         }
@@ -882,13 +877,6 @@
     }
 
     /**
-     * Gets the stack trace elements.
-     * @param  elements
-     * @throws IndexOutOfBoundsException if {@code elements.length != depth }
-     */
-    private native void getStackTraceElements(StackTraceElement[] elements);
-
-    /**
      * Reads a {@code Throwable} from a stream, enforcing
      * well-formedness constraints on fields.  Null entries and
      * self-pointers are not allowed in the list of {@code
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Fri Nov 11 16:44:36 2016 +0100
@@ -5347,7 +5347,7 @@
      * {@code (V T A...)} must have at least one {@code A} type, and the default iterator
      * handle parameter is adjusted to accept the leading {@code A} type, as if by
      * the {@link MethodHandle#asType asType} conversion method.
-     * The leading {@code A} type must be {@code Iterable} or a subtype thereof, or an array type.
+     * The leading {@code A} type must be {@code Iterable} or a subtype thereof.
      * This conversion step, done at loop construction time, must not throw a {@code WrongMethodTypeException}.
      * </ul>
      * <p>
@@ -5374,7 +5374,8 @@
      * V iteratedLoop(A... a...) {
      *   Iterator<T> it = iterator(a...);
      *   V v = init(a...);
-     *   for (T t : it) {
+     *   while (it.hasNext()) {
+     *     T t = it.next();
      *     v = body(v, t, a...);
      *   }
      *   return v;
@@ -5483,49 +5484,59 @@
         Objects.requireNonNull(body);
         MethodType bodyType = body.type();
         Class<?> returnType = bodyType.returnType();
-        List<Class<?>> innerList = bodyType.parameterList();
+        List<Class<?>> internalParamList = bodyType.parameterList();
         // strip leading V value if present
         int vsize = (returnType == void.class ? 0 : 1);
-        if (vsize != 0 && (innerList.size() == 0 || innerList.get(0) != returnType)) {
+        if (vsize != 0 && (internalParamList.size() == 0 || internalParamList.get(0) != returnType)) {
             // argument list has no "V" => error
             MethodType expected = bodyType.insertParameterTypes(0, returnType);
             throw misMatchedTypes("body function", bodyType, expected);
-        } else if (innerList.size() <= vsize) {
+        } else if (internalParamList.size() <= vsize) {
             // missing T type => error
             MethodType expected = bodyType.insertParameterTypes(vsize, Object.class);
             throw misMatchedTypes("body function", bodyType, expected);
         }
-        //Class<?> elementType = innerList.get(vsize);  // do not need this
-        List<Class<?>> outerList = innerList.subList(vsize + 1, innerList.size());
-        if (outerList.isEmpty()) {
-            // special case; take lists from iterator handle
-            outerList = ((iterator != null)
-                    ? iterator.type().parameterList()
-                    : Arrays.asList(Iterable.class));
-            innerList = bodyType.insertParameterTypes(vsize + 1, outerList).parameterList();
-        }
+        List<Class<?>> externalParamList = internalParamList.subList(vsize + 1, internalParamList.size());
+        Class<?> iterableType = null;
         if (iterator != null) {
+            // special case; if the body handle only declares V and T then
+            // the external parameter list is obtained from iterator handle
+            if (externalParamList.isEmpty()) {
+                externalParamList = iterator.type().parameterList();
+            }
             MethodType itype = iterator.type();
             if (!Iterator.class.isAssignableFrom(itype.returnType())) {
                 throw newIllegalArgumentException("iteratedLoop first argument must have Iterator return type");
             }
-            if (!itype.effectivelyIdenticalParameters(0, outerList)) {
-                MethodType expected = methodType(itype.returnType(), outerList);
+            if (!itype.effectivelyIdenticalParameters(0, externalParamList)) {
+                MethodType expected = methodType(itype.returnType(), externalParamList);
                 throw misMatchedTypes("iterator parameters", itype, expected);
             }
+        } else {
+            if (externalParamList.isEmpty()) {
+                // special case; if the iterator handle is null and the body handle
+                // only declares V and T then the external parameter list consists
+                // of Iterable
+                externalParamList = Arrays.asList(Iterable.class);
+                iterableType = Iterable.class;
+            } else {
+                // special case; if the iterator handle is null and the external
+                // parameter list is not empty then the first parameter must be
+                // assignable to Iterable
+                iterableType = externalParamList.get(0);
+                if (!Iterable.class.isAssignableFrom(iterableType)) {
+                    throw newIllegalArgumentException(
+                            "inferred first loop argument must inherit from Iterable: " + iterableType);
+                }
+            }
         }
         if (init != null) {
             MethodType initType = init.type();
             if (initType.returnType() != returnType ||
-                    !initType.effectivelyIdenticalParameters(0, outerList)) {
-                throw misMatchedTypes("loop initializer", initType, methodType(returnType, outerList));
+                    !initType.effectivelyIdenticalParameters(0, externalParamList)) {
+                throw misMatchedTypes("loop initializer", initType, methodType(returnType, externalParamList));
             }
         }
-        Class<?> iterableType = outerList.isEmpty() ? null : outerList.get(0);
-        if (iterableType != null && !Iterable.class.isAssignableFrom(iterableType) && !iterableType.isArray()) {
-            throw newIllegalArgumentException(
-                    "inferred first loop argument must be an array or inherit from Iterable: " + iterableType);
-        }
         return iterableType;  // help the caller a bit
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,6 +31,7 @@
 import java.io.UncheckedIOException;
 import java.net.URI;
 import java.nio.ByteBuffer;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -1997,6 +1998,13 @@
                 public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) {
                     return descriptor.hashes();
                 }
+
+                @Override
+                public ModuleFinder newModulePath(Runtime.Version version,
+                                                  boolean isLinkPhase,
+                                                  Path... entries) {
+                    return new ModulePath(version, isLinkPhase, entries);
+                }
             });
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleFinder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -228,7 +228,7 @@
      *
      *         <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 preceding 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>
@@ -248,18 +248,23 @@
      *     <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 set of packages in the module is derived from the names
+     *     of non-directory entries in the JAR file. A candidate package name
+     *     is derived from an entry using the characters up to, but not
+     *     including, the last forward slash. All remaining forward slashes are
+     *     replaced with dot ({@code "."}). If the resulting string is a valid
+     *     Java identifier then it is assumed to be a package name. For example,
+     *     if the JAR file contains an entry "{@code p/q/Foo.class}" then the
+     *     package name derived is "{@code p.q}". All packages are {@link
+     *     ModuleDescriptor#exports() exported}. </p></li>
      *
-     *     <li><p> The contents of all entries starting with {@code
+     *     <li><p> The contents of 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>
+     *     (see {@link java.util.ServiceLoader}). If the name of a file
+     *     (that follows {@code META-INF/services/}) is a legal Java identifier
+     *     then it 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
@@ -271,8 +276,8 @@
      * {@link ModuleDescriptor.Builder ModuleDescriptor.Builder} API) for an
      * automatic module then {@code FindException} is thrown. This can arise,
      * for example, when a legal Java identifier name cannot be derived from
-     * the file name of the JAR file or where a package name derived from an
-     * entry ending with {@code .class} is not a legal Java identifier. </p>
+     * the file name of the JAR file or where the JAR file contains a {@code
+     * .class} in the top-level directory of the JAR file. </p>
      *
      * <p> In addition to JAR files, an implementation may also support modules
      * that are packaged in other implementation specific module formats. When
@@ -283,8 +288,10 @@
      *
      * <p> 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>
+     * in the module. If a {@code .class} file (other than {@code
+     * module-info.class}) is found in the top-level directory then it is
+     * assumed to be a class in the unnamed package and so {@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.
@@ -341,7 +348,7 @@
      * @return A {@code ModuleFinder} that composes a sequence of module finders
      */
     static ModuleFinder compose(ModuleFinder... finders) {
-        // copy the list, also checking for nulls
+        // copy the list and check for nulls
         final List<ModuleFinder> finderList = List.of(finders);
 
         return new ModuleFinder() {
--- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,10 +33,12 @@
 import java.io.InputStreamReader;
 import java.io.UncheckedIOException;
 import java.lang.module.ModuleDescriptor.Requires;
+import java.net.URI;
 import java.nio.file.DirectoryStream;
 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.Collections;
 import java.util.HashMap;
@@ -52,49 +54,53 @@
 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.jmod.JmodFile;
 import jdk.internal.jmod.JmodFile.Section;
-import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.module.Checks;
 import jdk.internal.perf.PerfCounter;
+import jdk.internal.util.jar.VersionedStream;
 
 
 /**
  * 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
+ * The {@code ModuleFinder} can be created 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. When created for link-time then it additionally locates
  * modules in JMOD files.
  */
 
-class ModulePath implements ConfigurableModuleFinder {
+class ModulePath implements ModuleFinder {
     private static final String MODULE_INFO = "module-info.class";
 
+    // the version to use for multi-release modular JARs
+    private final Runtime.Version releaseVersion;
+
+    // true for the link phase (supports modules packaged in JMOD format)
+    private final boolean isLinkPhase;
+
     // 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) {
+    ModulePath(Runtime.Version version, boolean isLinkPhase, Path... entries) {
+        this.releaseVersion = version;
+        this.isLinkPhase = isLinkPhase;
         this.entries = entries.clone();
         for (Path entry : this.entries) {
             Objects.requireNonNull(entry);
         }
     }
 
-    @Override
-    public void configurePhase(Phase phase) {
-        isLinkPhase = (phase == Phase.LINK_TIME);
+    ModulePath(Path... entries) {
+        this(JarFile.runtimeVersion(), false, entries);
     }
 
     @Override
@@ -239,9 +245,13 @@
                 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) {
+                    ModuleReference previous = nameToReference.put(name, mref);
+                    if (previous != null) {
+                        String fn1 = fileName(mref);
+                        String fn2 = fileName(previous);
                         throw new FindException("Two versions of module "
-                                                  + name + " found in " + dir);
+                                                 + name + " found in " + dir
+                                                 + " (" + fn1 + " and " + fn2 + ")");
                     }
                 }
             }
@@ -294,6 +304,25 @@
     }
 
 
+    /**
+     * Returns a string with the file name of the module if possible.
+     * If the module location is not a file URI then return the URI
+     * as a string.
+     */
+    private String fileName(ModuleReference mref) {
+        URI uri = mref.location().orElse(null);
+        if (uri != null) {
+            if (uri.getScheme().equalsIgnoreCase("file")) {
+                Path file = Paths.get(uri);
+                return file.getFileName().toString();
+            } else {
+                return uri.toString();
+            }
+        } else {
+            return "<unknown>";
+        }
+    }
+
     // -- jmod files --
 
     private Set<String> jmodPackages(JmodFile jf) {
@@ -301,7 +330,7 @@
             .filter(e -> e.section() == Section.CLASSES)
             .map(JmodFile.Entry::name)
             .map(this::toPackageName)
-            .filter(pkg -> pkg.length() > 0) // module-info
+            .flatMap(Optional::stream)
             .collect(Collectors.toSet());
     }
 
@@ -328,8 +357,8 @@
     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.
+     * Returns the service type corresponding to the name of a services
+     * configuration file if it is a valid Java identifier.
      *
      * For example, if called with "META-INF/services/p.S" then this method
      * returns a container with the value "p.S".
@@ -341,7 +370,8 @@
             String prefix = cf.substring(0, index);
             if (prefix.equals(SERVICES_PREFIX)) {
                 String sn = cf.substring(index);
-                return Optional.of(sn);
+                if (Checks.isJavaIdentifier(sn))
+                    return Optional.of(sn);
             }
         }
         return Optional.empty();
@@ -416,28 +446,28 @@
         if (vs != null)
             builder.version(vs);
 
-        // scan the entries in the JAR file to locate the .class and service
-        // configuration file
-        Map<Boolean, Set<String>> map =
-            versionedStream(jf)
-              .map(JarEntry::getName)
-              .filter(s -> (s.endsWith(".class") ^ s.startsWith(SERVICES_PREFIX)))
-              .collect(Collectors.partitioningBy(s -> s.endsWith(".class"),
-                                                 Collectors.toSet()));
-        Set<String> classFiles = map.get(Boolean.TRUE);
-        Set<String> configFiles = map.get(Boolean.FALSE);
+        // scan the names of the entries in the JAR file
+        Map<Boolean, Set<String>> map = VersionedStream.stream(jf)
+                .filter(e -> !e.isDirectory())
+                .map(JarEntry::getName)
+                .collect(Collectors.partitioningBy(e -> e.startsWith(SERVICES_PREFIX),
+                                                   Collectors.toSet()));
+
+        Set<String> resources = map.get(Boolean.FALSE);
+        Set<String> configFiles = map.get(Boolean.TRUE);
 
         // all packages are exported
-        classFiles.stream()
-            .map(c -> toPackageName(c))
-            .distinct()
-            .forEach(builder::exports);
+        resources.stream()
+                .map(this::toPackageName)
+                .flatMap(Optional::stream)
+                .distinct()
+                .forEach(builder::exports);
 
         // map names of service configuration files to service names
         Set<String> serviceNames = configFiles.stream()
-            .map(this::toServiceName)
-            .flatMap(Optional::stream)
-            .collect(Collectors.toSet());
+                .map(this::toServiceName)
+                .flatMap(Optional::stream)
+                .collect(Collectors.toSet());
 
         // parse each service configuration file
         for (String sn : serviceNames) {
@@ -502,25 +532,13 @@
         return mn;
     }
 
-    private Stream<JarEntry> versionedStream(JarFile jf) {
-        if (jf.isMultiRelease()) {
-            // a stream of JarEntries whose names are base names and whose
-            // contents are from the corresponding versioned entries in
-            // a multi-release jar file
-            return jf.stream().map(JarEntry::getName)
-                    .filter(name -> !name.startsWith("META-INF/versions/"))
-                    .map(jf::getJarEntry);
-        } else {
-            return jf.stream();
-        }
-    }
-
     private Set<String> jarPackages(JarFile jf) {
-        return versionedStream(jf)
-            .filter(e -> e.getName().endsWith(".class"))
-            .map(e -> toPackageName(e.getName()))
-            .filter(pkg -> pkg.length() > 0)   // module-info
-            .collect(Collectors.toSet());
+        return VersionedStream.stream(jf)
+                .filter(e -> !e.isDirectory())
+                .map(JarEntry::getName)
+                .map(this::toPackageName)
+                .flatMap(Optional::stream)
+                .collect(Collectors.toSet());
     }
 
     /**
@@ -535,7 +553,7 @@
         try (JarFile jf = new JarFile(file.toFile(),
                                       true,               // verify
                                       ZipFile.OPEN_READ,
-                                      JarFile.runtimeVersion()))
+                                      releaseVersion))
         {
             ModuleDescriptor md;
             JarEntry entry = jf.getJarEntry(MODULE_INFO);
@@ -565,11 +583,11 @@
     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
-                .collect(Collectors.toSet());
+                              ((path, attrs) -> attrs.isRegularFile()))
+                    .map(path -> dir.relativize(path))
+                    .map(this::toPackageName)
+                    .flatMap(Optional::stream)
+                    .collect(Collectors.toSet());
         } catch (IOException x) {
             throw new UncheckedIOException(x);
         }
@@ -595,29 +613,62 @@
         return ModuleReferences.newExplodedModule(md, dir);
     }
 
-
-    //
+    /**
+     * Maps the name of an entry in a JAR or ZIP file to a package name.
+     *
+     * @throws IllegalArgumentException if the name is a class file in
+     *         the top-level directory of the JAR/ZIP file (and it's
+     *         not module-info.class)
+     */
+    private Optional<String> toPackageName(String name) {
+        assert !name.endsWith("/");
 
-    // 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('/', '.');
+        int index = name.lastIndexOf("/");
+        if (index == -1) {
+            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
+                throw new IllegalArgumentException(name
+                        + " found in top-level directory:"
+                        + " (unnamed package not allowed in module)");
+            }
+            return Optional.empty();
+        }
+
+        String pn = name.substring(0, index).replace('/', '.');
+        if (Checks.isJavaIdentifier(pn)) {
+            return Optional.of(pn);
         } else {
-            return "";
+            // not a valid package name
+            return Optional.empty();
         }
     }
 
-    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, '.');
+    /**
+     * Maps the relative path of an entry in an exploded module to a package
+     * name.
+     *
+     * @throws IllegalArgumentException if the name is a class file in
+     *         the top-level directory (and it's not module-info.class)
+     */
+    private Optional<String> toPackageName(Path file) {
+        assert file.getRoot() == null;
+
+        Path parent = file.getParent();
+        if (parent == null) {
+            String name = file.toString();
+            if (name.endsWith(".class") && !name.equals(MODULE_INFO)) {
+                throw new IllegalArgumentException(name
+                        + " found in in top-level directory"
+                        + " (unnamed package not allowed in module)");
+            }
+            return Optional.empty();
+        }
+
+        String pn = parent.toString().replace(File.separatorChar, '.');
+        if (Checks.isJavaIdentifier(pn)) {
+            return Optional.of(pn);
         } else {
-            return "";
+            // not a valid package name
+            return Optional.empty();
         }
     }
 
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,6 +32,7 @@
 import java.nio.ByteBuffer;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 
 /**
@@ -44,6 +45,11 @@
  * module. A module reader is also intended to be used by {@code ClassLoader}
  * implementations that load classes and resources from modules. </p>
  *
+ * <p> A resource in a module is identified by a name that is a
+ * '{@code /}'-separated path string. For example, module {@code java.base} may
+ * have a resource "{@code java/lang/Object.class}" that, by convention, is the
+ * class file for {@code java.lang.Object}. </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
@@ -52,8 +58,8 @@
  *
  * <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>
+ * open}, {@link #read read}, and {@link #list list} methods may throw {@code
+ * SecurityException} if access is denied by the security manager. </p>
  *
  * @see ModuleReference
  * @since 9
@@ -84,6 +90,9 @@
      * Opens a resource, returning an input stream to read the resource in
      * the module.
      *
+     * <p> The behavior of the input stream when used after the module reader
+     * is closed is implementation specific and therefore not specified. </p>
+     *
      * @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
@@ -172,17 +181,37 @@
     }
 
     /**
+     * Lists the contents of the module, returning a stream of elements that
+     * are the names of all resources in the module.
+     *
+     * <p> In lazy implementations then an {@code IOException} may be thrown
+     * when using the stream to list the module contents. If this occurs then
+     * the {@code IOException} will be wrapped in an {@link
+     * java.io.UncheckedIOException} and thrown from the method that caused the
+     * access to be attempted. {@code SecurityException} may also be thrown
+     * when using the stream to list the module contents and access is denied
+     * by the security manager. </p>
+     *
+     * <p> The behavior of the stream when used after the module reader is
+     * closed is implementation specific and therefore not specified. </p>
+     *
+     * @return A stream of elements that are the names of all resources
+     *         in the module
+     *
+     * @throws IOException
+     *         If an I/O error occurs or the module reader is closed
+     * @throws SecurityException
+     *         If denied by the security manager
+     */
+    Stream<String> list() throws IOException;
+
+    /**
      * 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}.
+     * read a resource will fail by 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.
+     * then the second thread may block until the read operation is complete. </p>
      */
     @Override
     void close() throws IOException;
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,6 +35,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.concurrent.locks.Lock;
@@ -43,14 +44,17 @@
 import java.util.function.Supplier;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
-import java.util.zip.ZipEntry;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import java.util.zip.ZipFile;
 
+import jdk.internal.jmod.JmodFile;
 import jdk.internal.misc.JavaLangAccess;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleHashes.HashSupplier;
 import jdk.internal.module.ModulePatcher;
+import jdk.internal.util.jar.VersionedStream;
 import sun.net.www.ParseUtil;
 
 
@@ -140,6 +144,13 @@
         abstract Optional<InputStream> implOpen(String name) throws IOException;
 
         /**
+         * Returns a stream of the names of resources in the module. This
+         * method is invoked by the list method to do the actual work of
+         * creating the stream.
+         */
+        abstract Stream<String> implList() throws IOException;
+
+        /**
          * Closes the module reader. This method is invoked by close to do the
          * actual work of closing the module reader.
          */
@@ -175,7 +186,21 @@
         }
 
         @Override
-        public void close() throws IOException {
+        public final Stream<String> list() throws IOException {
+            readLock.lock();
+            try {
+                if (!closed) {
+                    return implList();
+                } else {
+                    throw new IOException("ModuleReader is closed");
+                }
+            } finally {
+                readLock.unlock();
+            }
+        }
+
+        @Override
+        public final void close() throws IOException {
             writeLock.lock();
             try {
                 if (!closed) {
@@ -241,6 +266,16 @@
         }
 
         @Override
+        Stream<String> implList() throws IOException {
+            // take snapshot to avoid async close
+            List<String> names = VersionedStream.stream(jf)
+                    .filter(e -> !e.isDirectory())
+                    .map(JarEntry::getName)
+                    .collect(Collectors.toList());
+            return names.stream();
+        }
+
+        @Override
         void implClose() throws IOException {
             jf.close();
         }
@@ -251,30 +286,31 @@
      * A ModuleReader for a JMOD file.
      */
     static class JModModuleReader extends SafeCloseModuleReader {
-        private final ZipFile zf;
+        private final JmodFile jf;
         private final URI uri;
 
-        static ZipFile newZipFile(Path path) {
+        static JmodFile newJmodFile(Path path) {
             try {
-                return new ZipFile(path.toFile());
+                return new JmodFile(path);
             } catch (IOException ioe) {
                 throw new UncheckedIOException(ioe);
             }
         }
 
         JModModuleReader(Path path, URI uri) {
-            this.zf = newZipFile(path);
+            this.jf = newJmodFile(path);
             this.uri = uri;
         }
 
-        private ZipEntry getEntry(String name) {
-            return zf.getEntry("classes/" + Objects.requireNonNull(name));
+        private JmodFile.Entry getEntry(String name) {
+            Objects.requireNonNull(name);
+            return jf.getEntry(JmodFile.Section.CLASSES, name);
         }
 
         @Override
         Optional<URI> implFind(String name) {
-            ZipEntry ze = getEntry(name);
-            if (ze != null) {
+            JmodFile.Entry je = getEntry(name);
+            if (je != null) {
                 String encodedPath = ParseUtil.encodePath(name, false);
                 String uris = "jmod:" + uri + "!/" + encodedPath;
                 return Optional.of(URI.create(uris));
@@ -285,17 +321,27 @@
 
         @Override
         Optional<InputStream> implOpen(String name) throws IOException {
-            ZipEntry ze = getEntry(name);
-            if (ze != null) {
-                return Optional.of(zf.getInputStream(ze));
+            JmodFile.Entry je = getEntry(name);
+            if (je != null) {
+                return Optional.of(jf.getInputStream(je));
             } else {
                 return Optional.empty();
             }
         }
 
         @Override
+        Stream<String> implList() throws IOException {
+            // take snapshot to avoid async close
+            List<String> names = jf.stream()
+                    .filter(e -> e.section() == JmodFile.Section.CLASSES)
+                    .map(JmodFile.Entry::name)
+                    .collect(Collectors.toList());
+            return names.stream();
+        }
+
+        @Override
         void implClose() throws IOException {
-            zf.close();
+            jf.close();
         }
     }
 
@@ -378,6 +424,17 @@
         }
 
         @Override
+        public Stream<String> list() throws IOException {
+            ensureOpen();
+            // sym links not followed
+            return Files.find(dir, Integer.MAX_VALUE,
+                              (path, attrs) -> attrs.isRegularFile())
+                    .map(f -> dir.relativize(f)
+                                 .toString()
+                                 .replace(File.separatorChar, '/'));
+        }
+
+        @Override
         public void close() {
             closed = true;
         }
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,14 +32,21 @@
 import java.net.URI;
 import java.net.URLConnection;
 import java.nio.ByteBuffer;
+import java.util.ArrayDeque;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.Spliterator;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
 
 import jdk.internal.jimage.ImageLocation;
 import jdk.internal.jimage.ImageReader;
@@ -62,6 +69,8 @@
 
 class SystemModuleFinder implements ModuleFinder {
 
+    private static final JavaNetUriAccess JNUA = SharedSecrets.getJavaNetUriAccess();
+
     private static final PerfCounter initTime
         = PerfCounter.newPerfCounter("jdk.module.finder.jimage.initTime");
     private static final PerfCounter moduleCount
@@ -73,8 +82,6 @@
     // ImageReader used to access all modules in the image
     private static final ImageReader imageReader;
 
-    private static final JavaNetUriAccess jnua = SharedSecrets.getJavaNetUriAccess();
-
     // the set of modules in the run-time image
     private static final Set<ModuleReference> modules;
 
@@ -170,8 +177,7 @@
                                                      HashSupplier hash)
     {
         String mn = md.name();
-
-        URI uri = jnua.create("jrt", "/".concat(mn));
+        URI uri = JNUA.create("jrt", "/".concat(mn));
 
         Supplier<ModuleReader> readerSupplier = new Supplier<>() {
             @Override
@@ -332,10 +338,101 @@
         }
 
         @Override
+        public Stream<String> list() throws IOException {
+            if (closed)
+                throw new IOException("ModuleReader is closed");
+
+            Spliterator<String> s = new ModuleContentSpliterator(module);
+            return StreamSupport.stream(s, false);
+        }
+
+        @Override
         public void close() {
             // nothing else to do
             closed = true;
         }
     }
 
+    /**
+     * A Spliterator for traversing the resources of a module linked into the
+     * run-time image.
+     */
+    static class ModuleContentSpliterator implements Spliterator<String> {
+        final String moduleRoot;
+        final Deque<ImageReader.Node> stack;
+        Iterator<ImageReader.Node> iterator;
+
+        ModuleContentSpliterator(String module) throws IOException {
+            moduleRoot = "/modules/" + module;
+            stack = new ArrayDeque<>();
+
+            // push the root node to the stack to get started
+            ImageReader.Node dir = imageReader.findNode(moduleRoot);
+            if (dir == null || !dir.isDirectory())
+                throw new IOException(moduleRoot + " not a directory");
+            stack.push(dir);
+            iterator = Collections.emptyIterator();
+        }
+
+        /**
+         * Returns the name of the next non-directory node or {@code null} if
+         * there are no remaining nodes to visit.
+         */
+        private String next() throws IOException {
+            for (;;) {
+                while (iterator.hasNext()) {
+                    ImageReader.Node node = iterator.next();
+                    String name = node.getName();
+                    if (node.isDirectory()) {
+                        // build node
+                        ImageReader.Node dir = imageReader.findNode(name);
+                        assert dir.isDirectory();
+                        stack.push(dir);
+                    } else {
+                        // strip /modules/$MODULE/ prefix
+                        return name.substring(moduleRoot.length() + 1);
+                    }
+                }
+
+                if (stack.isEmpty()) {
+                    return null;
+                } else {
+                    ImageReader.Node dir = stack.poll();
+                    assert dir.isDirectory();
+                    iterator = dir.getChildren().iterator();
+                }
+            }
+        }
+
+        @Override
+        public boolean tryAdvance(Consumer<? super String> action) {
+            String next;
+            try {
+                next = next();
+            } catch (IOException ioe) {
+                throw new UncheckedIOException(ioe);
+            }
+            if (next != null) {
+                action.accept(next);
+                return true;
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public Spliterator<String> trySplit() {
+            return null;
+        }
+
+        @Override
+        public int characteristics() {
+            return Spliterator.DISTINCT + Spliterator.NONNULL + Spliterator.IMMUTABLE;
+        }
+
+        @Override
+        public long estimateSize() {
+            return Long.MAX_VALUE;
+        }
+    }
 }
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java	Fri Nov 11 16:44:36 2016 +0100
@@ -201,13 +201,13 @@
      * Specify the address family: Internet Protocol, Version 4
      * @since 1.4
      */
-    static final int IPv4 = 1;
+    @Native static final int IPv4 = 1;
 
     /**
      * Specify the address family: Internet Protocol, Version 6
      * @since 1.4
      */
-    static final int IPv6 = 2;
+    @Native static final int IPv6 = 2;
 
     /* Specify address family preference */
     static transient final int preferIPv6Address;
--- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -110,19 +110,19 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
+        this.ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
     }
 
-    URLClassLoader(URL[] urls, ClassLoader parent,
+    URLClassLoader(String name, URL[] urls, ClassLoader parent,
                    AccessControlContext acc) {
-        super(parent);
+        super(name, parent);
         // this is to make the stack depth consistent with 1.1
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
+        this.ucp = new URLClassPath(urls);
         this.acc = acc;
     }
 
@@ -154,7 +154,7 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
+        this.ucp = new URLClassPath(urls);
         this.acc = AccessController.getContext();
     }
 
@@ -165,7 +165,7 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls);
+        this.ucp = new URLClassPath(urls);
         this.acc = acc;
     }
 
@@ -198,8 +198,76 @@
         if (security != null) {
             security.checkCreateClassLoader();
         }
-        ucp = new URLClassPath(urls, factory);
-        acc = AccessController.getContext();
+        this.ucp = new URLClassPath(urls, factory);
+        this.acc = AccessController.getContext();
+    }
+
+
+    /**
+     * Constructs a new named {@code URLClassLoader} for the specified URLs.
+     * The URLs will be searched in the order specified for classes
+     * and resources after first searching in the specified parent class loader.
+     * Any URL that ends with a '/' is assumed to refer to a directory.
+     * Otherwise, the URL is assumed to refer to a JAR file which will be
+     * downloaded and opened as needed.
+     *
+     * @param  name class loader name; or {@code null} if not named
+     * @param  urls the URLs from which to load classes and resources
+     * @param  parent the parent class loader for delegation
+     *
+     * @throws IllegalArgumentException if the given name is empty.
+     * @throws NullPointerException if {@code urls} is {@code null}.
+     *
+     * @throws SecurityException if a security manager exists and its
+     *         {@link SecurityManager#checkCreateClassLoader()} method doesn't
+     *         allow creation of a class loader.
+     *
+     * @since 9
+     */
+    public URLClassLoader(String name,
+                          URL[] urls,
+                          ClassLoader parent) {
+        super(name, parent);
+        // this is to make the stack depth consistent with 1.1
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        this.ucp = new URLClassPath(urls);
+        this.acc = AccessController.getContext();
+    }
+
+    /**
+     * Constructs a new named {@code URLClassLoader} for the specified URLs,
+     * parent class loader, and URLStreamHandlerFactory.
+     * The parent argument will be used as the parent class loader for delegation.
+     * The factory argument will be used as the stream handler factory to
+     * obtain protocol handlers when creating new jar URLs.
+     *
+     * @param  name class loader name; or {@code null} if not named
+     * @param  urls the URLs from which to load classes and resources
+     * @param  parent the parent class loader for delegation
+     * @param  factory the URLStreamHandlerFactory to use when creating URLs
+     *
+     * @throws IllegalArgumentException if the given name is empty.
+     * @throws NullPointerException if {@code urls} is {@code null}.
+     *
+     * @throws SecurityException if a security manager exists and its
+     *         {@code checkCreateClassLoader} method doesn't allow
+     *         creation of a class loader.
+     *
+     * @since 9
+     */
+    public URLClassLoader(String name, URL[] urls, ClassLoader parent,
+                          URLStreamHandlerFactory factory) {
+        super(name, parent);
+        // this is to make the stack depth consistent with 1.1
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        this.ucp = new URLClassPath(urls, factory);
+        this.acc = AccessController.getContext();
     }
 
     /* A map (used as a set) to keep track of closeable local resources
@@ -735,7 +803,7 @@
         URLClassLoader ucl = AccessController.doPrivileged(
             new PrivilegedAction<>() {
                 public URLClassLoader run() {
-                    return new FactoryURLClassLoader(urls, parent, acc);
+                    return new FactoryURLClassLoader(null, urls, parent, acc);
                 }
             });
         return ucl;
@@ -785,9 +853,9 @@
         ClassLoader.registerAsParallelCapable();
     }
 
-    FactoryURLClassLoader(URL[] urls, ClassLoader parent,
+    FactoryURLClassLoader(String name, URL[] urls, ClassLoader parent,
                           AccessControlContext acc) {
-        super(urls, parent, acc);
+        super(name, urls, parent, acc);
     }
 
     FactoryURLClassLoader(URL[] urls, AccessControlContext acc) {
--- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,8 +55,8 @@
     private static final SecureRandom random = new SecureRandom();
     private static Path generatePath(String prefix, String suffix, Path dir) {
         long n = random.nextLong();
-        n = (n == Long.MIN_VALUE) ? 0 : Math.abs(n);
-        Path name = dir.getFileSystem().getPath(prefix + Long.toString(n) + suffix);
+        String s = prefix + Long.toUnsignedString(n) + suffix;
+        Path name = dir.getFileSystem().getPath(s);
         // the generated name should be a simple file name
         if (name.getParent() != null)
             throw new IllegalArgumentException("Invalid prefix or suffix");
--- a/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/AlgorithmParameterGenerator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,6 +26,7 @@
 package java.security;
 
 import java.security.spec.AlgorithmParameterSpec;
+import java.util.Objects;
 
 /**
  * The {@code AlgorithmParameterGenerator} class is used to generate a
@@ -153,16 +154,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new AlgorithmParameterGenerator object.
+     * @return the new {@code AlgorithmParameterGenerator} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports an
-     *          AlgorithmParameterGeneratorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports an
+     *         {@code AlgorithmParameterGeneratorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static AlgorithmParameterGenerator getInstance(String algorithm)
         throws NoSuchAlgorithmException {
+            Objects.requireNonNull(algorithm, "null algorithm name");
             try {
                 Object[] objs = Security.getImpl(algorithm,
                                                  "AlgorithmParameterGenerator",
@@ -197,17 +201,20 @@
      *
      * @param provider the string name of the Provider.
      *
-     * @return the new AlgorithmParameterGenerator object.
+     * @return the new {@code AlgorithmParameterGenerator} object
      *
-     * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if an
+     *         {@code AlgorithmParameterGeneratorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
@@ -215,6 +222,7 @@
                                                           String provider)
         throws NoSuchAlgorithmException, NoSuchProviderException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null || provider.length() == 0)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm,
@@ -241,15 +249,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @param provider the Provider object.
+     * @param provider the {@code Provider} object.
      *
-     * @return the new AlgorithmParameterGenerator object.
+     * @return the new {@code AlgorithmParameterGenerator} object
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if an
+     *         {@code AlgorithmParameterGeneratorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -259,6 +271,7 @@
                                                           Provider provider)
         throws NoSuchAlgorithmException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm,
--- a/jdk/src/java.base/share/classes/java/security/AlgorithmParameters.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/AlgorithmParameters.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.security.spec.AlgorithmParameterSpec;
 import java.security.spec.InvalidParameterSpecException;
+import java.util.Objects;
 
 /**
  * This class is used as an opaque representation of cryptographic parameters.
@@ -140,16 +141,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new parameter object.
+     * @return the new parameter object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports an
-     *          AlgorithmParametersSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports an
+     *         {@code AlgorithmParametersSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static AlgorithmParameters getInstance(String algorithm)
     throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         try {
             Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
                                              (String)null);
@@ -184,17 +188,19 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new parameter object.
+     * @return the new parameter object
      *
-     * @exception NoSuchAlgorithmException if an AlgorithmParametersSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if an {@code AlgorithmParametersSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
@@ -202,6 +208,7 @@
                                                   String provider)
         throws NoSuchAlgorithmException, NoSuchProviderException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null || provider.length() == 0)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
@@ -231,13 +238,16 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new parameter object.
+     * @return the new parameter object
+     *
+     * @throws IllegalArgumentException if the provider is {@code null}
      *
-     * @exception NoSuchAlgorithmException if an AlgorithmParameterGeneratorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if an
+     *         {@code AlgorithmParameterGeneratorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -247,6 +257,7 @@
                                                   Provider provider)
         throws NoSuchAlgorithmException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm, "AlgorithmParameters",
--- a/jdk/src/java.base/share/classes/java/security/KeyFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/KeyFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -167,16 +167,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new KeyFactory object.
+     * @return the new {@code KeyFactory} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyFactorySpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyFactorySpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         return new KeyFactory(algorithm);
     }
 
@@ -200,22 +203,25 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new KeyFactory object.
+     * @return the new {@code KeyFactory} object
      *
-     * @exception NoSuchAlgorithmException if a KeyFactorySpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyFactory getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("KeyFactory",
             KeyFactorySpi.class, algorithm, provider);
         return new KeyFactory((KeyFactorySpi)instance.impl,
@@ -239,13 +245,16 @@
      *
      * @param provider the provider.
      *
-     * @return the new KeyFactory object.
+     * @return the new {@code KeyFactory} object
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a KeyFactorySpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code KeyFactorySpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -253,6 +262,7 @@
      */
     public static KeyFactory getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("KeyFactory",
             KeyFactorySpi.class, algorithm, provider);
         return new KeyFactory((KeyFactorySpi)instance.impl,
--- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -209,16 +209,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyPairGeneratorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyPairGeneratorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyPairGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         List<Service> list =
                 GetInstance.getServices("KeyPairGenerator", algorithm);
         Iterator<Service> t = list.iterator();
@@ -267,23 +270,26 @@
      *
      * @param provider the string name of the provider.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
      *
-     * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static KeyPairGenerator getInstance(String algorithm,
             String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("KeyPairGenerator",
                 KeyPairGeneratorSpi.class, algorithm, provider);
         return getInstance(instance, algorithm);
@@ -306,13 +312,16 @@
      *
      * @param provider the provider.
      *
-     * @return the new KeyPairGenerator object.
+     * @return the new {@code KeyPairGenerator} object
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a KeyPairGeneratorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code KeyPairGeneratorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -320,6 +329,7 @@
      */
     public static KeyPairGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("KeyPairGenerator",
                 KeyPairGeneratorSpi.class, algorithm, provider);
         return getInstance(instance, algorithm);
--- a/jdk/src/java.base/share/classes/java/security/KeyStore.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/KeyStore.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,7 +26,6 @@
 package java.security;
 
 import java.io.*;
-import java.net.URI;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
@@ -855,17 +854,20 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard keystore types.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
      *
-     * @exception KeyStoreException if no Provider supports a
-     *          KeyStoreSpi implementation for the
-     *          specified type.
+     * @throws KeyStoreException if no {@code Provider} supports a
+     *         {@code KeyStoreSpi} implementation for the
+     *         specified type
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see Provider
      */
     public static KeyStore getInstance(String type)
         throws KeyStoreException
     {
+        Objects.requireNonNull(type, "null type name");
         try {
             Object[] objs = Security.getImpl(type, "KeyStore", (String)null);
             return new KeyStore((KeyStoreSpi)objs[0], (Provider)objs[1], type);
@@ -895,23 +897,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
      *
-     * @exception KeyStoreException if a KeyStoreSpi
-     *          implementation for the specified type is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws KeyStoreException if a {@code KeyStoreSpi}
+     *         implementation for the specified type is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see Provider
      */
     public static KeyStore getInstance(String type, String provider)
         throws KeyStoreException, NoSuchProviderException
     {
+        Objects.requireNonNull(type, "null type name");
         if (provider == null || provider.length() == 0)
             throw new IllegalArgumentException("missing provider");
         try {
@@ -938,13 +943,16 @@
      *
      * @param provider the provider.
      *
-     * @return a keystore object of the specified type.
+     * @return a keystore object of the specified type
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception KeyStoreException if KeyStoreSpi
-     *          implementation for the specified type is not available
-     *          from the specified Provider object.
+     * @throws KeyStoreException if {@code KeyStoreSpi}
+     *         implementation for the specified type is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see Provider
      *
@@ -953,6 +961,7 @@
     public static KeyStore getInstance(String type, Provider provider)
         throws KeyStoreException
     {
+        Objects.requireNonNull(type, "null type name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
         try {
--- a/jdk/src/java.base/share/classes/java/security/MessageDigest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/MessageDigest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,13 +26,8 @@
 package java.security;
 
 import java.util.*;
-import java.lang.*;
-import java.io.IOException;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
-import java.io.InputStream;
-import java.io.ByteArrayInputStream;
-import java.security.InvalidKeyException;
 import java.nio.ByteBuffer;
 
 import sun.security.util.Debug;
@@ -163,16 +158,20 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return a Message Digest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          MessageDigestSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code MessageDigestSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static MessageDigest getInstance(String algorithm)
     throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         try {
             MessageDigest md;
             Object[] objs = Security.getImpl(algorithm, "MessageDigest",
@@ -216,23 +215,27 @@
      *
      * @param provider the name of the provider.
      *
-     * @return a MessageDigest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a MessageDigestSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code MessageDigestSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static MessageDigest getInstance(String algorithm, String provider)
         throws NoSuchAlgorithmException, NoSuchProviderException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null || provider.length() == 0)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
@@ -265,13 +268,17 @@
      *
      * @param provider the provider.
      *
-     * @return a MessageDigest object that implements the specified algorithm.
+     * @return a {@code MessageDigest} object that implements the
+     *         specified algorithm
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a MessageDigestSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code MessageDigestSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -281,6 +288,7 @@
                                             Provider provider)
         throws NoSuchAlgorithmException
     {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (provider == null)
             throw new IllegalArgumentException("missing provider");
         Object[] objs = Security.getImpl(algorithm, "MessageDigest", provider);
--- a/jdk/src/java.base/share/classes/java/security/Policy.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/Policy.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,6 +29,7 @@
 import java.util.Enumeration;
 import java.util.WeakHashMap;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.Objects;
 import sun.security.jca.GetInstance;
 import sun.security.util.Debug;
 import sun.security.util.SecurityConstants;
@@ -372,26 +373,26 @@
      *
      * @param params parameters for the Policy, which may be null.
      *
-     * @return the new Policy object.
+     * @return the new {@code Policy} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Policy instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified parameters
+     *         are not understood by the {@code PolicySpi} implementation
+     *         from the selected {@code Provider}
      *
-     * @exception IllegalArgumentException if the specified parameters
-     *          are not understood by the PolicySpi implementation
-     *          from the selected Provider.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports
+     *         a {@code PolicySpi} implementation for the specified type
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi
-     *          implementation for the specified type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Policy} instance for the specified type.
      *
      * @see Provider
      * @since 1.6
      */
     public static Policy getInstance(String type, Policy.Parameters params)
                 throws NoSuchAlgorithmException {
-
+        Objects.requireNonNull(type, "null type name");
         checkPermission(type);
         try {
             GetInstance.Instance instance = GetInstance.getInstance("Policy",
@@ -428,23 +429,24 @@
      *
      * @param provider the provider.
      *
-     * @return the new Policy object.
+     * @return the new {@code Policy} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Policy instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified provider
+     *         is {@code null} or empty, or if the specified parameters are
+     *         not understood by the {@code PolicySpi} implementation from
+     *         the specified provider
      *
-     * @exception IllegalArgumentException if the specified provider
-     *          is null or empty,
-     *          or if the specified parameters are not understood by
-     *          the PolicySpi implementation from the specified provider.
+     * @throws NoSuchAlgorithmException if the specified provider does not
+     *         support a {@code PolicySpi} implementation for the specified
+     *         type
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
-     * @exception NoSuchAlgorithmException if the specified provider does not
-     *          support a PolicySpi implementation for the specified type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Policy} instance for the specified type
      *
      * @see Provider
      * @since 1.6
@@ -454,6 +456,7 @@
                                 String provider)
                 throws NoSuchProviderException, NoSuchAlgorithmException {
 
+        Objects.requireNonNull(type, "null type name");
         if (provider == null || provider.length() == 0) {
             throw new IllegalArgumentException("missing provider");
         }
@@ -492,19 +495,21 @@
      *
      * @param provider the Provider.
      *
-     * @return the new Policy object.
+     * @return the new {@code Policy} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Policy instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified {@code Provider}
+     *         is {@code null}, or if the specified parameters are not
+     *         understood by the {@code PolicySpi} implementation from the
+     *         specified {@code Provider}
      *
-     * @exception IllegalArgumentException if the specified Provider is null,
-     *          or if the specified parameters are not understood by
-     *          the PolicySpi implementation from the specified Provider.
+     * @throws NoSuchAlgorithmException if the specified {@code Provider}
+     *         does not support a {@code PolicySpi} implementation for
+     *         the specified type
      *
-     * @exception NoSuchAlgorithmException if the specified Provider does not
-     *          support a PolicySpi implementation for the specified type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Policy} instance for the specified type
      *
      * @see Provider
      * @since 1.6
@@ -514,6 +519,7 @@
                                 Provider provider)
                 throws NoSuchAlgorithmException {
 
+        Objects.requireNonNull(type, "null type name");
         if (provider == null) {
             throw new IllegalArgumentException("missing provider");
         }
--- a/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/SecureClassLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,8 +25,6 @@
 
 package java.security;
 
-import java.net.URL;
-import java.util.ArrayList;
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
@@ -114,6 +112,30 @@
     }
 
     /**
+     * Creates a new {@code SecureClassLoader} of the specified name and
+     * using the specified parent class loader for delegation.
+     *
+     * @param name class loader name; or {@code null} if not named
+     * @param parent the parent class loader
+     *
+     * @throws IllegalArgumentException if the given name is empty.
+     *
+     * @throws SecurityException  if a security manager exists and its
+     *         {@link SecurityManager#checkCreateClassLoader()} method
+     *         doesn't allow creation of a class loader.
+     *
+     * @since 9
+     */
+    protected SecureClassLoader(String name, ClassLoader parent) {
+        super(name, parent);
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkCreateClassLoader();
+        }
+        initialized = true;
+    }
+
+    /**
      * Converts an array of bytes into an instance of class Class,
      * with an optional CodeSource. Before the
      * class can be used it must be resolved.
--- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java	Fri Nov 11 16:44:36 2016 +0100
@@ -303,11 +303,13 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard RNG algorithm names.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          {@code SecureRandomSpi} implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code SecureRandomSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -315,6 +317,7 @@
      */
     public static SecureRandom getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("SecureRandom",
                 SecureRandomSpi.class, algorithm);
         return new SecureRandom((SecureRandomSpi)instance.impl,
@@ -341,17 +344,19 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
+     *
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
      * @throws NoSuchAlgorithmException if a {@code SecureRandomSpi}
      *         implementation for the specified algorithm is not
-     *         available from the specified provider.
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *         registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @throws IllegalArgumentException if the provider name is null
-     *         or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -359,6 +364,7 @@
      */
     public static SecureRandom getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("SecureRandom",
             SecureRandomSpi.class, algorithm, provider);
         return new SecureRandom((SecureRandomSpi)instance.impl,
@@ -382,13 +388,16 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
+     *
+     * @throws IllegalArgumentException if the specified provider is
+     *         {@code null}
      *
      * @throws NoSuchAlgorithmException if a {@code SecureRandomSpi}
      *         implementation for the specified algorithm is not available
-     *         from the specified {@code Provider} object.
+     *         from the specified {@code Provider} object
      *
-     * @throws IllegalArgumentException if the specified provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -396,6 +405,7 @@
      */
     public static SecureRandom getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("SecureRandom",
             SecureRandomSpi.class, algorithm, provider);
         return new SecureRandom((SecureRandomSpi)instance.impl,
@@ -433,13 +443,16 @@
      * @param params the {@code SecureRandomParameters}
      *               the newly created {@code SecureRandom} object must support.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
+     *
+     * @throws IllegalArgumentException if the specified params is
+     *         {@code null}
      *
      * @throws NoSuchAlgorithmException if no Provider supports a
      *         {@code SecureRandomSpi} implementation for the specified
-     *         algorithm and parameters.
+     *         algorithm and parameters
      *
-     * @throws IllegalArgumentException if the specified params is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -448,6 +461,7 @@
     public static SecureRandom getInstance(
             String algorithm, SecureRandomParameters params)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (params == null) {
             throw new IllegalArgumentException("params cannot be null");
         }
@@ -481,17 +495,19 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
+     *
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty, or params is {@code null}
      *
      * @throws NoSuchAlgorithmException if the specified provider does not
      *         support a {@code SecureRandomSpi} implementation for the
-     *         specified algorithm and parameters.
+     *         specified algorithm and parameters
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *         registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @throws IllegalArgumentException if the provider name is null
-     *         or empty, or params is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -500,6 +516,7 @@
     public static SecureRandom getInstance(String algorithm,
             SecureRandomParameters params, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (params == null) {
             throw new IllegalArgumentException("params cannot be null");
         }
@@ -531,14 +548,16 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code SecureRandom} object.
+     * @return the new {@code SecureRandom} object
+     *
+     * @throws IllegalArgumentException if the specified provider or params
+     *         is {@code null}
      *
      * @throws NoSuchAlgorithmException if the specified provider does not
      *         support a {@code SecureRandomSpi} implementation for the
-     *         specified algorithm and parameters.
+     *         specified algorithm and parameters
      *
-     * @throws IllegalArgumentException if the specified provider or params
-     *         is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -547,6 +566,7 @@
     public static SecureRandom getInstance(String algorithm,
             SecureRandomParameters params, Provider provider)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (params == null) {
             throw new IllegalArgumentException("params cannot be null");
         }
--- a/jdk/src/java.base/share/classes/java/security/Signature.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/Signature.java	Fri Nov 11 16:44:36 2016 +0100
@@ -213,16 +213,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new Signature object.
+     * @return the new {@code Signature} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          Signature implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code Signature} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static Signature getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         List<Service> list;
         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
             list = GetInstance.getServices(rsaIds);
@@ -335,22 +338,25 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new Signature object.
+     * @return the new {@code Signature} object
      *
-     * @exception NoSuchAlgorithmException if a SignatureSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code SignatureSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      */
     public static Signature getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
             // exception compatibility with existing code
             if ((provider == null) || (provider.length() == 0)) {
@@ -385,13 +391,15 @@
      *
      * @param provider the provider.
      *
-     * @return the new Signature object.
+     * @return the new {@code Signature} object
+     *
+     * @throws IllegalArgumentException if the provider is {@code null}
      *
-     * @exception NoSuchAlgorithmException if a SignatureSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code SignatureSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the provider is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see Provider
      *
@@ -399,6 +407,7 @@
      */
     public static Signature getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
             // exception compatibility with existing code
             if (provider == null) {
--- a/jdk/src/java.base/share/classes/java/security/cert/CertPathBuilder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertPathBuilder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,7 @@
 import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
-import sun.security.util.Debug;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -157,16 +157,19 @@
      * for information about standard algorithm names.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @throws NoSuchAlgorithmException if no Provider supports a
-     *          CertPathBuilderSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertPathBuilderSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
@@ -194,22 +197,25 @@
      * @param provider the name of the provider.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @throws NoSuchAlgorithmException if a CertPathBuilderSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
+     *
+     * @throws NoSuchAlgorithmException if a {@code CertPathBuilderSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm, String provider)
            throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm, provider);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
@@ -234,19 +240,22 @@
      * @param provider the provider.
      *
      * @return a {@code CertPathBuilder} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
+     *
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a CertPathBuilderSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code CertPathBuilderSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathBuilder getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathBuilder",
             CertPathBuilderSpi.class, algorithm, provider);
         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
--- a/jdk/src/java.base/share/classes/java/security/cert/CertPathValidator.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertPathValidator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,7 @@
 import java.security.PrivilegedAction;
 import java.security.Provider;
 import java.security.Security;
-import sun.security.util.Debug;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -158,16 +158,19 @@
      * for information about standard algorithm names.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          CertPathValidatorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertPathValidatorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
@@ -195,23 +198,26 @@
      * @param provider the name of the provider.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code CertPathValidatorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm, provider);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
@@ -236,19 +242,22 @@
      * @param provider the provider.
      *
      * @return a {@code CertPathValidator} object that implements the
-     *          specified algorithm.
+     *          specified algorithm
+     *
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a CertPathValidatorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code CertPathValidatorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified Provider object
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertPathValidator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = GetInstance.getInstance("CertPathValidator",
             CertPathValidatorSpi.class, algorithm, provider);
         return new CertPathValidator((CertPathValidatorSpi)instance.impl,
--- a/jdk/src/java.base/share/classes/java/security/cert/CertStore.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertStore.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,6 +33,7 @@
 import java.security.Provider;
 import java.security.Security;
 import java.util.Collection;
+import java.util.Objects;
 
 import sun.security.jca.*;
 import sun.security.jca.GetInstance.Instance;
@@ -218,20 +219,23 @@
      * @param params the initialization parameters (may be {@code null}).
      *
      * @return a {@code CertStore} object that implements the specified
-     *          {@code CertStore} type.
-     *
-     * @throws NoSuchAlgorithmException if no Provider supports a
-     *          CertStoreSpi implementation for the specified type.
+     *          {@code CertStore} type
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}.
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
+     *
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code CertStoreSpi} implementation for the specified type
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertStore getInstance(String type, CertStoreParameters params)
             throws InvalidAlgorithmParameterException,
             NoSuchAlgorithmException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params);
@@ -243,7 +247,8 @@
     }
 
     private static CertStore handleException(NoSuchAlgorithmException e)
-            throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
+            throws NoSuchAlgorithmException,
+            InvalidAlgorithmParameterException {
         Throwable cause = e.getCause();
         if (cause instanceof InvalidAlgorithmParameterException) {
             throw (InvalidAlgorithmParameterException)cause;
@@ -280,21 +285,23 @@
      * @param provider the name of the provider.
      *
      * @return a {@code CertStore} object that implements the
-     *          specified type.
+     *          specified type
      *
-     * @throws NoSuchAlgorithmException if a CertStoreSpi
-     *          implementation for the specified type is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null} or empty
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}.
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
+     *
+     * @throws NoSuchAlgorithmException if a {@code CertStoreSpi}
+     *         implementation for the specified type is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null or empty.
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
@@ -302,6 +309,7 @@
             CertStoreParameters params, String provider)
             throws InvalidAlgorithmParameterException,
             NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params, provider);
@@ -338,24 +346,27 @@
      * @param provider the provider.
      *
      * @return a {@code CertStore} object that implements the
-     *          specified type.
+     *          specified type
      *
-     * @exception NoSuchAlgorithmException if a CertStoreSpi
-     *          implementation for the specified type is not available
-     *          from the specified Provider object.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         null
      *
      * @throws InvalidAlgorithmParameterException if the specified
-     *          initialization parameters are inappropriate for this
-     *          {@code CertStore}
+     *         initialization parameters are inappropriate for this
+     *         {@code CertStore}
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws NoSuchAlgorithmException if a {@code CertStoreSpi}
+     *         implementation for the specified type is not available
+     *         from the specified Provider object
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static CertStore getInstance(String type, CertStoreParameters params,
             Provider provider) throws NoSuchAlgorithmException,
             InvalidAlgorithmParameterException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertStore",
                 CertStoreSpi.class, type, params, provider);
--- a/jdk/src/java.base/share/classes/java/security/cert/CertificateFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/security/cert/CertificateFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,10 +29,9 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.security.Provider;
 import java.security.Security;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchProviderException;
 
@@ -177,16 +176,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard certificate types.
      *
-     * @return a certificate factory object for the specified type.
+     * @return a certificate factory object for the specified type
      *
-     * @exception CertificateException if no Provider supports a
-     *          CertificateFactorySpi implementation for the
-     *          specified type.
+     * @throws CertificateException if no {@code Provider} supports a
+     *         {@code CertificateFactorySpi} implementation for the
+     *         specified type
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final CertificateFactory getInstance(String type)
             throws CertificateException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertificateFactory",
                 CertificateFactorySpi.class, type);
@@ -217,23 +219,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return a certificate factory object for the specified type.
+     * @return a certificate factory object for the specified type
      *
-     * @exception CertificateException if a CertificateFactorySpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws CertificateException if a {@code CertificateFactorySpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
      *
-     * @exception IllegalArgumentException if the provider name is null
-     *          or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final CertificateFactory getInstance(String type,
             String provider) throws CertificateException,
             NoSuchProviderException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertificateFactory",
                 CertificateFactorySpi.class, type, provider);
@@ -260,14 +265,16 @@
      * for information about standard certificate types.
      * @param provider the provider.
      *
-     * @return a certificate factory object for the specified type.
+     * @return a certificate factory object for the specified type
      *
-     * @exception CertificateException if a CertificateFactorySpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws CertificateException if a {@code CertificateFactorySpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the {@code provider} is
-     *          null.
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
+     *
+     * @throws NullPointerException if {@code type} is {@code null}
      *
      * @see java.security.Provider
      *
@@ -275,6 +282,7 @@
      */
     public static final CertificateFactory getInstance(String type,
             Provider provider) throws CertificateException {
+        Objects.requireNonNull(type, "null type name");
         try {
             Instance instance = GetInstance.getInstance("CertificateFactory",
                 CertificateFactorySpi.class, type, provider);
--- a/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/ImmutableCollections.java	Fri Nov 11 16:44:36 2016 +0100
@@ -53,7 +53,8 @@
      */
     static final int SALT;
     static {
-        SALT = new Random().nextInt();
+        long nt = System.nanoTime();
+        SALT = (int)((nt >>> 32) ^ nt);
     }
 
     /** No instances. */
@@ -63,7 +64,7 @@
      * The reciprocal of load factor. Given a number of elements
      * to store, multiply by this factor to get the table size.
      */
-    static final double EXPAND_FACTOR = 2.0;
+    static final int EXPAND_FACTOR = 2;
 
     static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
 
@@ -84,7 +85,14 @@
     }
 
     static final class List0<E> extends AbstractImmutableList<E> {
-        List0() { }
+        private static final List0<?> INSTANCE = new List0<>();
+
+        @SuppressWarnings("unchecked")
+        static <T> List0<T> instance() {
+            return (List0<T>) INSTANCE;
+        }
+
+        private List0() { }
 
         @Override
         public int size() {
@@ -214,7 +222,14 @@
     }
 
     static final class Set0<E> extends AbstractImmutableSet<E> {
-        Set0() { }
+        private static final Set0<?> INSTANCE = new Set0<>();
+
+        @SuppressWarnings("unchecked")
+        static <T> Set0<T> instance() {
+            return (Set0<T>) INSTANCE;
+        }
+
+        private Set0() { }
 
         @Override
         public int size() {
@@ -351,7 +366,7 @@
         SetN(E... input) {
             size = input.length; // implicit nullcheck of input
 
-            elements = (E[])new Object[(int)Math.ceil(EXPAND_FACTOR * input.length)];
+            elements = (E[])new Object[EXPAND_FACTOR * input.length];
             for (int i = 0; i < input.length; i++) {
                 E e = Objects.requireNonNull(input[i]);
                 int idx = probe(e);
@@ -450,7 +465,14 @@
     }
 
     static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
-        Map0() { }
+        private static final Map0<?,?> INSTANCE = new Map0<>();
+
+        @SuppressWarnings("unchecked")
+        static <K,V> Map0<K,V> instance() {
+            return (Map0<K,V>) INSTANCE;
+        }
+
+        private Map0() { }
 
         @Override
         public Set<Map.Entry<K,V>> entrySet() {
@@ -529,7 +551,7 @@
             }
             size = input.length >> 1;
 
-            int len = (int)Math.ceil(EXPAND_FACTOR * input.length);
+            int len = EXPAND_FACTOR * input.length;
             len = (len + 1) & ~1; // ensure table is even length
             table = new Object[len];
 
@@ -789,7 +811,7 @@
                     return Set.of(array);
                 case IMM_MAP:
                     if (array.length == 0) {
-                        return new ImmutableCollections.Map0<>();
+                        return ImmutableCollections.Map0.instance();
                     } else if (array.length == 2) {
                         return new ImmutableCollections.Map1<>(array[0], array[1]);
                     } else {
--- a/jdk/src/java.base/share/classes/java/util/List.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/List.java	Fri Nov 11 16:44:36 2016 +0100
@@ -786,7 +786,7 @@
      * @since 9
      */
     static <E> List<E> of() {
-        return new ImmutableCollections.List0<>();
+        return ImmutableCollections.List0.instance();
     }
 
     /**
@@ -1030,7 +1030,7 @@
         Objects.requireNonNull(elements);
         switch (elements.length) {
             case 0:
-                return new ImmutableCollections.List0<>();
+                return ImmutableCollections.List0.instance();
             case 1:
                 return new ImmutableCollections.List1<>(elements[0]);
             case 2:
--- a/jdk/src/java.base/share/classes/java/util/Map.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Map.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1286,7 +1286,7 @@
      * @since 9
      */
     static <K, V> Map<K, V> of() {
-        return new ImmutableCollections.Map0<>();
+        return ImmutableCollections.Map0.instance();
     }
 
     /**
@@ -1604,7 +1604,7 @@
     static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
         Objects.requireNonNull(entries);
         if (entries.length == 0) {
-            return new ImmutableCollections.Map0<>();
+            return ImmutableCollections.Map0.instance();
         } else if (entries.length == 1) {
             return new ImmutableCollections.Map1<>(entries[0].getKey(),
                                                    entries[0].getValue());
--- a/jdk/src/java.base/share/classes/java/util/Scanner.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Scanner.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1267,6 +1267,9 @@
     // The next operation should occur in the specified radix but
     // the default is left untouched.
     private void setRadix(int radix) {
+        if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
+            throw new IllegalArgumentException("radix:"+radix);
+
         if (this.radix != radix) {
             // Force rebuilding and recompilation of radix dependent patterns
             integerPattern = null;
@@ -1811,10 +1814,15 @@
      * interpreted as a byte value in the specified radix using the
      * {@link #nextByte} method. The scanner does not advance past any input.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as a byte value
      * @return true if and only if this scanner's next token is a valid
      *         byte value
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public boolean hasNextByte(int radix) {
         setRadix(radix);
@@ -1869,6 +1877,10 @@
      * {@link Byte#parseByte(String, int) Byte.parseByte} with the
      * specified radix.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as a byte value
      * @return the {@code byte} scanned from the input
      * @throws InputMismatchException
@@ -1876,6 +1888,7 @@
      *         regular expression, or is out of range
      * @throws NoSuchElementException if input is exhausted
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public byte nextByte(int radix) {
         // Check cached result
@@ -1917,10 +1930,15 @@
      * interpreted as a short value in the specified radix using the
      * {@link #nextShort} method. The scanner does not advance past any input.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as a short value
      * @return true if and only if this scanner's next token is a valid
      *         short value in the specified radix
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public boolean hasNextShort(int radix) {
         setRadix(radix);
@@ -1975,6 +1993,10 @@
      * {@link Short#parseShort(String, int) Short.parseShort} with the
      * specified radix.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as a short value
      * @return the {@code short} scanned from the input
      * @throws InputMismatchException
@@ -1982,6 +2004,7 @@
      *         regular expression, or is out of range
      * @throws NoSuchElementException if input is exhausted
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public short nextShort(int radix) {
         // Check cached result
@@ -2023,10 +2046,15 @@
      * interpreted as an int value in the specified radix using the
      * {@link #nextInt} method. The scanner does not advance past any input.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as an int value
      * @return true if and only if this scanner's next token is a valid
      *         int value
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public boolean hasNextInt(int radix) {
         setRadix(radix);
@@ -2105,6 +2133,10 @@
      * {@link Integer#parseInt(String, int) Integer.parseInt} with the
      * specified radix.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as an int value
      * @return the {@code int} scanned from the input
      * @throws InputMismatchException
@@ -2112,6 +2144,7 @@
      *         regular expression, or is out of range
      * @throws NoSuchElementException if input is exhausted
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public int nextInt(int radix) {
         // Check cached result
@@ -2153,10 +2186,15 @@
      * interpreted as a long value in the specified radix using the
      * {@link #nextLong} method. The scanner does not advance past any input.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as a long value
      * @return true if and only if this scanner's next token is a valid
      *         long value
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public boolean hasNextLong(int radix) {
         setRadix(radix);
@@ -2211,6 +2249,10 @@
      * {@link Long#parseLong(String, int) Long.parseLong} with the
      * specified radix.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as an int value
      * @return the {@code long} scanned from the input
      * @throws InputMismatchException
@@ -2218,6 +2260,7 @@
      *         regular expression, or is out of range
      * @throws NoSuchElementException if input is exhausted
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public long nextLong(int radix) {
         // Check cached result
@@ -2450,10 +2493,15 @@
      * the {@link #nextBigInteger} method. The scanner does not advance past
      * any input.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token as an integer
      * @return true if and only if this scanner's next token is a valid
      *         {@code BigInteger}
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public boolean hasNextBigInteger(int radix) {
         setRadix(radix);
@@ -2504,6 +2552,10 @@
      * java.math.BigInteger#BigInteger(java.lang.String)
      * BigInteger(String, int)} constructor with the specified radix.
      *
+     * <p>If the radix is less than {@link Character#MIN_RADIX Character.MIN_RADIX}
+     * or greater than {@link Character#MAX_RADIX Character.MAX_RADIX}, then an
+     * {@code IllegalArgumentException} is thrown.
+     *
      * @param radix the radix used to interpret the token
      * @return the {@code BigInteger} scanned from the input
      * @throws InputMismatchException
@@ -2511,6 +2563,7 @@
      *         regular expression, or is out of range
      * @throws NoSuchElementException if the input is exhausted
      * @throws IllegalStateException if this scanner is closed
+     * @throws IllegalArgumentException if the radix is out of range
      */
     public BigInteger nextBigInteger(int radix) {
         // Check cached result
--- a/jdk/src/java.base/share/classes/java/util/Set.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/Set.java	Fri Nov 11 16:44:36 2016 +0100
@@ -448,7 +448,7 @@
      * @since 9
      */
     static <E> Set<E> of() {
-        return new ImmutableCollections.Set0<>();
+        return ImmutableCollections.Set0.instance();
     }
 
     /**
@@ -692,7 +692,7 @@
         Objects.requireNonNull(elements);
         switch (elements.length) {
             case 0:
-                return new ImmutableCollections.Set0<>();
+                return ImmutableCollections.Set0.instance();
             case 1:
                 return new ImmutableCollections.Set1<>(elements[0]);
             case 2:
--- a/jdk/src/java.base/share/classes/java/util/stream/Collectors.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/util/stream/Collectors.java	Fri Nov 11 16:44:36 2016 +0100
@@ -508,7 +508,7 @@
      * transformation.  For example, one could adapt the {@link #toList()}
      * collector to always produce an immutable list with:
      * <pre>{@code
-     *     List<String> people
+     *     List<String> list
      *         = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
      * }</pre>
      *
--- a/jdk/src/java.base/share/classes/javax/crypto/Cipher.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/Cipher.java	Fri Nov 11 16:44:36 2016 +0100
@@ -493,21 +493,24 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard transformation names.
      *
-     * @return a cipher that implements the requested transformation.
+     * @return a cipher that implements the requested transformation
      *
-     * @exception NoSuchAlgorithmException if {@code transformation}
-     *          is null, empty, in an invalid format,
-     *          or if no Provider supports a CipherSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if {@code transformation}
+     *         is {@code null}, empty, in an invalid format,
+     *         or if no {@code Provider} supports a {@code CipherSpi}
+     *         implementation for the specified algorithm
      *
-     * @exception NoSuchPaddingException if {@code transformation}
-     *          contains a padding scheme that is not available.
+     * @throws NoSuchPaddingException if {@code transformation}
+     *         contains a padding scheme that is not available
      *
      * @see java.security.Provider
      */
     public static final Cipher getInstance(String transformation)
             throws NoSuchAlgorithmException, NoSuchPaddingException
     {
+        if ((transformation == null) || transformation.equals("")) {
+            throw new NoSuchAlgorithmException("Null or empty transformation");
+        }
         List<Transform> transforms = getTransforms(transformation);
         List<ServiceId> cipherServices = new ArrayList<>(transforms.size());
         for (Transform transform : transforms) {
@@ -570,21 +573,22 @@
      *
      * @param provider the name of the provider.
      *
-     * @return a cipher that implements the requested transformation.
+     * @return a cipher that implements the requested transformation
      *
-     * @exception NoSuchAlgorithmException if {@code transformation}
-     *          is null, empty, in an invalid format,
-     *          or if a CipherSpi implementation for the specified algorithm
-     *          is not available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if {@code transformation}
+     *         is {@code null}, empty, in an invalid format,
+     *         or if a {@code CipherSpi} implementation for the
+     *         specified algorithm is not available from the specified
+     *         provider
      *
-     * @exception NoSuchPaddingException if {@code transformation}
-     *          contains a padding scheme that is not available.
+     * @throws NoSuchPaddingException if {@code transformation}
+     *         contains a padding scheme that is not available
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
      * @see java.security.Provider
      */
@@ -593,6 +597,9 @@
             throws NoSuchAlgorithmException, NoSuchProviderException,
             NoSuchPaddingException
     {
+        if ((transformation == null) || transformation.equals("")) {
+            throw new NoSuchAlgorithmException("Null or empty transformation");
+        }
         if ((provider == null) || (provider.length() == 0)) {
             throw new IllegalArgumentException("Missing provider");
         }
@@ -622,18 +629,19 @@
      *
      * @param provider the provider.
      *
-     * @return a cipher that implements the requested transformation.
+     * @return a cipher that implements the requested transformation
+     *
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null}
      *
-     * @exception NoSuchAlgorithmException if {@code transformation}
-     *          is null, empty, in an invalid format,
-     *          or if a CipherSpi implementation for the specified algorithm
-     *          is not available from the specified Provider object.
+     * @throws NoSuchAlgorithmException if {@code transformation}
+     *         is {@code null}, empty, in an invalid format,
+     *         or if a {@code CipherSpi} implementation for the
+     *         specified algorithm is not available from the specified
+     *         {@code Provider} object
      *
-     * @exception NoSuchPaddingException if {@code transformation}
-     *          contains a padding scheme that is not available.
-     *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null.
+     * @throws NoSuchPaddingException if {@code transformation}
+     *         contains a padding scheme that is not available
      *
      * @see java.security.Provider
      */
@@ -641,6 +649,9 @@
                                            Provider provider)
             throws NoSuchAlgorithmException, NoSuchPaddingException
     {
+        if ((transformation == null) || transformation.equals("")) {
+            throw new NoSuchAlgorithmException("Null or empty transformation");
+        }
         if (provider == null) {
             throw new IllegalArgumentException("Missing provider");
         }
--- a/jdk/src/java.base/share/classes/javax/crypto/ExemptionMechanism.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/ExemptionMechanism.java	Fri Nov 11 16:44:36 2016 +0100
@@ -34,6 +34,7 @@
 import java.security.InvalidKeyException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.spec.AlgorithmParameterSpec;
+import java.util.Objects;
 
 import sun.security.jca.GetInstance.Instance;
 
@@ -128,19 +129,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard exemption mechanism names.
      *
-     * @return the new <code>ExemptionMechanism</code> object.
+     * @return the new {@code ExemptionMechanism} object
      *
-     * @exception NullPointerException if <code>algorithm</code>
-     *          is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports an
+     *         {@code ExemptionMechanismSpi} implementation for the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports an
-     *          ExemptionMechanismSpi implementation for the
-     *          specified algorithm.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final ExemptionMechanism getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("ExemptionMechanism",
                 ExemptionMechanismSpi.class, algorithm);
         return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
@@ -169,26 +170,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new <code>ExemptionMechanism</code> object.
+     * @return the new {@code ExemptionMechanism} object
      *
-     * @exception NullPointerException if <code>algorithm</code>
-     *          is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws NoSuchAlgorithmException if an {@code ExemptionMechanismSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the <code>provider</code>
-     *          is null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final ExemptionMechanism getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("ExemptionMechanism",
                 ExemptionMechanismSpi.class, algorithm, provider);
         return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
@@ -213,22 +214,22 @@
      *
      * @param provider the provider.
      *
-     * @return the new <code>ExemptionMechanism</code> object.
+     * @return the new {@code ExemptionMechanism} object
      *
-     * @exception NullPointerException if <code>algorithm</code>
-     *          is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is null
      *
-     * @exception NoSuchAlgorithmException if an ExemptionMechanismSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if an {@code ExemptionMechanismSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider object}
      *
-     * @exception IllegalArgumentException if the <code>provider</code>
-     *          is null.
+     * @exception NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final ExemptionMechanism getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("ExemptionMechanism",
                 ExemptionMechanismSpi.class, algorithm, provider);
         return new ExemptionMechanism((ExemptionMechanismSpi)instance.impl,
--- a/jdk/src/java.base/share/classes/javax/crypto/KeyAgreement.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/KeyAgreement.java	Fri Nov 11 16:44:36 2016 +0100
@@ -165,19 +165,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new {@code KeyAgreement} object.
+     * @return the new {@code KeyAgreement} object
      *
-     * @exception NullPointerException if the specified algorithm
-     *          is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyAgreementSpi} implementation for the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyAgreementSpi implementation for the
-     *          specified algorithm.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyAgreement getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         List<Service> services =
                 GetInstance.getServices("KeyAgreement", algorithm);
         // make sure there is at least one service from a signed provider
@@ -214,26 +214,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code KeyAgreement} object.
+     * @return the new {@code KeyAgreement} object
      *
-     * @exception NullPointerException if the specified algorithm
-     *          is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NoSuchAlgorithmException if a KeyAgreementSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws NoSuchAlgorithmException if a {@code KeyAgreementSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyAgreement getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance
                 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
         return new KeyAgreement((KeyAgreementSpi)instance.impl,
@@ -258,22 +258,22 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code KeyAgreement} object.
+     * @return the new {@code KeyAgreement} object
      *
-     * @exception NullPointerException if the specified algorithm
-     *          is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null}
      *
-     * @exception NoSuchAlgorithmException if a KeyAgreementSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code KeyAgreementSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified Provider object
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyAgreement getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance
                 ("KeyAgreement", KeyAgreementSpi.class, algorithm, provider);
         return new KeyAgreement((KeyAgreementSpi)instance.impl,
--- a/jdk/src/java.base/share/classes/javax/crypto/KeyGenerator.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/KeyGenerator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -216,18 +216,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new {@code KeyGenerator} object.
-     *
-     * @exception NullPointerException if the specified algorithm is null.
+     * @return the new {@code KeyGenerator} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyGeneratorSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyGeneratorSpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyGenerator getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         return new KeyGenerator(algorithm);
     }
 
@@ -251,25 +252,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code KeyGenerator} object.
+     * @return the new {@code KeyGenerator} object
      *
-     * @exception NullPointerException if the specified algorithm is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyGenerator getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("KeyGenerator",
                 KeyGeneratorSpi.class, algorithm, provider);
         return new KeyGenerator((KeyGeneratorSpi)instance.impl,
@@ -293,21 +295,22 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code KeyGenerator} object.
+     * @return the new {@code KeyGenerator} object
      *
-     * @exception NullPointerException if the specified algorithm is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null}
      *
-     * @exception NoSuchAlgorithmException if a KeyGeneratorSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code KeyGeneratorSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyGenerator getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("KeyGenerator",
                 KeyGeneratorSpi.class, algorithm, provider);
         return new KeyGenerator((KeyGeneratorSpi)instance.impl,
--- a/jdk/src/java.base/share/classes/javax/crypto/Mac.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/Mac.java	Fri Nov 11 16:44:36 2016 +0100
@@ -166,16 +166,18 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new {@code Mac} object.
+     * @return the new {@code Mac} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          MacSpi implementation for the
-     *          specified algorithm.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code MacSpi} implementation for the specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final Mac getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         List<Service> services = GetInstance.getServices("Mac", algorithm);
         // make sure there is at least one service from a signed provider
         Iterator<Service> t = services.iterator();
@@ -210,22 +212,25 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code Mac} object.
+     * @return the new {@code Mac} object
      *
-     * @exception NoSuchAlgorithmException if a MacSpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if a {@code MacSpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null or empty.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final Mac getInstance(String algorithm, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance
                 ("Mac", MacSpi.class, algorithm, provider);
         return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
@@ -248,19 +253,22 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code Mac} object.
+     * @return the new {@code Mac} object
+     *
+     * @throws IllegalArgumentException if the {@code provider} is
+     *         {@code null}
      *
-     * @exception NoSuchAlgorithmException if a MacSpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code MacSpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final Mac getInstance(String algorithm, Provider provider)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance
                 ("Mac", MacSpi.class, algorithm, provider);
         return new Mac((MacSpi)instance.impl, instance.provider, algorithm);
--- a/jdk/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -152,19 +152,19 @@
      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
      * for information about standard algorithm names.
      *
-     * @return the new {@code SecretKeyFactory} object.
+     * @return the new {@code SecretKeyFactory} object
      *
-     * @exception NullPointerException if the specified algorithm
-     *          is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code SecretKeyFactorySpi} implementation for the
+     *         specified algorithm
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          SecretKeyFactorySpi implementation for the
-     *          specified algorithm.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final SecretKeyFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         return new SecretKeyFactory(algorithm);
     }
 
@@ -189,26 +189,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code SecretKeyFactory} object.
+     * @return the new {@code SecretKeyFactory} object
      *
-     * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null} or empty
      *
-     * @exception NullPointerException if the specified algorithm
-     *          is null.
+     * @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null or empty.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final SecretKeyFactory getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
                 SecretKeyFactorySpi.class, algorithm, provider);
         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
@@ -233,22 +233,22 @@
      *
      * @param provider the provider.
      *
-     * @return the new {@code SecretKeyFactory} object.
+     * @return the new {@code SecretKeyFactory} object
      *
-     * @exception NullPointerException if the specified algorithm
-     * is null.
+     * @throws IllegalArgumentException if the {@code provider}
+     *         is {@code null}
      *
-     * @exception NoSuchAlgorithmException if a SecretKeyFactorySpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code SecretKeyFactorySpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @exception IllegalArgumentException if the {@code provider}
-     *          is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final SecretKeyFactory getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         Instance instance = JceSecurity.getInstance("SecretKeyFactory",
                 SecretKeyFactorySpi.class, algorithm, provider);
         return new SecretKeyFactory((SecretKeyFactorySpi)instance.impl,
--- a/jdk/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/KeyManagerFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -27,6 +27,7 @@
 
 import java.security.Security;
 import java.security.*;
+import java.util.Objects;
 
 import sun.security.jca.GetInstance;
 
@@ -130,17 +131,19 @@
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
-     * @return the new <code>KeyManagerFactory</code> object.
+     * @return the new {@code KeyManagerFactory} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          KeyManagerFactorySpi implementation for the
-     *          specified algorithm.
-     * @exception NullPointerException if <code>algorithm</code> is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code KeyManagerFactorySpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyManagerFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("KeyManagerFactory", KeyManagerFactorySpi.class,
                 algorithm);
@@ -168,23 +171,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new <code>KeyManagerFactory</code> object.
+     * @return the new {@code KeyManagerFactory} object
      *
-     * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is {@code null}
+     *         or empty
+     *
+     * @throws NoSuchAlgorithmException if a {@code KeyManagerFactorySpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @throws IllegalArgumentException if the provider name is null or empty.
-     * @throws NullPointerException if <code>algorithm</code> is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyManagerFactory getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("KeyManagerFactory", KeyManagerFactorySpi.class,
                 algorithm, provider);
@@ -209,19 +215,21 @@
      *
      * @param provider an instance of the provider.
      *
-     * @return the new <code>KeyManagerFactory</code> object.
+     * @return the new {@code KeyManagerFactory} object
+     *
+     * @throws IllegalArgumentException if provider is {@code null}
      *
-     * @throws NoSuchAlgorithmException if a KeyManagerFactorySpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code @KeyManagerFactorySpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified Provider object
      *
-     * @throws IllegalArgumentException if provider is null.
-     * @throws NullPointerException if <code>algorithm</code> is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final KeyManagerFactory getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("KeyManagerFactory", KeyManagerFactorySpi.class,
                 algorithm, provider);
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLContext.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,6 +26,7 @@
 package javax.net.ssl;
 
 import java.security.*;
+import java.util.Objects;
 
 import sun.security.jca.GetInstance;
 
@@ -151,17 +152,19 @@
      *          Documentation</a>
      *          for information about standard protocol names.
      *
-     * @return the new {@code SSLContext} object.
+     * @return the new {@code SSLContext} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          SSLContextSpi implementation for the
-     *          specified protocol.
-     * @exception NullPointerException if protocol is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code SSLContextSpi} implementation for the
+     *         specified protocol
+     *
+     * @throws NullPointerException if {@code protocol} is {@code null}
      *
      * @see java.security.Provider
      */
     public static SSLContext getInstance(String protocol)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(protocol, "null protocol name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("SSLContext", SSLContextSpi.class, protocol);
         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
@@ -189,22 +192,25 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new {@code SSLContext} object.
+     * @return the new {@code SSLContext} object
      *
-     * @throws NoSuchAlgorithmException if a SSLContextSpi
-     *          implementation for the specified protocol is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is
+     *         {@code null} or empty
+     *
+     * @throws NoSuchAlgorithmException if a {@code SSLContextSpi}
+     *         implementation for the specified protocol is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @throws IllegalArgumentException if the provider name is null or empty.
-     * @throws NullPointerException if protocol is null.
+     * @throws NullPointerException if {@code protocol} is {@code null}
      *
      * @see java.security.Provider
      */
     public static SSLContext getInstance(String protocol, String provider)
             throws NoSuchAlgorithmException, NoSuchProviderException {
+        Objects.requireNonNull(protocol, "null protocol name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("SSLContext", SSLContextSpi.class, protocol, provider);
         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
@@ -229,19 +235,21 @@
      *
      * @param provider an instance of the provider.
      *
-     * @return the new {@code SSLContext} object.
+     * @return the new {@code SSLContext} object
+     *
+     * @throws IllegalArgumentException if the provider is {@code null}
      *
-     * @throws NoSuchAlgorithmException if a SSLContextSpi
-     *          implementation for the specified protocol is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code SSLContextSpi}
+     *         implementation for the specified protocol is not available
+     *         from the specified {@code Provider} object
      *
-     * @throws IllegalArgumentException if the provider is null.
-     * @throws NullPointerException if protocol is null.
+     * @throws NullPointerException if {@code protocol} is {@code null}
      *
      * @see java.security.Provider
      */
     public static SSLContext getInstance(String protocol, Provider provider)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(protocol, "null protocol name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("SSLContext", SSLContextSpi.class, protocol, provider);
         return new SSLContext((SSLContextSpi)instance.impl, instance.provider,
--- a/jdk/src/java.base/share/classes/javax/net/ssl/TrustManagerFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/net/ssl/TrustManagerFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -27,6 +27,7 @@
 
 import java.security.Security;
 import java.security.*;
+import java.util.Objects;
 
 import sun.security.jca.GetInstance;
 
@@ -144,17 +145,19 @@
      *          Java Secure Socket Extension Reference Guide </a>
      *          for information about standard algorithm names.
      *
-     * @return the new <code>TrustManagerFactory</code> object.
+     * @return the new {@code TrustManagerFactory} object
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          TrustManagerFactorySpi implementation for the
-     *          specified algorithm.
-     * @exception NullPointerException if algorithm is null.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code TrustManagerFactorySpi} implementation for the
+     *         specified algorithm
+     *
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final TrustManagerFactory getInstance(String algorithm)
             throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("TrustManagerFactory", TrustManagerFactorySpi.class,
                 algorithm);
@@ -182,23 +185,26 @@
      *
      * @param provider the name of the provider.
      *
-     * @return the new <code>TrustManagerFactory</code> object
+     * @return the new {@code TrustManagerFactory} object
      *
-     * @throws NoSuchAlgorithmException if a TrustManagerFactorySpi
-     *          implementation for the specified algorithm is not
-     *          available from the specified provider.
+     * @throws IllegalArgumentException if the provider name is
+     *         {@code null} or empty
+     *
+     * @throws NoSuchAlgorithmException if a {@code TrustManagerFactorySpi}
+     *         implementation for the specified algorithm is not
+     *         available from the specified provider
      *
      * @throws NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     *         registered in the security provider list
      *
-     * @throws IllegalArgumentException if the provider name is null or empty.
-     * @throws NullPointerException if algorithm is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final TrustManagerFactory getInstance(String algorithm,
             String provider) throws NoSuchAlgorithmException,
             NoSuchProviderException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("TrustManagerFactory", TrustManagerFactorySpi.class,
                 algorithm, provider);
@@ -223,19 +229,21 @@
      *
      * @param provider an instance of the provider.
      *
-     * @return the new <code>TrustManagerFactory</code> object.
+     * @return the new {@code TrustManagerFactory} object
+     *
+     * @throws IllegalArgumentException if the provider is {@code null}
      *
-     * @throws NoSuchAlgorithmException if a TrustManagerFactorySpi
-     *          implementation for the specified algorithm is not available
-     *          from the specified Provider object.
+     * @throws NoSuchAlgorithmException if a {@code TrustManagerFactorySpi}
+     *         implementation for the specified algorithm is not available
+     *         from the specified {@code Provider} object
      *
-     * @throws IllegalArgumentException if the provider is null.
-     * @throws NullPointerException if algorithm is null.
+     * @throws NullPointerException if {@code algorithm} is {@code null}
      *
      * @see java.security.Provider
      */
     public static final TrustManagerFactory getInstance(String algorithm,
             Provider provider) throws NoSuchAlgorithmException {
+        Objects.requireNonNull(algorithm, "null algorithm name");
         GetInstance.Instance instance = GetInstance.getInstance
                 ("TrustManagerFactory", TrustManagerFactorySpi.class,
                 algorithm, provider);
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java	Fri Nov 11 16:44:36 2016 +0100
@@ -329,27 +329,29 @@
      *
      * @param params parameters for the Configuration, which may be null.
      *
-     * @return the new Configuration object.
+     * @return the new {@code Configuration} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Configuration instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified parameters
+     *         are not understood by the {@code ConfigurationSpi}
+     *         implementation from the selected {@code Provider}
      *
-     * @exception IllegalArgumentException if the specified parameters
-     *          are not understood by the ConfigurationSpi implementation
-     *          from the selected Provider.
+     * @throws NoSuchAlgorithmException if no {@code Provider} supports a
+     *         {@code ConfigurationSpi} implementation for the specified type
      *
-     * @exception NoSuchAlgorithmException if no Provider supports a
-     *          ConfigurationSpi implementation for the specified type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Configuration} instance for the specified type
      *
      * @see Provider
+     *
      * @since 1.6
      */
     public static Configuration getInstance(String type,
                                 Configuration.Parameters params)
                 throws NoSuchAlgorithmException {
 
+        Objects.requireNonNull(type, "null type name");
         checkPermission(type);
         try {
             GetInstance.Instance instance = GetInstance.getInstance
@@ -387,24 +389,24 @@
      *
      * @param provider the provider.
      *
-     * @return the new Configuration object.
+     * @return the new {@code Configuration} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Configuration instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified provider
+     *         is {@code null} or empty, or if the specified parameters
+     *         are not understood by the {@code ConfigurationSpi}
+     *         implementation from the specified provider
      *
-     * @exception IllegalArgumentException if the specified provider
-     *          is null or empty,
-     *          or if the specified parameters are not understood by
-     *          the ConfigurationSpi implementation from the specified provider.
+     * @throws NoSuchProviderException if the specified provider is not
+     *         registered in the security provider list
      *
-     * @exception NoSuchProviderException if the specified provider is not
-     *          registered in the security provider list.
+     * @throws NoSuchAlgorithmException if the specified provider does not
+     *         support a {@code ConfigurationSpi} implementation for the
+     *         specified type
      *
-     * @exception NoSuchAlgorithmException if the specified provider does not
-     *          support a ConfigurationSpi implementation for the specified
-     *          type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Configuration} instance for the specified type
      *
      * @see Provider
      * @since 1.6
@@ -414,6 +416,7 @@
                                 String provider)
                 throws NoSuchProviderException, NoSuchAlgorithmException {
 
+        Objects.requireNonNull(type, "null type name");
         if (provider == null || provider.length() == 0) {
             throw new IllegalArgumentException("missing provider");
         }
@@ -453,20 +456,21 @@
      *
      * @param provider the Provider.
      *
-     * @return the new Configuration object.
+     * @return the new {@code Configuration} object
      *
-     * @exception SecurityException if the caller does not have permission
-     *          to get a Configuration instance for the specified type.
-     *
-     * @exception NullPointerException if the specified type is null.
+     * @throws IllegalArgumentException if the specified {@code Provider}
+     *         is {@code null}, or if the specified parameters are not
+     *         understood by the {@code ConfigurationSpi} implementation
+     *         from the specified Provider
      *
-     * @exception IllegalArgumentException if the specified Provider is null,
-     *          or if the specified parameters are not understood by
-     *          the ConfigurationSpi implementation from the specified Provider.
+     * @throws NoSuchAlgorithmException if the specified {@code Provider}
+     *         does not support a {@code ConfigurationSpi} implementation
+     *         for the specified type
      *
-     * @exception NoSuchAlgorithmException if the specified Provider does not
-     *          support a ConfigurationSpi implementation for the specified
-     *          type.
+     * @throws NullPointerException if {@code type} is {@code null}
+     *
+     * @throws SecurityException if the caller does not have permission
+     *         to get a {@code Configuration} instance for the specified type
      *
      * @see Provider
      * @since 1.6
@@ -476,6 +480,7 @@
                                 Provider provider)
                 throws NoSuchAlgorithmException {
 
+        Objects.requireNonNull(type, "null type name");
         if (provider == null) {
             throw new IllegalArgumentException("missing provider");
         }
--- a/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/jmod/JmodFile.java	Fri Nov 11 16:44:36 2016 +0100
@@ -176,6 +176,16 @@
     }
 
     /**
+     * Returns the {@code Entry} for a resource in a JMOD file section
+     * or {@code null} if not found.
+     */
+    public Entry getEntry(Section section, String name) {
+        String entry = section.jmodDir() + "/" + name;
+        ZipEntry ze = zipfile.getEntry(entry);
+        return (ze != null) ? new Entry(ze) : null;
+    }
+
+    /**
      * Opens an {@code InputStream} for reading the named entry of the given
      * section in this jmod file.
      *
@@ -185,7 +195,6 @@
     public InputStream getInputStream(Section section, String name)
         throws IOException
     {
-
         String entry = section.jmodDir() + "/" + name;
         ZipEntry e = zipfile.getEntry(entry);
         if (e == null) {
@@ -195,6 +204,15 @@
     }
 
     /**
+     * Opens an {@code InputStream} for reading an entry in the JMOD file.
+     *
+     * @throws IOException if an I/O error occurs
+     */
+    public InputStream getInputStream(Entry entry) throws IOException {
+        return zipfile.getInputStream(entry.zipEntry());
+    }
+
+    /**
      * Returns a stream of non-directory entries in this jmod file.
      */
     public Stream<Entry> stream() {
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -53,6 +53,7 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
+import java.util.stream.Stream;
 
 import jdk.internal.module.ModulePatcher.PatchedModuleReader;
 import jdk.internal.misc.VM;
@@ -144,9 +145,9 @@
     /**
      * Create a new instance.
      */
-    BuiltinClassLoader(BuiltinClassLoader parent, URLClassPath ucp) {
+    BuiltinClassLoader(String name, BuiltinClassLoader parent, URLClassPath ucp) {
         // ensure getParent() returns null when the parent is the boot loader
-        super(parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
+        super(name, parent == null || parent == ClassLoaders.bootLoader() ? null : parent);
 
         this.parent = parent;
         this.ucp = ucp;
@@ -749,6 +750,10 @@
             return Optional.empty();
         }
         @Override
+        public Stream<String> list() {
+            return Stream.empty();
+        }
+        @Override
         public void close() {
             throw new InternalError("Should not get here");
         }
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Fri Nov 11 16:44:36 2016 +0100
@@ -69,16 +69,17 @@
             bcp = toURLClassPath(s);
 
         // we have a class path if -cp is specified or -m is not specified.
-        // If neither is specified then default to -cp <working directory>.
+        // If neither is specified then default to -cp <working directory>
+        // If -cp is not specified and -m is specified, the value of
+        // java.class.path is an empty string, then no class path.
         URLClassPath ucp = null;
         String mainMid = System.getProperty("jdk.module.main");
         String cp = System.getProperty("java.class.path");
-        if (mainMid == null && cp == null)
+        if (cp == null)
             cp = "";
-        if (cp != null)
+        if (mainMid == null || cp.length() > 0)
             ucp = toURLClassPath(cp);
 
-
         // create the class loaders
         BOOT_LOADER = new BootClassLoader(bcp);
         PLATFORM_LOADER = new PlatformClassLoader(BOOT_LOADER);
@@ -117,7 +118,7 @@
      */
     private static class BootClassLoader extends BuiltinClassLoader {
         BootClassLoader(URLClassPath bcp) {
-            super(null, bcp);
+            super(null, null, bcp);
         }
 
         @Override
@@ -137,7 +138,7 @@
         }
 
         PlatformClassLoader(BootClassLoader parent) {
-            super(parent, null);
+            super("platform", parent, null);
         }
 
         /**
@@ -164,7 +165,7 @@
         final URLClassPath ucp;
 
         AppClassLoader(PlatformClassLoader parent, URLClassPath ucp) {
-            super(parent, ucp);
+            super("app", parent, ucp);
             this.ucp = ucp;
         }
 
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/loader/Loader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -53,6 +53,7 @@
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
 
 
 /**
@@ -534,6 +535,10 @@
             return Optional.empty();
         }
         @Override
+        public Stream<String> list() {
+            return Stream.empty();
+        }
+        @Override
         public void close() {
             throw new InternalError("Should not get here");
         }
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -137,13 +137,20 @@
     }
 
     public static boolean isSystem(Module m) {
-        ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<>() {
+        return AccessController.doPrivileged(new PrivilegedAction<>() {
             @Override
-            public ClassLoader run() {
-                return m.getClassLoader();
+            public Boolean run() {
+                final ClassLoader moduleCL = m.getClassLoader();
+                if (moduleCL == null) return true;
+                ClassLoader cl = ClassLoader.getPlatformClassLoader();
+                while (cl != null && moduleCL != cl) {
+                    cl = cl.getParent();
+                }
+                // returns true if moduleCL is the platform class loader
+                // or one of its ancestors.
+                return moduleCL == cl;
             }
         });
-        return cl == null;
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java	Fri Nov 11 16:44:36 2016 +0100
@@ -39,6 +39,7 @@
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
 import java.net.URI;
+import java.nio.file.Path;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -103,6 +104,11 @@
                                          ModuleHashes hashes);
 
     /**
+     * Returns the object with the hashes of other modules
+     */
+    Optional<ModuleHashes> hashes(ModuleDescriptor descriptor);
+
+    /**
      * Resolves a collection of root modules, with service binding
      * and the empty configuration as the parent. The post resolution
      * checks are optionally run.
@@ -120,8 +126,10 @@
                                      Supplier<ModuleReader> readerSupplier);
 
     /**
-     * Returns the object with the hashes of other modules
+     * Creates a ModuleFinder for a module path.
      */
-    Optional<ModuleHashes> hashes(ModuleDescriptor descriptor);
+    ModuleFinder newModulePath(Runtime.Version version,
+                               boolean isLinkPhase,
+                               Path... entries);
 
 }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ConfigurableModuleFinder.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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.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);
-
-}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -57,7 +57,15 @@
         cw.visit(Opcodes.V1_9, ACC_MODULE, name, null, null, null);
 
         cw.visitAttribute(new ModuleAttribute(md));
-        cw.visitAttribute(new ConcealedPackagesAttribute(md.conceals()));
+
+        // for tests: write the ConcealedPackages attribute when there are non-exported packages
+        long nExportedPackages = md.exports().stream()
+                .map(ModuleDescriptor.Exports::source)
+                .distinct()
+                .count();
+        if (md.packages().size() > nExportedPackages)
+            cw.visitAttribute(new ConcealedPackagesAttribute(md.packages()));
+
         md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v)));
         md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc)));
 
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java	Fri Nov 11 16:44:36 2016 +0100
@@ -50,6 +50,7 @@
 import java.util.Set;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.stream.Stream;
 
 import jdk.internal.loader.Resource;
 import jdk.internal.misc.JavaLangModuleAccess;
@@ -159,21 +160,19 @@
                     // is not supported by the boot class loader
                     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)
+                          .filter(Checks::isJavaIdentifier)
                           .forEach(packages::add);
                     }
 
                 } else if (Files.isDirectory(file)) {
 
-                    // exploded directory
+                    // exploded directory without following sym links
                     Path top = file;
                     Files.find(top, Integer.MAX_VALUE,
-                            ((path, attrs) -> attrs.isRegularFile() &&
-                                    path.toString().endsWith(".class")))
+                               ((path, attrs) -> attrs.isRegularFile()))
                             .map(path -> toPackageName(top, path))
-                            .filter(pn -> pn.length() > 0)
+                            .filter(Checks::isJavaIdentifier)
                             .forEach(packages::add);
 
                 }
@@ -381,6 +380,15 @@
         }
 
         @Override
+        public Stream<String> list() throws IOException {
+            Stream<String> s = delegate().list();
+            for (ResourceFinder finder : finders) {
+                s = Stream.concat(s, finder.list());
+            }
+            return s.distinct();
+        }
+
+        @Override
         public void close() throws IOException {
             closeAll(finders);
             delegate().close();
@@ -393,6 +401,7 @@
      */
     private static interface ResourceFinder extends Closeable {
         Resource find(String name) throws IOException;
+        Stream<String> list() throws IOException;
     }
 
 
@@ -453,6 +462,13 @@
                 }
             };
         }
+
+        @Override
+        public Stream<String> list() throws IOException {
+            return jf.stream()
+                    .filter(e -> !e.isDirectory())
+                    .map(JarEntry::getName);
+        }
     }
 
 
@@ -527,6 +543,15 @@
                 }
             };
         }
+
+        @Override
+        public Stream<String> list() throws IOException {
+            return Files.find(dir, Integer.MAX_VALUE,
+                              (path, attrs) -> attrs.isRegularFile())
+                    .map(f -> dir.relativize(f)
+                                 .toString()
+                                 .replace(File.separatorChar, '/'));
+        }
     }
 
 
@@ -537,7 +562,7 @@
         Path entry = top.relativize(file);
         Path parent = entry.getParent();
         if (parent == null) {
-            return warnUnnamedPackage(top, entry.toString());
+            return warnIfModuleInfo(top, entry.toString());
         } else {
             return parent.toString().replace(File.separatorChar, '.');
         }
@@ -557,14 +582,15 @@
         String name = entry.getName();
         int index = name.lastIndexOf("/");
         if (index == -1) {
-            return warnUnnamedPackage(file, name);
+            return warnIfModuleInfo(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);
+    private static String warnIfModuleInfo(Path file, String e) {
+        if (e.equals("module-info.class"))
+            System.err.println("WARNING: " + e + " ignored in patch: " + file);
         return "";
     }
 
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -364,6 +364,16 @@
         }
     }
 
+    public final Constructor<?> newConstructorForSerialization(Class<?> cl,
+                                                               Constructor<?> constructorToCall)
+    {
+        if (constructorToCall.getDeclaringClass() == cl) {
+            constructorToCall.setAccessible(true);
+            return constructorToCall;
+        }
+        return generateConstructor(cl, constructorToCall);
+    }
+
     public final Constructor<?> newConstructorForSerialization(Class<?> cl) {
         Class<?> initCl = cl;
         while (Serializable.class.isAssignableFrom(initCl)) {
@@ -383,6 +393,12 @@
         } catch (NoSuchMethodException ex) {
             return null;
         }
+        return generateConstructor(cl, constructorToCall);
+    }
+
+    private final Constructor<?> generateConstructor(Class<?> cl,
+                                                     Constructor<?> constructorToCall) {
+
 
         ConstructorAccessor acc = new MethodAccessorGenerator().
             generateSerializationConstructor(cl,
--- a/jdk/src/java.base/share/classes/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -196,7 +196,8 @@
         jdk.vm.ci;
     exports jdk.internal.util.jar to
         jdk.jartool,
-        jdk.jdeps;
+        jdk.jdeps,
+        jdk.jlink;
     exports jdk.internal.vm to
         java.management,
         jdk.jvmstat;
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -31,7 +31,7 @@
 \           (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
+java.launcher.opt.datamodel  =\    -d{0}\t  Deprecated, will be removed in a future release\n
 java.launcher.opt.vmselect   =\    {0}\t  to select the "{1}" VM\n
 java.launcher.opt.hotspot    =\    {0}\t  is a synonym for the "{1}" VM  [deprecated]\n
 
@@ -95,6 +95,12 @@
 \                  load Java programming language agent, see java.lang.instrument\n\
 \    -splash:<imagepath>\n\
 \                  show splash screen with specified image\n\
+\                  HiDPI scaled images are automatically supported and used\n\
+\                  if available. The unscaled image filename, e.g. image.ext,\n\
+\                  should always be passed as the argument to the -splash option.\n\
+\                  The most appropriate scaled image provided will be picked up\n\
+\                  automatically.\n\
+\                  See the SplashScreen API documentation for more information.\n\
 \    @<filepath>   read options from the specified file\n\
 \To specify an argument for a long option, you can use --<name>=<value> or\n\
 \--<name> <value>.\n\
--- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java	Fri Nov 11 16:44:36 2016 +0100
@@ -253,20 +253,20 @@
     }
 
     private static String toSourceString(char c) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("'");
+        StringBuilder sb = new StringBuilder(4);
+        sb.append('\'');
         if (c == '\'')
             sb.append("\\'");
         else
             sb.append(c);
-        sb.append("'");
-        return sb.toString();
+        return sb.append('\'')
+                .toString();
     }
 
     private static String toSourceString(long ell) {
-        return (Math.abs(ell) <= Integer.MAX_VALUE) ?
-            String.valueOf(ell) :
-            (String.valueOf(ell) + "L");
+        String str = String.valueOf(ell);
+        return (ell < Integer.MIN_VALUE || ell > Integer.MAX_VALUE)
+                ? (str + 'L') : str;
     }
 
     /**
@@ -278,10 +278,7 @@
         sb.append('"');
         // Escape embedded quote characters, if present, but don't do
         // anything more heroic.
-        if (s.indexOf('"') != -1) {
-            s = s.replace("\"", "\\\"");
-        }
-        sb.append(s);
+        sb.append(s.replace("\"", "\\\""));
         sb.append('"');
         return sb.toString();
     }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -42,10 +42,6 @@
 
     private DTLSReassembler reassembler = null;
 
-    // Cache the session identifier for the detection of session-resuming
-    // handshake.
-    byte[]              prevSessionID = new byte[0];
-
     int                 readEpoch;
 
     int                 prevReadEpoch;
@@ -114,13 +110,7 @@
     @Override
     Plaintext acquirePlaintext() {
         if (reassembler != null) {
-            Plaintext plaintext = reassembler.acquirePlaintext();
-            if (reassembler.finished()) {
-                // discard all buffered unused message.
-                reassembler = null;
-            }
-
-            return plaintext;
+            return reassembler.acquirePlaintext();
         }
 
         return null;
@@ -149,40 +139,54 @@
         packet.get(recordEnS);
         int recordEpoch = ((recordEnS[0] & 0xFF) << 8) |
                            (recordEnS[1] & 0xFF);          // pos: 3, 4
-        long recordSeq  = Authenticator.toLong(recordEnS);
+        long recordSeq  = ((recordEnS[2] & 0xFFL) << 40) |
+                          ((recordEnS[3] & 0xFFL) << 32) |
+                          ((recordEnS[4] & 0xFFL) << 24) |
+                          ((recordEnS[5] & 0xFFL) << 16) |
+                          ((recordEnS[6] & 0xFFL) <<  8) |
+                           (recordEnS[7] & 0xFFL);         // pos: 5-10
+
         int contentLen = ((packet.get() & 0xFF) << 8) |
-                          (packet.get() & 0xFF);            // pos: 11, 12
+                          (packet.get() & 0xFF);           // pos: 11, 12
 
         if (debug != null && Debug.isOn("record")) {
-             System.out.println(Thread.currentThread().getName() +
-                    ", READ: " +
+            Debug.log("READ: " +
                     ProtocolVersion.valueOf(majorVersion, minorVersion) +
                     " " + Record.contentName(contentType) + ", length = " +
                     contentLen);
         }
 
         int recLim = srcPos + DTLSRecord.headerSize + contentLen;
-        if (this.readEpoch > recordEpoch) {
-            // Discard old records delivered before this epoch.
 
+        if (this.prevReadEpoch > recordEpoch) {
             // Reset the position of the packet buffer.
             packet.position(recLim);
+            if (debug != null && Debug.isOn("record")) {
+                Debug.printHex("READ: discard this old record", recordEnS);
+            }
             return null;
         }
 
+        // Buffer next epoch message if necessary.
         if (this.readEpoch < recordEpoch) {
-            if (contentType != Record.ct_handshake) {
-                // just discard it if not a handshake message
+            // Discard the record younger than the current epcoh if:
+            // 1. it is not a handshake message, or
+            // 2. it is not of next epoch.
+            if (((contentType != Record.ct_handshake) &&
+                    (contentType != Record.ct_change_cipher_spec)) ||
+                (this.readEpoch < (recordEpoch - 1))) {
+
                 packet.position(recLim);
+
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Premature record (epoch), discard it.");
+                }
+
                 return null;
             }
 
-            // Not ready to decrypt this record, may be encrypted Finished
+            // Not ready to decrypt this record, may be an encrypted Finished
             // message, need to buffer it.
-            if (reassembler == null) {
-               reassembler = new DTLSReassembler();
-            }
-
             byte[] fragment = new byte[contentLen];
             packet.get(fragment);              // copy the fragment
             RecordFragment buffered = new RecordFragment(fragment, contentType,
@@ -194,94 +198,130 @@
             // consume the full record in the packet buffer.
             packet.position(recLim);
 
-            Plaintext plaintext = reassembler.acquirePlaintext();
-            if (reassembler.finished()) {
-                // discard all buffered unused message.
+            return reassembler.acquirePlaintext();
+        }
+
+        //
+        // Now, the message is of this epoch or the previous epoch.
+        //
+        Authenticator decodeAuthenticator;
+        CipherBox decodeCipher;
+        if (this.readEpoch == recordEpoch) {
+            decodeAuthenticator = readAuthenticator;
+            decodeCipher = readCipher;
+        } else {                        // prevReadEpoch == recordEpoch
+            decodeAuthenticator = prevReadAuthenticator;
+            decodeCipher = prevReadCipher;
+        }
+
+        // decrypt the fragment
+        packet.limit(recLim);
+        packet.position(srcPos + DTLSRecord.headerSize);
+
+        ByteBuffer plaintextFragment;
+        try {
+            plaintextFragment = decrypt(decodeAuthenticator,
+                    decodeCipher, contentType, packet, recordEnS);
+        } catch (BadPaddingException bpe) {
+            if (debug != null && Debug.isOn("ssl")) {
+                Debug.log("Discard invalid record: " + bpe);
+            }
+
+            // invalid, discard this record [section 4.1.2.7, RFC 6347]
+            return null;
+        } finally {
+            // comsume a complete record
+            packet.limit(srcLim);
+            packet.position(recLim);
+        }
+
+        if (contentType != Record.ct_change_cipher_spec &&
+            contentType != Record.ct_handshake) {   // app data or alert
+                                                    // no retransmission
+            // Cleanup the handshake reassembler if necessary.
+            if ((reassembler != null) &&
+                    (reassembler.handshakeEpoch < recordEpoch)) {
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Cleanup the handshake reassembler");
+                }
+
                 reassembler = null;
             }
 
-            return plaintext;
+            return new Plaintext(contentType, majorVersion, minorVersion,
+                    recordEpoch, Authenticator.toLong(recordEnS),
+                    plaintextFragment);
         }
 
-        if (this.readEpoch == recordEpoch) {
-            // decrypt the fragment
-            packet.limit(recLim);
-            packet.position(srcPos + DTLSRecord.headerSize);
-
-            ByteBuffer plaintextFragment;
-            try {
-                plaintextFragment = decrypt(readAuthenticator,
-                        readCipher, contentType, packet, recordEnS);
-            } catch (BadPaddingException bpe) {
-                if (debug != null && Debug.isOn("ssl")) {
-                    System.out.println(Thread.currentThread().getName() +
-                            " discard invalid record: " + bpe);
-                }
-
-                // invalid, discard this record [section 4.1.2.7, RFC 6347]
-                return null;
-            } finally {
-                // comsume a complete record
-                packet.limit(srcLim);
-                packet.position(recLim);
-            }
-
-            if (contentType != Record.ct_change_cipher_spec &&
-                contentType != Record.ct_handshake) {   // app data or alert
-                                                        // no retransmission
-               return new Plaintext(contentType, majorVersion, minorVersion,
-                        recordEpoch, recordSeq, plaintextFragment);
-            }
-
-            if (contentType == Record.ct_change_cipher_spec) {
-                if (reassembler == null) {
+        if (contentType == Record.ct_change_cipher_spec) {
+            if (reassembler == null) {
+                if (this.readEpoch != recordEpoch) {
                     // handshake has not started, should be an
                     // old handshake message, discard it.
+
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                                "Lagging behind ChangeCipherSpec, discard it.");
+                    }
+
                     return null;
                 }
 
-                reassembler.queueUpFragment(
-                        new RecordFragment(plaintextFragment, contentType,
-                                majorVersion, minorVersion,
-                                recordEnS, recordEpoch, recordSeq, false));
-            } else {    // handshake record
-                // One record may contain 1+ more handshake messages.
-                while (plaintextFragment.remaining() > 0) {
+                reassembler = new DTLSReassembler(recordEpoch);
+            }
+
+            reassembler.queueUpChangeCipherSpec(
+                    new RecordFragment(plaintextFragment, contentType,
+                            majorVersion, minorVersion,
+                            recordEnS, recordEpoch, recordSeq, false));
+        } else {    // handshake record
+            // One record may contain 1+ more handshake messages.
+            while (plaintextFragment.remaining() > 0) {
+
+                HandshakeFragment hsFrag = parseHandshakeMessage(
+                    contentType, majorVersion, minorVersion,
+                    recordEnS, recordEpoch, recordSeq, plaintextFragment);
 
-                    HandshakeFragment hsFrag = parseHandshakeMessage(
-                        contentType, majorVersion, minorVersion,
-                        recordEnS, recordEpoch, recordSeq, plaintextFragment);
+                if (hsFrag == null) {
+                    // invalid, discard this record
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log("Invalid handshake message, discard it.");
+                    }
+
+                    return null;
+                }
 
-                    if (hsFrag == null) {
-                        // invalid, discard this record
+                if (reassembler == null) {
+                    if (this.readEpoch != recordEpoch) {
+                        // handshake has not started, should be an
+                        // old handshake message, discard it.
+
+                        if (debug != null && Debug.isOn("verbose")) {
+                            Debug.log(
+                                "Lagging behind handshake record, discard it.");
+                        }
+
                         return null;
                     }
 
-                    if ((reassembler == null) &&
-                            isKickstart(hsFrag.handshakeType)) {
-                       reassembler = new DTLSReassembler();
-                    }
-
-                    if (reassembler != null) {
-                        reassembler.queueUpHandshake(hsFrag);
-                    }   // else, just ignore the message.
-                }
-            }
-
-            // Completed the read of the full record. Acquire the reassembled
-            // messages.
-            if (reassembler != null) {
-                Plaintext plaintext = reassembler.acquirePlaintext();
-                if (reassembler.finished()) {
-                    // discard all buffered unused message.
-                    reassembler = null;
+                    reassembler = new DTLSReassembler(recordEpoch);
                 }
 
-                return plaintext;
+                reassembler.queueUpHandshake(hsFrag);
             }
         }
 
-        return null;    // make the complier happy
+        // Completed the read of the full record.  Acquire the reassembled
+        // messages.
+        if (reassembler != null) {
+            return reassembler.acquirePlaintext();
+        }
+
+        if (debug != null && Debug.isOn("verbose")) {
+            Debug.log("The reassembler is not initialized yet.");
+        }
+
+        return null;
     }
 
     @Override
@@ -330,12 +370,6 @@
         }
     }
 
-    private static boolean isKickstart(byte handshakeType) {
-        return (handshakeType == HandshakeMessage.ht_client_hello) ||
-               (handshakeType == HandshakeMessage.ht_hello_request) ||
-               (handshakeType == HandshakeMessage.ht_hello_verify_request);
-    }
-
     private static HandshakeFragment parseHandshakeMessage(
             byte contentType, byte majorVersion, byte minorVersion,
             byte[] recordEnS, int recordEpoch, long recordSeq,
@@ -344,9 +378,7 @@
         int remaining = plaintextFragment.remaining();
         if (remaining < handshakeHeaderSize) {
             if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(
-                        Thread.currentThread().getName() +
-                        " discard invalid record: " +
+                Debug.log("Discard invalid record: " +
                         "too small record to hold a handshake fragment");
             }
 
@@ -372,9 +404,7 @@
                  (plaintextFragment.get() & 0xFF);          // pos: 9-11
         if ((remaining - handshakeHeaderSize) < fragmentLength) {
             if (debug != null && Debug.isOn("ssl")) {
-                System.out.println(
-                        Thread.currentThread().getName() +
-                        " discard invalid record: " +
+                Debug.log("Discard invalid record: " +
                         "not a complete handshake fragment in the record");
             }
 
@@ -431,7 +461,39 @@
 
         @Override
         public int compareTo(RecordFragment o) {
-            return Long.compareUnsigned(this.recordSeq, o.recordSeq);
+            if (this.contentType == Record.ct_change_cipher_spec) {
+                if (o.contentType == Record.ct_change_cipher_spec) {
+                    // Only one incoming ChangeCipherSpec message for an epoch.
+                    //
+                    // Ignore duplicated ChangeCipherSpec messages.
+                    return Integer.compare(this.recordEpoch, o.recordEpoch);
+                } else if ((this.recordEpoch == o.recordEpoch) &&
+                        (o.contentType == Record.ct_handshake)) {
+                    // ChangeCipherSpec is the latest message of an epoch.
+                    return 1;
+                }
+            } else if (o.contentType == Record.ct_change_cipher_spec) {
+                if ((this.recordEpoch == o.recordEpoch) &&
+                        (this.contentType == Record.ct_handshake)) {
+                    // ChangeCipherSpec is the latest message of an epoch.
+                    return -1;
+                } else {
+                    // different epoch or this is not a handshake message
+                    return compareToSequence(o.recordEpoch, o.recordSeq);
+                }
+            }
+
+            return compareToSequence(o.recordEpoch, o.recordSeq);
+        }
+
+        int compareToSequence(int epoch, long seq) {
+            if (this.recordEpoch > epoch) {
+                return 1;
+            } else if (this.recordEpoch == epoch) {
+                return Long.compare(this.recordSeq, seq);
+            } else {
+                return -1;
+            }
         }
     }
 
@@ -465,12 +527,24 @@
             if (o instanceof HandshakeFragment) {
                 HandshakeFragment other = (HandshakeFragment)o;
                 if (this.messageSeq != other.messageSeq) {
-                    // keep the insertion order for the same message
+                    // keep the insertion order of handshake messages
                     return this.messageSeq - other.messageSeq;
+                } else if (this.fragmentOffset != other.fragmentOffset) {
+                    // small fragment offset was transmitted first
+                    return this.fragmentOffset - other.fragmentOffset;
+                } else if (this.fragmentLength == other.fragmentLength) {
+                    // retransmissions, ignore duplicated messages.
+                    return 0;
                 }
+
+                // Should be repacked for suitable fragment length.
+                //
+                // Note that the acquiring processes will reassemble the
+                // the fragments later.
+                return compareToSequence(o.recordEpoch, o.recordSeq);
             }
 
-            return Long.compareUnsigned(this.recordSeq, o.recordSeq);
+            return super.compareTo(o);
         }
     }
 
@@ -484,24 +558,72 @@
         }
     }
 
+    private static final class HandshakeFlight implements Cloneable {
+        static final byte HF_UNKNOWN = HandshakeMessage.ht_not_applicable;
+
+        byte        handshakeType;      // handshake type
+        int         flightEpoch;        // the epoch of the first message
+        int         minMessageSeq;      // minimal message sequence
+
+        int         maxMessageSeq;      // maximum message sequence
+        int         maxRecordEpoch;     // maximum record sequence number
+        long        maxRecordSeq;       // maximum record sequence number
+
+        HashMap<Byte, List<HoleDescriptor>> holesMap;
+
+        HandshakeFlight() {
+            this.handshakeType = HF_UNKNOWN;
+            this.flightEpoch = 0;
+            this.minMessageSeq = 0;
+
+            this.maxMessageSeq = 0;
+            this.maxRecordEpoch = 0;
+            this.maxRecordSeq = -1;
+
+            this.holesMap = new HashMap<>(5);
+        }
+
+        boolean isRetransmitOf(HandshakeFlight hs) {
+            return (hs != null) &&
+                   (this.handshakeType == hs.handshakeType) &&
+                   (this.minMessageSeq == hs.minMessageSeq);
+        }
+
+        @Override
+        public Object clone() {
+            HandshakeFlight hf = new HandshakeFlight();
+
+            hf.handshakeType = this.handshakeType;
+            hf.flightEpoch = this.flightEpoch;
+            hf.minMessageSeq = this.minMessageSeq;
+
+            hf.maxMessageSeq = this.maxMessageSeq;
+            hf.maxRecordEpoch = this.maxRecordEpoch;
+            hf.maxRecordSeq = this.maxRecordSeq;
+
+            hf.holesMap = new HashMap<>(this.holesMap);
+
+            return hf;
+        }
+    }
+
     final class DTLSReassembler {
+        // The handshake epoch.
+        final int handshakeEpoch;
+
+        // The buffered fragments.
         TreeSet<RecordFragment> bufferedFragments = new TreeSet<>();
 
-        HashMap<Byte, List<HoleDescriptor>> holesMap = new HashMap<>(5);
+        // The handshake flight in progress.
+        HandshakeFlight handshakeFlight = new HandshakeFlight();
 
-        // Epoch, sequence number and handshake message sequence of the
-        // beginning message of a flight.
-        byte        flightType = (byte)0xFF;
-
-        int         flightTopEpoch = 0;
-        long        flightTopRecordSeq = -1;
-        int         flightTopMessageSeq = 0;
+        // The preceding handshake flight.
+        HandshakeFlight precedingFlight = null;
 
         // Epoch, sequence number and handshake message sequence of the
         // next message acquisition of a flight.
-        int         nextRecordEpoch = 0;    // next record epoch
+        int         nextRecordEpoch;        // next record epoch
         long        nextRecordSeq = 0;      // next record sequence number
-        int         nextMessageSeq = 0;     // next handshake message number
 
         // Expect ChangeCipherSpec and Finished messages for the final flight.
         boolean     expectCCSFlight = false;
@@ -510,65 +632,66 @@
         boolean     flightIsReady = false;
         boolean     needToCheckFlight = false;
 
-        // Is it a session-resuming abbreviated handshake.?
-        boolean     isAbbreviatedHandshake = false;
-
-        // The handshke fragment with the biggest record sequence number
-        // in a flight, not counting the Finished message.
-        HandshakeFragment lastHandshakeFragment = null;
+        DTLSReassembler(int handshakeEpoch) {
+            this.handshakeEpoch = handshakeEpoch;
+            this.nextRecordEpoch = handshakeEpoch;
 
-        // Is handshake (intput) finished?
-        boolean handshakeFinished = false;
-
-        DTLSReassembler() {
-            // blank
-        }
-
-        boolean finished() {
-            return handshakeFinished;
+            this.handshakeFlight.flightEpoch = handshakeEpoch;
         }
 
         void expectingFinishFlight() {
             expectCCSFlight = true;
         }
 
+        // Queue up a handshake message.
         void queueUpHandshake(HandshakeFragment hsf) {
-
-            if ((nextRecordEpoch > hsf.recordEpoch) ||
-                    (nextRecordSeq > hsf.recordSeq) ||
-                    (nextMessageSeq > hsf.messageSeq)) {
-                // too old, discard this record
+            if (!isDesirable(hsf)) {
+                // Not a dedired record, discard it.
                 return;
             }
 
-            // Is it the first message of next flight?
-            if ((flightTopMessageSeq == hsf.messageSeq) &&
-                    (hsf.fragmentOffset == 0) && (flightTopRecordSeq == -1)) {
+            // Clean up the retransmission messages if necessary.
+            cleanUpRetransmit(hsf);
 
-                flightType = hsf.handshakeType;
-                flightTopEpoch = hsf.recordEpoch;
-                flightTopRecordSeq = hsf.recordSeq;
+            // Is it the first message of next flight?
+            //
+            // Note: the Finished message is handled in the final CCS flight.
+            boolean isMinimalFlightMessage = false;
+            if (handshakeFlight.minMessageSeq == hsf.messageSeq) {
+                isMinimalFlightMessage = true;
+            } else if ((precedingFlight != null) &&
+                    (precedingFlight.minMessageSeq == hsf.messageSeq)) {
+                isMinimalFlightMessage = true;
+            }
+
+            if (isMinimalFlightMessage && (hsf.fragmentOffset == 0) &&
+                    (hsf.handshakeType != HandshakeMessage.ht_finished)) {
 
-                if (hsf.handshakeType == HandshakeMessage.ht_server_hello) {
-                    // Is it a session-resuming handshake?
-                    try {
-                        isAbbreviatedHandshake =
-                                isSessionResuming(hsf.fragment, prevSessionID);
-                    } catch (SSLException ssle) {
-                        if (debug != null && Debug.isOn("ssl")) {
-                            System.out.println(
-                                    Thread.currentThread().getName() +
-                                    " discard invalid record: " + ssle);
-                        }
+                // reset the handshake flight
+                handshakeFlight.handshakeType = hsf.handshakeType;
+                handshakeFlight.flightEpoch = hsf.recordEpoch;
+                handshakeFlight.minMessageSeq = hsf.messageSeq;
+            }
 
-                        // invalid, discard it [section 4.1.2.7, RFC 6347]
-                        return;
-                    }
+            if (hsf.handshakeType == HandshakeMessage.ht_finished) {
+                handshakeFlight.maxMessageSeq = hsf.messageSeq;
+                handshakeFlight.maxRecordEpoch = hsf.recordEpoch;
+                handshakeFlight.maxRecordSeq = hsf.recordSeq;
+            } else {
+                if (handshakeFlight.maxMessageSeq < hsf.messageSeq) {
+                    handshakeFlight.maxMessageSeq = hsf.messageSeq;
+                }
 
-                    if (!isAbbreviatedHandshake) {
-                        prevSessionID = getSessionID(hsf.fragment);
+                int n = (hsf.recordEpoch - handshakeFlight.maxRecordEpoch);
+                if (n > 0) {
+                    handshakeFlight.maxRecordEpoch = hsf.recordEpoch;
+                    handshakeFlight.maxRecordSeq = hsf.recordSeq;
+                } else if (n == 0) {
+                    // the same epoch
+                    if (handshakeFlight.maxRecordSeq < hsf.recordSeq) {
+                        handshakeFlight.maxRecordSeq = hsf.recordSeq;
                     }
-                }
+                }   // Otherwise, it is unlikely to happen.
             }
 
             boolean fragmented = false;
@@ -578,7 +701,8 @@
                 fragmented = true;
             }
 
-            List<HoleDescriptor> holes = holesMap.get(hsf.handshakeType);
+            List<HoleDescriptor> holes =
+                    handshakeFlight.holesMap.get(hsf.handshakeType);
             if (holes == null) {
                 if (!fragmented) {
                     holes = Collections.emptyList();
@@ -586,7 +710,7 @@
                     holes = new LinkedList<HoleDescriptor>();
                     holes.add(new HoleDescriptor(0, hsf.messageLength));
                 }
-                holesMap.put(hsf.handshakeType, holes);
+                handshakeFlight.holesMap.put(hsf.handshakeType, holes);
             } else if (holes.isEmpty()) {
                 // Have got the full handshake message.  This record may be
                 // a handshake message retransmission.  Discard this record.
@@ -594,20 +718,11 @@
                 // It's OK to discard retransmission as the handshake hash
                 // is computed as if each handshake message had been sent
                 // as a single fragment.
-                //
-                // Note that ClientHello messages are delivered twice in
-                // DTLS handshaking.
-                if ((hsf.handshakeType != HandshakeMessage.ht_client_hello &&
-                     hsf.handshakeType != ht_hello_verify_request) ||
-                        (nextMessageSeq != hsf.messageSeq)) {
-                    return;
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Have got the full message, discard it.");
                 }
 
-                if (fragmented) {
-                    holes = new LinkedList<HoleDescriptor>();
-                    holes.add(new HoleDescriptor(0, hsf.messageLength));
-                }
-                holesMap.put(hsf.handshakeType, holes);
+                return;
             }
 
             if (fragmented) {
@@ -628,9 +743,7 @@
                          (hole.limit < fragmentLimit))) {
 
                         if (debug != null && Debug.isOn("ssl")) {
-                            System.out.println(
-                                Thread.currentThread().getName() +
-                                " discard invalid record: " +
+                            Debug.log("Discard invalid record: " +
                                 "handshake fragment ranges are overlapping");
                         }
 
@@ -659,48 +772,205 @@
                 }
             }
 
-            // append this fragment
-            bufferedFragments.add(hsf);
-
-            if ((lastHandshakeFragment == null) ||
-                (lastHandshakeFragment.compareTo(hsf) < 0)) {
-
-                lastHandshakeFragment = hsf;
+            // buffer this fragment
+            if (hsf.handshakeType == HandshakeMessage.ht_finished) {
+                // Need no status update.
+                bufferedFragments.add(hsf);
+            } else {
+                bufferFragment(hsf);
             }
-
-            if (flightIsReady) {
-                flightIsReady = false;
-            }
-            needToCheckFlight = true;
         }
 
-        // queue up change_cipher_spec or encrypted message
-        void queueUpFragment(RecordFragment rf) {
-            if ((nextRecordEpoch > rf.recordEpoch) ||
-                    (nextRecordSeq > rf.recordSeq)) {
-                // too old, discard this record
+        // Queue up a ChangeCipherSpec message
+        void queueUpChangeCipherSpec(RecordFragment rf) {
+            if (!isDesirable(rf)) {
+                // Not a dedired record, discard it.
                 return;
             }
 
-            // Is it the first message of next flight?
-            if (expectCCSFlight &&
-                    (rf.contentType == Record.ct_change_cipher_spec)) {
+            // Clean up the retransmission messages if necessary.
+            cleanUpRetransmit(rf);
 
-                flightType = (byte)0xFE;
-                flightTopEpoch = rf.recordEpoch;
-                flightTopRecordSeq = rf.recordSeq;
+            // Is it the first message of this flight?
+            //
+            // Note: the first message of the final flight is ChangeCipherSpec.
+            if (expectCCSFlight) {
+                handshakeFlight.handshakeType = HandshakeFlight.HF_UNKNOWN;
+                handshakeFlight.flightEpoch = rf.recordEpoch;
+            }
+
+            // The epoch should be the same as the first message of the flight.
+            if (handshakeFlight.maxRecordSeq < rf.recordSeq) {
+                handshakeFlight.maxRecordSeq = rf.recordSeq;
             }
 
+            // buffer this fragment
+            bufferFragment(rf);
+        }
+
+        // Queue up a ciphertext message.
+        //
+        // Note: not yet be able to decrypt the message.
+        void queueUpFragment(RecordFragment rf) {
+            if (!isDesirable(rf)) {
+                // Not a dedired record, discard it.
+                return;
+            }
+
+            // Clean up the retransmission messages if necessary.
+            cleanUpRetransmit(rf);
+
+            // buffer this fragment
+            bufferFragment(rf);
+        }
+
+        private void bufferFragment(RecordFragment rf) {
             // append this fragment
             bufferedFragments.add(rf);
 
             if (flightIsReady) {
                 flightIsReady = false;
             }
-            needToCheckFlight = true;
+
+            if (!needToCheckFlight) {
+                needToCheckFlight = true;
+            }
+        }
+
+        private void cleanUpRetransmit(RecordFragment rf) {
+            // Does the next flight start?
+            boolean isNewFlight = false;
+            if (precedingFlight != null) {
+                if (precedingFlight.flightEpoch < rf.recordEpoch) {
+                    isNewFlight = true;
+                } else {
+                    if (rf instanceof HandshakeFragment) {
+                        HandshakeFragment hsf = (HandshakeFragment)rf;
+                        if (precedingFlight.maxMessageSeq  < hsf.messageSeq) {
+                            isNewFlight = true;
+                        }
+                    } else if (rf.contentType != Record.ct_change_cipher_spec) {
+                        // ciphertext
+                        if (precedingFlight.maxRecordEpoch < rf.recordEpoch) {
+                            isNewFlight = true;
+                        }
+                    }
+                }
+            }
+
+            if (!isNewFlight) {
+                // Need no cleanup.
+                return;
+            }
+
+            // clean up the buffer
+            for (Iterator<RecordFragment> it = bufferedFragments.iterator();
+                    it.hasNext();) {
+
+                RecordFragment frag = it.next();
+                boolean isOld = false;
+                if (frag.recordEpoch < precedingFlight.maxRecordEpoch) {
+                    isOld = true;
+                } else if (frag.recordEpoch == precedingFlight.maxRecordEpoch) {
+                    if (frag.recordSeq <= precedingFlight.maxRecordSeq) {
+                        isOld = true;
+                    }
+                }
+
+                if (!isOld && (frag instanceof HandshakeFragment)) {
+                    HandshakeFragment hsf = (HandshakeFragment)frag;
+                    isOld = (hsf.messageSeq <= precedingFlight.maxMessageSeq);
+                }
+
+                if (isOld) {
+                    it.remove();
+                } else {
+                    // Safe to break as items in the buffer are ordered.
+                    break;
+                }
+            }
+
+            // discard retransmissions of the previous flight if any.
+            precedingFlight = null;
         }
 
-        boolean isEmpty() {
+        // Is a desired record?
+        //
+        // Check for retransmission and lost records.
+        private boolean isDesirable(RecordFragment rf) {
+            //
+            // Discard records old than the previous epoch.
+            //
+            int previousEpoch = nextRecordEpoch - 1;
+            if (rf.recordEpoch < previousEpoch) {
+                // Too old to use, discard this record.
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Too old epoch to use this record, discard it.");
+                }
+
+                return false;
+            }
+
+            //
+            // Allow retransmission of last flight of the previous epoch
+            //
+            // For example, the last server delivered flight for session
+            // resuming abbreviated handshaking consist three messages:
+            //      ServerHello
+            //      [ChangeCipherSpec]
+            //      Finished
+            //
+            // The epoch number is incremented and the sequence number is reset
+            // if the ChangeCipherSpec is sent.
+            if (rf.recordEpoch == previousEpoch) {
+                boolean isDesired = true;
+                if (precedingFlight == null) {
+                    isDesired = false;
+                } else {
+                    if (rf instanceof HandshakeFragment) {
+                        HandshakeFragment hsf = (HandshakeFragment)rf;
+                        if (precedingFlight.minMessageSeq > hsf.messageSeq) {
+                            isDesired = false;
+                        }
+                    } else if (rf.contentType == Record.ct_change_cipher_spec) {
+                        // ChangeCipherSpec
+                        if (precedingFlight.flightEpoch != rf.recordEpoch) {
+                            isDesired = false;
+                        }
+                    } else {        // ciphertext
+                        if ((rf.recordEpoch < precedingFlight.maxRecordEpoch) ||
+                            (rf.recordEpoch == precedingFlight.maxRecordEpoch &&
+                                rf.recordSeq <= precedingFlight.maxRecordSeq)) {
+                            isDesired = false;
+                        }
+                    }
+                }
+
+                if (!isDesired) {
+                    // Too old to use, discard this retransmitted record
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log("Too old retransmission to use, discard it.");
+                    }
+
+                    return false;
+                }
+            } else if ((rf.recordEpoch == nextRecordEpoch) &&
+                    (nextRecordSeq > rf.recordSeq)) {
+
+                // Previously disordered record for the current epoch.
+                //
+                // Should has been retransmitted. Discard this record.
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Lagging behind record (sequence), discard it.");
+                }
+
+                return false;
+            }
+
+            return true;
+        }
+
+        private boolean isEmpty() {
             return (bufferedFragments.isEmpty() ||
                     (!flightIsReady && !needToCheckFlight) ||
                     (needToCheckFlight && !flightIsReady()));
@@ -708,12 +978,9 @@
 
         Plaintext acquirePlaintext() {
             if (bufferedFragments.isEmpty()) {
-                // reset the flight
-                if (flightIsReady) {
-                    flightIsReady = false;
-                    needToCheckFlight = false;
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("No received handshake messages");
                 }
-
                 return null;
             }
 
@@ -721,27 +988,103 @@
                 // check the fligth status
                 flightIsReady = flightIsReady();
 
-                // set for next flight
+                // Reset if this flight is ready.
                 if (flightIsReady) {
-                    flightTopMessageSeq = lastHandshakeFragment.messageSeq + 1;
-                    flightTopRecordSeq = -1;
+                    // Retransmitted handshake messages are not needed for
+                    // further handshaking processing.
+                    if (handshakeFlight.isRetransmitOf(precedingFlight)) {
+                        // cleanup
+                        bufferedFragments.clear();
+
+                        // Reset the next handshake flight.
+                        resetHandshakeFlight(precedingFlight);
+
+                        if (debug != null && Debug.isOn("verbose")) {
+                            Debug.log("Received a retransmission flight.");
+                        }
+
+                        return Plaintext.PLAINTEXT_NULL;
+                    }
                 }
 
                 needToCheckFlight = false;
             }
 
             if (!flightIsReady) {
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("The handshake flight is not ready to use: " +
+                                handshakeFlight.handshakeType);
+                }
                 return null;
             }
 
             RecordFragment rFrag = bufferedFragments.first();
+            Plaintext plaintext;
             if (!rFrag.isCiphertext) {
                 // handshake message, or ChangeCipherSpec message
-                return acquireHandshakeMessage();
+                plaintext = acquireHandshakeMessage();
+
+                // Reset the handshake flight.
+                if (bufferedFragments.isEmpty()) {
+                    // Need not to backup the holes map.  Clear up it at first.
+                    handshakeFlight.holesMap.clear();   // cleanup holes map
+
+                    // Update the preceding flight.
+                    precedingFlight = (HandshakeFlight)handshakeFlight.clone();
+
+                    // Reset the next handshake flight.
+                    resetHandshakeFlight(precedingFlight);
+
+                    if (expectCCSFlight &&
+                            (precedingFlight.flightEpoch ==
+                                    HandshakeFlight.HF_UNKNOWN)) {
+                        expectCCSFlight = false;
+                    }
+                }
             } else {
                 // a Finished message or other ciphertexts
-                return acquireCachedMessage();
+                plaintext = acquireCachedMessage();
             }
+
+            return plaintext;
+        }
+
+        //
+        // Reset the handshake flight from a previous one.
+        //
+        private void resetHandshakeFlight(HandshakeFlight prev) {
+            // Reset the next handshake flight.
+            handshakeFlight.handshakeType = HandshakeFlight.HF_UNKNOWN;
+            handshakeFlight.flightEpoch = prev.maxRecordEpoch;
+            if (prev.flightEpoch != prev.maxRecordEpoch) {
+                // a new epoch starts
+                handshakeFlight.minMessageSeq = 0;
+            } else {
+                // stay at the same epoch
+                //
+                // The minimal message sequence number will get updated if
+                // a flight retransmission happens.
+                handshakeFlight.minMessageSeq = prev.maxMessageSeq + 1;
+            }
+
+            // cleanup the maximum sequence number and epoch number.
+            //
+            // Note: actually, we need to do nothing because the reassembler
+            // of handshake messages will reset them properly even for
+            // retransmissions.
+            //
+            handshakeFlight.maxMessageSeq = 0;
+            handshakeFlight.maxRecordEpoch = handshakeFlight.flightEpoch;
+
+            // Record sequence number cannot wrap even for retransmissions.
+            handshakeFlight.maxRecordSeq = prev.maxRecordSeq + 1;
+
+            // cleanup holes map
+            handshakeFlight.holesMap.clear();
+
+            // Ready to accept new input record.
+            flightIsReady = false;
+            needToCheckFlight = false;
         }
 
         private Plaintext acquireCachedMessage() {
@@ -750,6 +1093,9 @@
             if (readEpoch != rFrag.recordEpoch) {
                 if (readEpoch > rFrag.recordEpoch) {
                     // discard old records
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log("Discard old buffered ciphertext fragments.");
+                    }
                     bufferedFragments.remove(rFrag);    // popup the fragment
                 }
 
@@ -757,6 +1103,10 @@
                 if (flightIsReady) {
                     flightIsReady = false;
                 }
+
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Not yet ready to decrypt the cached fragments.");
+                }
                 return null;
             }
 
@@ -768,9 +1118,8 @@
                 plaintextFragment = decrypt(readAuthenticator, readCipher,
                         rFrag.contentType, fragment, rFrag.recordEnS);
             } catch (BadPaddingException bpe) {
-                if (debug != null && Debug.isOn("ssl")) {
-                    System.out.println(Thread.currentThread().getName() +
-                            " discard invalid record: " + bpe);
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Discard invalid record: " + bpe);
                 }
 
                 // invalid, discard this record [section 4.1.2.7, RFC 6347]
@@ -782,7 +1131,6 @@
             // beginning of the next flight) message.  Need not to check
             // any ChangeCipherSpec message.
             if (rFrag.contentType == Record.ct_handshake) {
-                HandshakeFragment finFrag = null;
                 while (plaintextFragment.remaining() > 0) {
                     HandshakeFragment hsFrag = parseHandshakeMessage(
                             rFrag.contentType,
@@ -792,66 +1140,31 @@
 
                     if (hsFrag == null) {
                         // invalid, discard this record
+                        if (debug != null && Debug.isOn("verbose")) {
+                            Debug.printHex(
+                                    "Invalid handshake fragment, discard it",
+                                    plaintextFragment);
+                        }
                         return null;
                     }
 
-                    if (hsFrag.handshakeType == HandshakeMessage.ht_finished) {
-                        finFrag = hsFrag;
-
-                        // reset for the next flight
-                        this.flightType = (byte)0xFF;
-                        this.flightTopEpoch = rFrag.recordEpoch;
-                        this.flightTopMessageSeq = hsFrag.messageSeq + 1;
-                        this.flightTopRecordSeq = -1;
-                    } else {
-                        // reset the flight
-                        if (flightIsReady) {
-                            flightIsReady = false;
-                        }
-                        queueUpHandshake(hsFrag);
+                    queueUpHandshake(hsFrag);
+                    // The flight ready status (flightIsReady) should have
+                    // been checked and updated for the Finished handshake
+                    // message before the decryption.  Please don't update
+                    // flightIsReady for Finished messages.
+                    if (hsFrag.handshakeType != HandshakeMessage.ht_finished) {
+                        flightIsReady = false;
+                        needToCheckFlight = true;
                     }
                 }
 
-                this.nextRecordSeq = rFrag.recordSeq + 1;
-                this.nextMessageSeq = 0;
-
-                if (finFrag != null) {
-                    this.nextRecordEpoch = finFrag.recordEpoch;
-                    this.nextRecordSeq = finFrag.recordSeq + 1;
-                    this.nextMessageSeq = finFrag.messageSeq + 1;
-
-                    // Finished message does not fragment.
-                    byte[] recordFrag = new byte[finFrag.messageLength + 4];
-                    Plaintext plaintext = new Plaintext(finFrag.contentType,
-                            finFrag.majorVersion, finFrag.minorVersion,
-                            finFrag.recordEpoch, finFrag.recordSeq,
-                            ByteBuffer.wrap(recordFrag));
-
-                    // fill the handshake fragment of the record
-                    recordFrag[0] = finFrag.handshakeType;
-                    recordFrag[1] =
-                            (byte)((finFrag.messageLength >>> 16) & 0xFF);
-                    recordFrag[2] =
-                            (byte)((finFrag.messageLength >>> 8) & 0xFF);
-                    recordFrag[3] = (byte)(finFrag.messageLength & 0xFF);
-
-                    System.arraycopy(finFrag.fragment, 0,
-                            recordFrag, 4, finFrag.fragmentLength);
-
-                    // handshake hashing
-                    handshakeHashing(finFrag, plaintext);
-
-                    // input handshake finished
-                    handshakeFinished = true;
-
-                    return plaintext;
-                } else {
-                    return acquirePlaintext();
-                }
+                return acquirePlaintext();
             } else {
                 return new Plaintext(rFrag.contentType,
                         rFrag.majorVersion, rFrag.minorVersion,
-                        rFrag.recordEpoch, rFrag.recordSeq,
+                        rFrag.recordEpoch,
+                        Authenticator.toLong(rFrag.recordEnS),
                         plaintextFragment);
             }
         }
@@ -861,17 +1174,23 @@
             RecordFragment rFrag = bufferedFragments.first();
             if (rFrag.contentType == Record.ct_change_cipher_spec) {
                 this.nextRecordEpoch = rFrag.recordEpoch + 1;
+
+                // For retransmissions, the next record sequence number is a
+                // positive value.  Don't worry about it as the acquiring of
+                // the immediately followed Finished handshake message will
+                // reset the next record sequence number correctly.
                 this.nextRecordSeq = 0;
-                // no change on next handshake message sequence number
 
-                bufferedFragments.remove(rFrag);        // popup the fragment
+                // Popup the fragment.
+                bufferedFragments.remove(rFrag);
 
                 // Reload if this message has been reserved for handshake hash.
                 handshakeHash.reload();
 
                 return new Plaintext(rFrag.contentType,
                         rFrag.majorVersion, rFrag.minorVersion,
-                        rFrag.recordEpoch, rFrag.recordSeq,
+                        rFrag.recordEpoch,
+                        Authenticator.toLong(rFrag.recordEnS),
                         ByteBuffer.wrap(rFrag.fragment));
             } else {    // rFrag.contentType == Record.ct_handshake
                 HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
@@ -882,13 +1201,13 @@
 
                     // this.nextRecordEpoch = hsFrag.recordEpoch;
                     this.nextRecordSeq = hsFrag.recordSeq + 1;
-                    this.nextMessageSeq = hsFrag.messageSeq + 1;
 
                     // Note: may try to avoid byte array copy in the future.
                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
                     Plaintext plaintext = new Plaintext(hsFrag.contentType,
                             hsFrag.majorVersion, hsFrag.minorVersion,
-                            hsFrag.recordEpoch, hsFrag.recordSeq,
+                            hsFrag.recordEpoch,
+                            Authenticator.toLong(hsFrag.recordEnS),
                             ByteBuffer.wrap(recordFrag));
 
                     // fill the handshake fragment of the record
@@ -913,7 +1232,8 @@
                     byte[] recordFrag = new byte[hsFrag.messageLength + 4];
                     Plaintext plaintext = new Plaintext(hsFrag.contentType,
                             hsFrag.majorVersion, hsFrag.minorVersion,
-                            hsFrag.recordEpoch, hsFrag.recordSeq,
+                            hsFrag.recordEpoch,
+                            Authenticator.toLong(hsFrag.recordEnS),
                             ByteBuffer.wrap(recordFrag));
 
                     // fill the handshake fragment of the record
@@ -957,7 +1277,6 @@
                     handshakeHashing(hsFrag, plaintext);
 
                     this.nextRecordSeq = maxRecodeSN + 1;
-                    this.nextMessageSeq = msgSeq + 1;
 
                     return plaintext;
                 }
@@ -966,15 +1285,26 @@
 
         boolean flightIsReady() {
 
-            //
-            // the ChangeCipherSpec/Finished flight
-            //
-            if (expectCCSFlight) {
-                // Have the ChangeCipherSpec/Finished messages been received?
-                return hasFinisedMessage(bufferedFragments);
-            }
+            byte flightType = handshakeFlight.handshakeType;
+            if (flightType == HandshakeFlight.HF_UNKNOWN) {
+                //
+                // the ChangeCipherSpec/Finished flight
+                //
+                if (expectCCSFlight) {
+                    // Have the ChangeCipherSpec/Finished flight been received?
+                    boolean isReady = hasFinishedMessage(bufferedFragments);
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                            "Has the final flight been received? " + isReady);
+                    }
 
-            if (flightType == (byte)0xFF) {
+                    return isReady;
+                }
+
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("No flight is received yet.");
+                }
+
                 return false;
             }
 
@@ -983,7 +1313,12 @@
                 (flightType == HandshakeMessage.ht_hello_verify_request)) {
 
                 // single handshake message flight
-                return hasCompleted(holesMap.get(flightType));
+                boolean isReady = hasCompleted(flightType);
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Is the handshake message completed? " + isReady);
+                }
+
+                return isReady;
             }
 
             //
@@ -991,31 +1326,52 @@
             //
             if (flightType == HandshakeMessage.ht_server_hello) {
                 // Firstly, check the first flight handshake message.
-                if (!hasCompleted(holesMap.get(flightType))) {
+                if (!hasCompleted(flightType)) {
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                            "The ServerHello message is not completed yet.");
+                    }
+
                     return false;
                 }
 
                 //
                 // an abbreviated handshake
                 //
-                if (isAbbreviatedHandshake) {
-                    // Ready to use the flight if received the
-                    // ChangeCipherSpec and Finished messages.
-                    return hasFinisedMessage(bufferedFragments);
+                if (hasFinishedMessage(bufferedFragments)) {
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log("It's an abbreviated handshake.");
+                    }
+
+                    return true;
                 }
 
                 //
                 // a full handshake
                 //
-                if (lastHandshakeFragment.handshakeType !=
-                        HandshakeMessage.ht_server_hello_done) {
+                List<HoleDescriptor> holes = handshakeFlight.holesMap.get(
+                        HandshakeMessage.ht_server_hello_done);
+                if ((holes == null) || !holes.isEmpty()) {
                     // Not yet got the final message of the flight.
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log("Not yet got the ServerHelloDone message");
+                    }
+
                     return false;
                 }
 
                 // Have all handshake message been received?
-                return hasCompleted(bufferedFragments,
-                    flightTopMessageSeq, lastHandshakeFragment.messageSeq);
+                boolean isReady = hasCompleted(bufferedFragments,
+                            handshakeFlight.minMessageSeq,
+                            handshakeFlight.maxMessageSeq);
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Is the ServerHello flight (message " +
+                            handshakeFlight.minMessageSeq + "-" +
+                            handshakeFlight.maxMessageSeq +
+                            ") completed? " + isReady);
+                }
+
+                return isReady;
             }
 
             //
@@ -1029,92 +1385,65 @@
                 (flightType == HandshakeMessage.ht_client_key_exchange)) {
 
                 // Firstly, check the first flight handshake message.
-                if (!hasCompleted(holesMap.get(flightType))) {
-                    return false;
-                }
+                if (!hasCompleted(flightType)) {
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                            "The ClientKeyExchange or client Certificate " +
+                            "message is not completed yet.");
+                    }
 
-                if (!hasFinisedMessage(bufferedFragments)) {
-                    // not yet got the ChangeCipherSpec/Finished messages
                     return false;
                 }
 
-                if (flightType == HandshakeMessage.ht_client_key_exchange) {
-                    // single handshake message flight
-                    return true;
+                // Is client CertificateVerify a mandatory message?
+                if (flightType == HandshakeMessage.ht_certificate) {
+                    if (needClientVerify(bufferedFragments) &&
+                        !hasCompleted(ht_certificate_verify)) {
+
+                        if (debug != null && Debug.isOn("verbose")) {
+                            Debug.log(
+                                "Not yet have the CertificateVerify message");
+                        }
+
+                        return false;
+                    }
                 }
 
-                //
-                // flightType == HandshakeMessage.ht_certificate
-                //
-                // We don't support certificates containing fixed
-                // Diffie-Hellman parameters.  Therefore, CertificateVerify
-                // message is required if client Certificate message presents.
-                //
-                if (lastHandshakeFragment.handshakeType !=
-                        HandshakeMessage.ht_certificate_verify) {
-                    // Not yet got the final message of the flight.
+                if (!hasFinishedMessage(bufferedFragments)) {
+                    // not yet have the ChangeCipherSpec/Finished messages
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                            "Not yet have the ChangeCipherSpec and " +
+                            "Finished messages");
+                    }
+
                     return false;
                 }
 
                 // Have all handshake message been received?
-                return hasCompleted(bufferedFragments,
-                    flightTopMessageSeq, lastHandshakeFragment.messageSeq);
+                boolean isReady = hasCompleted(bufferedFragments,
+                            handshakeFlight.minMessageSeq,
+                            handshakeFlight.maxMessageSeq);
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log("Is the ClientKeyExchange flight (message " +
+                            handshakeFlight.minMessageSeq + "-" +
+                            handshakeFlight.maxMessageSeq +
+                            ") completed? " + isReady);
+                }
+
+                return isReady;
             }
 
             //
             // Otherwise, need to receive more handshake messages.
             //
-            return false;
-        }
-
-        private boolean isSessionResuming(
-                byte[] fragment, byte[] prevSid) throws SSLException {
-
-            // As the first fragment of ServerHello should be big enough
-            // to hold the session_id field, need not to worry about the
-            // fragmentation here.
-            if ((fragment == null) || (fragment.length < 38)) {
-                                    // 38: the minimal ServerHello body length
-                throw new SSLException(
-                        "Invalid ServerHello message: no sufficient data");
-            }
-
-            int sidLen = fragment[34];          // 34: the length field
-            if (sidLen > 32) {                  // opaque SessionID<0..32>
-                throw new SSLException(
-                        "Invalid ServerHello message: invalid session id");
-            }
-
-            if (fragment.length < 38 + sidLen) {
-                throw new SSLException(
-                        "Invalid ServerHello message: no sufficient data");
-            }
-
-            if (sidLen != 0 && (prevSid.length == sidLen)) {
-                // may be a session-resuming handshake
-                for (int i = 0; i < sidLen; i++) {
-                    if (prevSid[i] != fragment[35 + i]) {
-                                                // 35: the session identifier
-                        return false;
-                    }
-                }
-
-                return true;
+            if (debug != null && Debug.isOn("verbose")) {
+                Debug.log("Need to receive more handshake messages");
             }
 
             return false;
         }
 
-        private byte[] getSessionID(byte[] fragment) {
-            // The validity has been checked in the call to isSessionResuming().
-            int sidLen = fragment[34];      // 34: the sessionID length field
-
-            byte[] temporary = new byte[sidLen];
-            System.arraycopy(fragment, 35, temporary, 0, sidLen);
-
-            return temporary;
-        }
-
         // Looking for the ChangeCipherSpec and Finished messages.
         //
         // As the cached Finished message should be a ciphertext, we don't
@@ -1122,8 +1451,7 @@
         // to the spec of TLS/DTLS handshaking, a Finished message is always
         // sent immediately after a ChangeCipherSpec message.  The first
         // ciphertext handshake message should be the expected Finished message.
-        private boolean hasFinisedMessage(
-                Set<RecordFragment> fragments) {
+        private boolean hasFinishedMessage(Set<RecordFragment> fragments) {
 
             boolean hasCCS = false;
             boolean hasFin = false;
@@ -1147,7 +1475,35 @@
             return hasFin && hasCCS;
         }
 
-        private boolean hasCompleted(List<HoleDescriptor> holes) {
+        // Is client CertificateVerify a mandatory message?
+        //
+        // In the current implementation, client CertificateVerify is a
+        // mandatory message if the client Certificate is not empty.
+        private boolean needClientVerify(Set<RecordFragment> fragments) {
+
+            // The caller should have checked the completion of the first
+            // present handshake message.  Need not to check it again.
+            for (RecordFragment rFrag : fragments) {
+                if ((rFrag.contentType != Record.ct_handshake) ||
+                        rFrag.isCiphertext) {
+                    break;
+                }
+
+                HandshakeFragment hsFrag = (HandshakeFragment)rFrag;
+                if (hsFrag.handshakeType != HandshakeMessage.ht_certificate) {
+                    continue;
+                }
+
+                return (rFrag.fragment != null) &&
+                   (rFrag.fragment.length > DTLSRecord.minCertPlaintextSize);
+            }
+
+            return false;
+        }
+
+        private boolean hasCompleted(byte handshakeType) {
+            List<HoleDescriptor> holes =
+                    handshakeFlight.holesMap.get(handshakeType);
             if (holes == null) {
                 // not yet received this kind of handshake message
                 return false;
@@ -1173,7 +1529,7 @@
                     continue;
                 } else if (hsFrag.messageSeq == (presentMsgSeq + 1)) {
                     // check the completion of the handshake message
-                    if (!hasCompleted(holesMap.get(hsFrag.handshakeType))) {
+                    if (!hasCompleted(hsFrag.handshakeType)) {
                         return false;
                     }
 
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSOutputRecord.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -279,6 +279,16 @@
         fragmenter = null;
     }
 
+    @Override
+    void launchRetransmission() {
+        // Note: Please don't retransmit if there are handshake messages
+        // or alerts waiting in the queue.
+        if (((alertMemos == null) || alertMemos.isEmpty()) &&
+                (fragmenter != null) && fragmenter.isRetransmittable()) {
+            fragmenter.setRetransmission();
+        }
+    }
+
     // buffered record fragment
     private static class RecordMemo {
         byte            contentType;
--- a/jdk/src/java.base/share/classes/sun/security/ssl/DTLSRecord.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/DTLSRecord.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -84,4 +84,18 @@
                                     + maxPadding            // padding
                                     + maxMacSize;           // MAC
 
+    /*
+     * Minimum record size of Certificate handshake message.
+     * Client sends a certificate message containing no certificates if no
+     * suitable certificate is available.  That is, the certificate_list
+     * structure has a length of zero.
+     *
+     *   struct {
+     *       ASN.1Cert certificate_list<0..2^24-1>;
+     *   } Certificate;
+     */
+    static final int    minCertPlaintextSize =
+                                      headerSize            // record header
+                                    + handshakeHeaderSize   // handshake header
+                                    + 3;                    // cert list length
 }
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Debug.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, 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
@@ -145,6 +145,13 @@
     }
 
     /**
+     * Print a message to stdout.
+     */
+    static void log(String message) {
+        System.out.println(Thread.currentThread().getName() + ": " + message);
+    }
+
+    /**
      * print a blank line to stderr that is prefixed with the prefix.
      */
 
@@ -156,7 +163,6 @@
     /**
      * print a message to stderr that is prefixed with the prefix.
      */
-
     public static void println(String prefix, String message)
     {
         System.err.println(prefix + ": "+message);
--- a/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/OutputRecord.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -194,6 +194,11 @@
         // blank
     }
 
+    // apply to DTLS SSLEngine
+    void launchRetransmission() {
+        // blank
+    }
+
     @Override
     public synchronized void close() throws IOException {
         if (!isClosed) {
@@ -224,6 +229,9 @@
             sequenceNumber = authenticator.sequenceNumber();
         }
 
+        // The sequence number may be shared for different purpose.
+        boolean sharedSequenceNumber = false;
+
         // "flip" but skip over header again, add MAC & encrypt
         if (authenticator instanceof MAC) {
             MAC signer = (MAC)authenticator;
@@ -243,6 +251,11 @@
                 // reset the position and limit
                 destination.limit(destination.position());
                 destination.position(dstContent);
+
+                // The signer has used and increased the sequence number.
+                if (isDTLS) {
+                    sharedSequenceNumber = true;
+                }
             }
         }
 
@@ -261,6 +274,11 @@
 
             // Encrypt may pad, so again the limit may be changed.
             encCipher.encrypt(destination, dstLim);
+
+            // The cipher has used and increased the sequence number.
+            if (isDTLS && encCipher.isAEADMode()) {
+                sharedSequenceNumber = true;
+            }
         } else {
             destination.position(destination.limit());
         }
@@ -290,8 +308,10 @@
             destination.put(headerOffset + 11, (byte)(fragLen >> 8));
             destination.put(headerOffset + 12, (byte)fragLen);
 
-            // Increase the sequence number for next use.
-            authenticator.increaseSequenceNumber();
+            // Increase the sequence number for next use if it is not shared.
+            if (!sharedSequenceNumber) {
+                authenticator.increaseSequenceNumber();
+            }
         }
 
         // Update destination position to reflect the amount of data produced.
--- a/jdk/src/java.base/share/classes/sun/security/ssl/Plaintext.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/Plaintext.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -38,7 +38,7 @@
     byte            majorVersion;
     byte            minorVersion;
     int             recordEpoch;    // incremented on every cipher state change
-    long            recordSN;
+    long            recordSN;       // contains epcoh number (epoch | sequence)
     ByteBuffer      fragment;       // null if need to be reassembled
 
     HandshakeStatus handshakeStatus;    // null if not used or not handshaking
--- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -994,7 +994,22 @@
 
         // plainText should never be null for TLS protocols
         HandshakeStatus hsStatus = null;
-        if (!isDTLS || plainText != null) {
+        if (plainText == Plaintext.PLAINTEXT_NULL) {
+            // Only happens for DTLS protocols.
+            //
+            // Received a retransmitted flight, and need to retransmit the
+            // previous delivered handshake flight messages.
+            if (enableRetransmissions) {
+                if (debug != null && Debug.isOn("verbose")) {
+                    Debug.log(
+                        "Retransmit the previous handshake flight messages.");
+                }
+
+                synchronized (this) {
+                    outputRecord.launchRetransmission();
+                }
+            }   // Otherwise, discard the retransmitted flight.
+        } else if (!isDTLS || plainText != null) {
             hsStatus = processInputRecord(plainText, appData, offset, length);
         }
 
@@ -1003,7 +1018,7 @@
         }
 
         if (plainText == null) {
-            plainText = new Plaintext();
+            plainText = Plaintext.PLAINTEXT_NULL;
         }
         plainText.handshakeStatus = hsStatus;
 
@@ -1378,7 +1393,8 @@
             // Acquire the buffered to-be-delivered records or retransmissions.
             //
             // May have buffered records, or need retransmission if handshaking.
-            if (!outputRecord.isEmpty() || (handshaker != null)) {
+            if (!outputRecord.isEmpty() ||
+                    (enableRetransmissions && handshaker != null)) {
                 ciphertext = outputRecord.acquireCiphertext(netData);
             }
 
@@ -1403,13 +1419,36 @@
 
         HandshakeStatus hsStatus = null;
         Ciphertext.RecordType recordType = ciphertext.recordType;
-        if ((handshaker != null) &&
-                (recordType.contentType == Record.ct_handshake) &&
-                (recordType.handshakeType == HandshakeMessage.ht_finished) &&
-                handshaker.isDone() && outputRecord.isEmpty()) {
+        if ((recordType.contentType == Record.ct_handshake) &&
+            (recordType.handshakeType == HandshakeMessage.ht_finished) &&
+            outputRecord.isEmpty()) {
+
+            if (handshaker == null) {
+                hsStatus = HandshakeStatus.FINISHED;
+            } else if (handshaker.isDone()) {
+                hsStatus = finishHandshake();
+                connectionState = cs_DATA;
 
-            hsStatus = finishHandshake();
-            connectionState = cs_DATA;
+                // Retransmit the last flight twice.
+                //
+                // The application data transactions may begin immediately
+                // after the last flight.  If the last flight get lost, the
+                // application data may be discarded accordingly.  As could
+                // be an issue for some applications.  This impact can be
+                // mitigated by sending the last fligth twice.
+                if (isDTLS && enableRetransmissions) {
+                    if (debug != null && Debug.isOn("verbose")) {
+                        Debug.log(
+                            "Retransmit the last flight messages.");
+                    }
+
+                    synchronized (this) {
+                        outputRecord.launchRetransmission();
+                    }
+
+                    hsStatus = HandshakeStatus.NEED_WRAP;
+                }
+            }
         }   // Otherwise, the followed call to getHSStatus() will help.
 
         /*
@@ -1676,12 +1715,17 @@
 
     synchronized void fatal(byte description, String diagnostic)
             throws SSLException {
-        fatal(description, diagnostic, null);
+        fatal(description, diagnostic, null, false);
     }
 
     synchronized void fatal(byte description, Throwable cause)
             throws SSLException {
-        fatal(description, null, cause);
+        fatal(description, null, cause, false);
+    }
+
+    synchronized void fatal(byte description, String diagnostic,
+            Throwable cause) throws SSLException {
+        fatal(description, diagnostic, cause, false);
     }
 
     /*
@@ -1693,12 +1737,12 @@
      * levels which then call here.  This code needs to determine
      * if one of the lower levels has already started the process.
      *
-     * We won't worry about Error's, if we have one of those,
+     * We won't worry about Errors, if we have one of those,
      * we're in worse trouble.  Note:  the networking code doesn't
      * deal with Errors either.
      */
     synchronized void fatal(byte description, String diagnostic,
-            Throwable cause) throws SSLException {
+            Throwable cause, boolean recvFatalAlert) throws SSLException {
 
         /*
          * If we have no further information, make a general-purpose
@@ -1759,10 +1803,11 @@
         }
 
         /*
-         * If we haven't even started handshaking yet, no need
-         * to generate the fatal close alert.
+         * If we haven't even started handshaking yet, or we are the
+         * recipient of a fatal alert, no need to generate a fatal close
+         * alert.
          */
-        if (oldState != cs_START) {
+        if (oldState != cs_START && !recvFatalAlert) {
             sendAlert(Alerts.alert_fatal, description);
         }
 
@@ -1802,10 +1847,6 @@
         byte level = fragment.get();
         byte description = fragment.get();
 
-        if (description == -1) { // check for short message
-            fatal(Alerts.alert_illegal_parameter, "Short alert message");
-        }
-
         if (debug != null && (Debug.isOn("record") ||
                 Debug.isOn("handshake"))) {
             synchronized (System.out) {
@@ -1823,7 +1864,9 @@
         }
 
         if (level == Alerts.alert_warning) {
-            if (description == Alerts.alert_close_notify) {
+            if (description == -1) {    // check for short message
+                fatal(Alerts.alert_illegal_parameter, "Short alert message");
+            } else if (description == Alerts.alert_close_notify) {
                 if (connectionState == cs_HANDSHAKE) {
                     fatal(Alerts.alert_unexpected_message,
                                 "Received close_notify during handshake");
@@ -1846,10 +1889,14 @@
         } else { // fatal or unknown level
             String reason = "Received fatal alert: "
                 + Alerts.alertDescription(description);
-            if (closeReason == null) {
-                closeReason = Alerts.getSSLException(description, reason);
-            }
-            fatal(Alerts.alert_unexpected_message, reason);
+
+            // The inbound and outbound queues will be closed as part of
+            // the call to fatal.  The handhaker to needs to be set to null
+            // so subsequent calls to getHandshakeStatus will return
+            // NOT_HANDSHAKING.
+            handshaker = null;
+            Throwable cause = Alerts.getSSLException(description, reason);
+            fatal(description, null, cause, true);
         }
     }
 
--- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -558,73 +558,6 @@
             applicationProtocol = "";
         }
 
-        // cookie exchange
-        if (isDTLS) {
-             HelloCookieManager hcMgr = sslContext.getHelloCookieManager();
-             if ((mesg.cookie == null) || (mesg.cookie.length == 0) ||
-                    (!hcMgr.isValid(mesg))) {
-
-                //
-                // Perform cookie exchange for DTLS handshaking if no cookie
-                // or the cookie is invalid in the ClientHello message.
-                //
-                HelloVerifyRequest m0 = new HelloVerifyRequest(hcMgr, mesg);
-
-                if (debug != null && Debug.isOn("handshake")) {
-                    m0.print(System.out);
-                }
-
-                m0.write(output);
-                handshakeState.update(m0, resumingSession);
-                output.flush();
-
-                return;
-            }
-        }
-
-        /*
-         * FIRST, construct the ServerHello using the options and priorities
-         * from the ClientHello.  Update the (pending) cipher spec as we do
-         * so, and save the client's version to protect against rollback
-         * attacks.
-         *
-         * There are a bunch of minor tasks here, and one major one: deciding
-         * if the short or the full handshake sequence will be used.
-         */
-        ServerHello m1 = new ServerHello();
-
-        clientRequestedVersion = mesg.protocolVersion;
-
-        // select a proper protocol version.
-        ProtocolVersion selectedVersion =
-               selectProtocolVersion(clientRequestedVersion);
-        if (selectedVersion == null ||
-                selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
-            fatalSE(Alerts.alert_handshake_failure,
-                "Client requested protocol " + clientRequestedVersion +
-                " not enabled or not supported");
-        }
-
-        handshakeHash.protocolDetermined(selectedVersion);
-        setVersion(selectedVersion);
-
-        m1.protocolVersion = protocolVersion;
-
-        //
-        // random ... save client and server values for later use
-        // in computing the master secret (from pre-master secret)
-        // and thence the other crypto keys.
-        //
-        // NOTE:  this use of three inputs to generating _each_ set
-        // of ciphers slows things down, but it does increase the
-        // security since each connection in the session can hold
-        // its own authenticated (and strong) keys.  One could make
-        // creation of a session a rare thing...
-        //
-        clnt_random = mesg.clnt_random;
-        svr_random = new RandomCookie(sslContext.getSecureRandom());
-        m1.svr_random = svr_random;
-
         session = null; // forget about the current session
         //
         // Here we go down either of two paths:  (a) the fast one, where
@@ -732,6 +665,73 @@
             }
         }   // else client did not try to resume
 
+        // cookie exchange
+        if (isDTLS && !resumingSession) {
+             HelloCookieManager hcMgr = sslContext.getHelloCookieManager();
+             if ((mesg.cookie == null) || (mesg.cookie.length == 0) ||
+                    (!hcMgr.isValid(mesg))) {
+
+                //
+                // Perform cookie exchange for DTLS handshaking if no cookie
+                // or the cookie is invalid in the ClientHello message.
+                //
+                HelloVerifyRequest m0 = new HelloVerifyRequest(hcMgr, mesg);
+
+                if (debug != null && Debug.isOn("handshake")) {
+                    m0.print(System.out);
+                }
+
+                m0.write(output);
+                handshakeState.update(m0, resumingSession);
+                output.flush();
+
+                return;
+            }
+        }
+
+        /*
+         * FIRST, construct the ServerHello using the options and priorities
+         * from the ClientHello.  Update the (pending) cipher spec as we do
+         * so, and save the client's version to protect against rollback
+         * attacks.
+         *
+         * There are a bunch of minor tasks here, and one major one: deciding
+         * if the short or the full handshake sequence will be used.
+         */
+        ServerHello m1 = new ServerHello();
+
+        clientRequestedVersion = mesg.protocolVersion;
+
+        // select a proper protocol version.
+        ProtocolVersion selectedVersion =
+               selectProtocolVersion(clientRequestedVersion);
+        if (selectedVersion == null ||
+                selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
+            fatalSE(Alerts.alert_handshake_failure,
+                "Client requested protocol " + clientRequestedVersion +
+                " not enabled or not supported");
+        }
+
+        handshakeHash.protocolDetermined(selectedVersion);
+        setVersion(selectedVersion);
+
+        m1.protocolVersion = protocolVersion;
+
+        //
+        // random ... save client and server values for later use
+        // in computing the master secret (from pre-master secret)
+        // and thence the other crypto keys.
+        //
+        // NOTE:  this use of three inputs to generating _each_ set
+        // of ciphers slows things down, but it does increase the
+        // security since each connection in the session can hold
+        // its own authenticated (and strong) keys.  One could make
+        // creation of a session a rare thing...
+        //
+        clnt_random = mesg.clnt_random;
+        svr_random = new RandomCookie(sslContext.getSecureRandom());
+        m1.svr_random = svr_random;
+
         //
         // If client hasn't specified a session we can resume, start a
         // new one and choose its cipher suite and compression options.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/BreakDictionary.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,306 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - 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.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * This is the class that represents the list of known words used by
+ * DictionaryBasedBreakIterator.  The conceptual data structure used
+ * here is a trie: there is a node hanging off the root node for every
+ * letter that can start a word.  Each of these nodes has a node hanging
+ * off of it for every letter that can be the second letter of a word
+ * if this node is the first letter, and so on.  The trie is represented
+ * as a two-dimensional array that can be treated as a table of state
+ * transitions.  Indexes are used to compress this array, taking
+ * advantage of the fact that this array will always be very sparse.
+ */
+class BreakDictionary {
+
+    //=========================================================================
+    // data members
+    //=========================================================================
+
+    /**
+      * The version of the dictionary that was read in.
+      */
+    private static int supportedVersion = 1;
+
+    /**
+     * Maps from characters to column numbers.  The main use of this is to
+     * avoid making room in the array for empty columns.
+     */
+    private CompactByteArray columnMap = null;
+    private SupplementaryCharacterData supplementaryCharColumnMap = null;
+
+    /**
+     * The number of actual columns in the table
+     */
+    private int numCols;
+
+    /**
+     * Columns are organized into groups of 32.  This says how many
+     * column groups.  (We could calculate this, but we store the
+     * value to avoid having to repeatedly calculate it.)
+     */
+    private int numColGroups;
+
+    /**
+     * The actual compressed state table.  Each conceptual row represents
+     * a state, and the cells in it contain the row numbers of the states
+     * to transition to for each possible letter.  0 is used to indicate
+     * an illegal combination of letters (i.e., the error state).  The
+     * table is compressed by eliminating all the unpopulated (i.e., zero)
+     * cells.  Multiple conceptual rows can then be doubled up in a single
+     * physical row by sliding them up and possibly shifting them to one
+     * side or the other so the populated cells don't collide.  Indexes
+     * are used to identify unpopulated cells and to locate populated cells.
+     */
+    private short[] table = null;
+
+    /**
+     * This index maps logical row numbers to physical row numbers
+     */
+    private short[] rowIndex = null;
+
+    /**
+     * A bitmap is used to tell which cells in the comceptual table are
+     * populated.  This array contains all the unique bit combinations
+     * in that bitmap.  If the table is more than 32 columns wide,
+     * successive entries in this array are used for a single row.
+     */
+    private int[] rowIndexFlags = null;
+
+    /**
+     * This index maps from a logical row number into the bitmap table above.
+     * (This keeps us from storing duplicate bitmap combinations.)  Since there
+     * are a lot of rows with only one populated cell, instead of wasting space
+     * in the bitmap table, we just store a negative number in this index for
+     * rows with one populated cell.  The absolute value of that number is
+     * the column number of the populated cell.
+     */
+    private short[] rowIndexFlagsIndex = null;
+
+    /**
+     * For each logical row, this index contains a constant that is added to
+     * the logical column number to get the physical column number
+     */
+    private byte[] rowIndexShifts = null;
+
+    //=========================================================================
+    // deserialization
+    //=========================================================================
+
+    BreakDictionary(String dictionaryName, byte[] dictionaryData) {
+        try {
+            setupDictionary(dictionaryName, dictionaryData);
+        } catch (BufferUnderflowException bue) {
+            MissingResourceException e;
+            e = new MissingResourceException("Corrupted dictionary data",
+                                             dictionaryName, "");
+            e.initCause(bue);
+            throw e;
+        }
+    }
+
+    private void setupDictionary(String dictionaryName, byte[] dictionaryData) {
+        ByteBuffer bb = ByteBuffer.wrap(dictionaryData);
+
+        // check version
+        int version = bb.getInt();
+        if (version != supportedVersion) {
+            throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
+                                               dictionaryName, "");
+        }
+
+        // Check data size
+        int len = bb.getInt();
+        if (bb.position() + len != bb.limit()) {
+            throw new MissingResourceException("Dictionary size is wrong: " + bb.limit(),
+                                               dictionaryName, "");
+        }
+
+        // read in the column map for BMP characteres (this is serialized in
+        // its internal form: an index array followed by a data array)
+        len = bb.getInt();
+        short[] temp = new short[len];
+        for (int i = 0; i < len; i++) {
+            temp[i] = bb.getShort();
+        }
+        len = bb.getInt();
+        byte[] temp2 = new byte[len];
+        bb.get(temp2);
+        columnMap = new CompactByteArray(temp, temp2);
+
+        // read in numCols and numColGroups
+        numCols = bb.getInt();
+        numColGroups = bb.getInt();
+
+        // read in the row-number index
+        len = bb.getInt();
+        rowIndex = new short[len];
+        for (int i = 0; i < len; i++) {
+            rowIndex[i] = bb.getShort();
+        }
+
+        // load in the populated-cells bitmap: index first, then bitmap list
+        len = bb.getInt();
+        rowIndexFlagsIndex = new short[len];
+        for (int i = 0; i < len; i++) {
+            rowIndexFlagsIndex[i] = bb.getShort();
+        }
+        len = bb.getInt();
+        rowIndexFlags = new int[len];
+        for (int i = 0; i < len; i++) {
+            rowIndexFlags[i] = bb.getInt();
+        }
+
+        // load in the row-shift index
+        len = bb.getInt();
+        rowIndexShifts = new byte[len];
+        bb.get(rowIndexShifts);
+
+        // load in the actual state table
+        len = bb.getInt();
+        table = new short[len];
+        for (int i = 0; i < len; i++) {
+            table[i] = bb.getShort();
+        }
+
+        // finally, prepare the column map for supplementary characters
+        len = bb.getInt();
+        int[] temp3 = new int[len];
+        for (int i = 0; i < len; i++) {
+            temp3[i] = bb.getInt();
+        }
+        assert bb.position() == bb.limit();
+
+        supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
+    }
+
+    //=========================================================================
+    // access to the words
+    //=========================================================================
+
+    /**
+     * Uses the column map to map the character to a column number, then
+     * passes the row and column number to getNextState()
+     * @param row The current state
+     * @param ch The character whose column we're interested in
+     * @return The new state to transition to
+     */
+    public final short getNextStateFromCharacter(int row, int ch) {
+        int col;
+        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            col = columnMap.elementAt((char)ch);
+        } else {
+            col = supplementaryCharColumnMap.getValue(ch);
+        }
+        return getNextState(row, col);
+    }
+
+    /**
+     * Returns the value in the cell with the specified (logical) row and
+     * column numbers.  In DictionaryBasedBreakIterator, the row number is
+     * a state number, the column number is an input, and the return value
+     * is the row number of the new state to transition to.  (0 is the
+     * "error" state, and -1 is the "end of word" state in a dictionary)
+     * @param row The row number of the current state
+     * @param col The column number of the input character (0 means "not a
+     * dictionary character")
+     * @return The row number of the new state to transition to
+     */
+    public final short getNextState(int row, int col) {
+        if (cellIsPopulated(row, col)) {
+            // we map from logical to physical row number by looking up the
+            // mapping in rowIndex; we map from logical column number to
+            // physical column number by looking up a shift value for this
+            // logical row and offsetting the logical column number by
+            // the shift amount.  Then we can use internalAt() to actually
+            // get the value out of the table.
+            return internalAt(rowIndex[row], col + rowIndexShifts[row]);
+        }
+        else {
+            return 0;
+        }
+    }
+
+    /**
+     * Given (logical) row and column numbers, returns true if the
+     * cell in that position is populated
+     */
+    private boolean cellIsPopulated(int row, int col) {
+        // look up the entry in the bitmap index for the specified row.
+        // If it's a negative number, it's the column number of the only
+        // populated cell in the row
+        if (rowIndexFlagsIndex[row] < 0) {
+            return col == -rowIndexFlagsIndex[row];
+        }
+
+        // if it's a positive number, it's the offset of an entry in the bitmap
+        // list.  If the table is more than 32 columns wide, the bitmap is stored
+        // successive entries in the bitmap list, so we have to divide the column
+        // number by 32 and offset the number we got out of the index by the result.
+        // Once we have the appropriate piece of the bitmap, test the appropriate
+        // bit and return the result.
+        else {
+            int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
+            return (flags & (1 << (col & 0x1f))) != 0;
+        }
+    }
+
+    /**
+     * Implementation of getNextState() when we know the specified cell is
+     * populated.
+     * @param row The PHYSICAL row number of the cell
+     * @param col The PHYSICAL column number of the cell
+     * @return The value stored in the cell
+     */
+    private short internalAt(int row, int col) {
+        // the table is a one-dimensional array, so this just does the math necessary
+        // to treat it as a two-dimensional array (we don't just use a two-dimensional
+        // array because two-dimensional arrays are inefficient in Java)
+        return table[row * numCols + col];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/DictionaryBasedBreakIterator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,526 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - 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.text;
+
+import java.text.CharacterIterator;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+/**
+ * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
+ * to further subdivide ranges of text beyond what is possible using just the
+ * state-table-based algorithm.  This is necessary, for example, to handle
+ * word and line breaking in Thai, which doesn't use spaces between words.  The
+ * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
+ * up text as far as possible, and then contiguous ranges of letters are
+ * repeatedly compared against a list of known words (i.e., the dictionary)
+ * to divide them up into words.
+ *
+ * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
+ * but adds one more special substitution name: &lt;dictionary&gt;.  This substitution
+ * name is used to identify characters in words in the dictionary.  The idea is that
+ * if the iterator passes over a chunk of text that includes two or more characters
+ * in a row that are included in &lt;dictionary&gt;, it goes back through that range and
+ * derives additional break positions (if possible) using the dictionary.
+ *
+ * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
+ * file.  It follows a prescribed search path to locate the dictionary (right now,
+ * it looks for it in /com/ibm/text/resources in each directory in the classpath,
+ * and won't find it in JAR files, but this location is likely to change).  The
+ * dictionary file is in a serialized binary format.  We have a very primitive (and
+ * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
+ * currently making it public.  Contact us for help.
+ */
+public class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
+
+    /**
+     * a list of known words that is used to divide up contiguous ranges of letters,
+     * stored in a compressed, indexed, format that offers fast access
+     */
+    private BreakDictionary dictionary;
+
+    /**
+     * a list of flags indicating which character categories are contained in
+     * the dictionary file (this is used to determine which ranges of characters
+     * to apply the dictionary to)
+     */
+    private boolean[] categoryFlags;
+
+    /**
+     * a temporary hiding place for the number of dictionary characters in the
+     * last range passed over by next()
+     */
+    private int dictionaryCharCount;
+
+    /**
+     * when a range of characters is divided up using the dictionary, the break
+     * positions that are discovered are stored here, preventing us from having
+     * to use either the dictionary or the state table again until the iterator
+     * leaves this range of text
+     */
+    private int[] cachedBreakPositions;
+
+    /**
+     * if cachedBreakPositions is not null, this indicates which item in the
+     * cache the current iteration position refers to
+     */
+    private int positionInCache;
+
+    /**
+     * Constructs a DictionaryBasedBreakIterator.
+     *
+     * @param ruleFile       the name of the rule data file
+     * @param ruleData       the rule data loaded from the rule data file
+     * @param dictionaryFile the name of the dictionary file
+     * @param dictionartData the dictionary data loaded from the dictionary file
+     * @throws MissingResourceException if rule data or dictionary initialization failed
+     */
+    public DictionaryBasedBreakIterator(String ruleFile, byte[] ruleData,
+                                        String dictionaryFile, byte[] dictionaryData) {
+        super(ruleFile, ruleData);
+        byte[] tmp = super.getAdditionalData();
+        if (tmp != null) {
+            prepareCategoryFlags(tmp);
+            super.setAdditionalData(null);
+        }
+        dictionary = new BreakDictionary(dictionaryFile, dictionaryData);
+    }
+
+    private void prepareCategoryFlags(byte[] data) {
+        categoryFlags = new boolean[data.length];
+        for (int i = 0; i < data.length; i++) {
+            categoryFlags[i] = (data[i] == (byte)1) ? true : false;
+        }
+    }
+
+    @Override
+    public void setText(CharacterIterator newText) {
+        super.setText(newText);
+        cachedBreakPositions = null;
+        dictionaryCharCount = 0;
+        positionInCache = 0;
+    }
+
+    /**
+     * Sets the current iteration position to the beginning of the text.
+     * (i.e., the CharacterIterator's starting offset).
+     * @return The offset of the beginning of the text.
+     */
+    @Override
+    public int first() {
+        cachedBreakPositions = null;
+        dictionaryCharCount = 0;
+        positionInCache = 0;
+        return super.first();
+    }
+
+    /**
+     * Sets the current iteration position to the end of the text.
+     * (i.e., the CharacterIterator's ending offset).
+     * @return The text's past-the-end offset.
+     */
+    @Override
+    public int last() {
+        cachedBreakPositions = null;
+        dictionaryCharCount = 0;
+        positionInCache = 0;
+        return super.last();
+    }
+
+    /**
+     * Advances the iterator one step backwards.
+     * @return The position of the last boundary position before the
+     * current iteration position
+     */
+    @Override
+    public int previous() {
+        CharacterIterator text = getText();
+
+        // if we have cached break positions and we're still in the range
+        // covered by them, just move one step backward in the cache
+        if (cachedBreakPositions != null && positionInCache > 0) {
+            --positionInCache;
+            text.setIndex(cachedBreakPositions[positionInCache]);
+            return cachedBreakPositions[positionInCache];
+        }
+
+        // otherwise, dump the cache and use the inherited previous() method to move
+        // backward.  This may fill up the cache with new break positions, in which
+        // case we have to mark our position in the cache
+        else {
+            cachedBreakPositions = null;
+            int result = super.previous();
+            if (cachedBreakPositions != null) {
+                positionInCache = cachedBreakPositions.length - 2;
+            }
+            return result;
+        }
+    }
+
+    /**
+     * Sets the current iteration position to the last boundary position
+     * before the specified position.
+     * @param offset The position to begin searching from
+     * @return The position of the last boundary before "offset"
+     */
+    @Override
+    public int preceding(int offset) {
+        CharacterIterator text = getText();
+        checkOffset(offset, text);
+
+        // if we have no cached break positions, or "offset" is outside the
+        // range covered by the cache, we can just call the inherited routine
+        // (which will eventually call other routines in this class that may
+        // refresh the cache)
+        if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
+                offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
+            cachedBreakPositions = null;
+            return super.preceding(offset);
+        }
+
+        // on the other hand, if "offset" is within the range covered by the cache,
+        // then all we have to do is search the cache for the last break position
+        // before "offset"
+        else {
+            positionInCache = 0;
+            while (positionInCache < cachedBreakPositions.length
+                   && offset > cachedBreakPositions[positionInCache]) {
+                ++positionInCache;
+            }
+            --positionInCache;
+            text.setIndex(cachedBreakPositions[positionInCache]);
+            return text.getIndex();
+        }
+    }
+
+    /**
+     * Sets the current iteration position to the first boundary position after
+     * the specified position.
+     * @param offset The position to begin searching forward from
+     * @return The position of the first boundary after "offset"
+     */
+    @Override
+    public int following(int offset) {
+        CharacterIterator text = getText();
+        checkOffset(offset, text);
+
+        // if we have no cached break positions, or if "offset" is outside the
+        // range covered by the cache, then dump the cache and call our
+        // inherited following() method.  This will call other methods in this
+        // class that may refresh the cache.
+        if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
+                offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
+            cachedBreakPositions = null;
+            return super.following(offset);
+        }
+
+        // on the other hand, if "offset" is within the range covered by the
+        // cache, then just search the cache for the first break position
+        // after "offset"
+        else {
+            positionInCache = 0;
+            while (positionInCache < cachedBreakPositions.length
+                   && offset >= cachedBreakPositions[positionInCache]) {
+                ++positionInCache;
+            }
+            text.setIndex(cachedBreakPositions[positionInCache]);
+            return text.getIndex();
+        }
+    }
+
+    /**
+     * This is the implementation function for next().
+     */
+    @Override
+    protected int handleNext() {
+        CharacterIterator text = getText();
+
+        // if there are no cached break positions, or if we've just moved
+        // off the end of the range covered by the cache, we have to dump
+        // and possibly regenerate the cache
+        if (cachedBreakPositions == null ||
+            positionInCache == cachedBreakPositions.length - 1) {
+
+            // start by using the inherited handleNext() to find a tentative return
+            // value.   dictionaryCharCount tells us how many dictionary characters
+            // we passed over on our way to the tentative return value
+            int startPos = text.getIndex();
+            dictionaryCharCount = 0;
+            int result = super.handleNext();
+
+            // if we passed over more than one dictionary character, then we use
+            // divideUpDictionaryRange() to regenerate the cached break positions
+            // for the new range
+            if (dictionaryCharCount > 1 && result - startPos > 1) {
+                divideUpDictionaryRange(startPos, result);
+            }
+
+            // otherwise, the value we got back from the inherited fuction
+            // is our return value, and we can dump the cache
+            else {
+                cachedBreakPositions = null;
+                return result;
+            }
+        }
+
+        // if the cache of break positions has been regenerated (or existed all
+        // along), then just advance to the next break position in the cache
+        // and return it
+        if (cachedBreakPositions != null) {
+            ++positionInCache;
+            text.setIndex(cachedBreakPositions[positionInCache]);
+            return cachedBreakPositions[positionInCache];
+        }
+        return -9999;   // SHOULD NEVER GET HERE!
+    }
+
+    /**
+     * Looks up a character category for a character.
+     */
+    @Override
+    protected int lookupCategory(int c) {
+        // this override of lookupCategory() exists only to keep track of whether we've
+        // passed over any dictionary characters.  It calls the inherited lookupCategory()
+        // to do the real work, and then checks whether its return value is one of the
+        // categories represented in the dictionary.  If it is, bump the dictionary-
+        // character count.
+        int result = super.lookupCategory(c);
+        if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
+            ++dictionaryCharCount;
+        }
+        return result;
+    }
+
+    /**
+     * This is the function that actually implements the dictionary-based
+     * algorithm.  Given the endpoints of a range of text, it uses the
+     * dictionary to determine the positions of any boundaries in this
+     * range.  It stores all the boundary positions it discovers in
+     * cachedBreakPositions so that we only have to do this work once
+     * for each time we enter the range.
+     */
+    @SuppressWarnings("unchecked")
+    private void divideUpDictionaryRange(int startPos, int endPos) {
+        CharacterIterator text = getText();
+
+        // the range we're dividing may begin or end with non-dictionary characters
+        // (i.e., for line breaking, we may have leading or trailing punctuation
+        // that needs to be kept with the word).  Seek from the beginning of the
+        // range to the first dictionary character
+        text.setIndex(startPos);
+        int c = getCurrent();
+        int category = lookupCategory(c);
+        while (category == IGNORE || !categoryFlags[category]) {
+            c = getNext();
+            category = lookupCategory(c);
+        }
+
+        // initialize.  We maintain two stacks: currentBreakPositions contains
+        // the list of break positions that will be returned if we successfully
+        // finish traversing the whole range now.  possibleBreakPositions lists
+        // all other possible word ends we've passed along the way.  (Whenever
+        // we reach an error [a sequence of characters that can't begin any word
+        // in the dictionary], we back up, possibly delete some breaks from
+        // currentBreakPositions, move a break from possibleBreakPositions
+        // to currentBreakPositions, and start over from there.  This process
+        // continues in this way until we either successfully make it all the way
+        // across the range, or exhaust all of our combinations of break
+        // positions.)
+        Stack<Integer> currentBreakPositions = new Stack<>();
+        Stack<Integer> possibleBreakPositions = new Stack<>();
+        List<Integer> wrongBreakPositions = new ArrayList<>();
+
+        // the dictionary is implemented as a trie, which is treated as a state
+        // machine.  -1 represents the end of a legal word.  Every word in the
+        // dictionary is represented by a path from the root node to -1.  A path
+        // that ends in state 0 is an illegal combination of characters.
+        int state = 0;
+
+        // these two variables are used for error handling.  We keep track of the
+        // farthest we've gotten through the range being divided, and the combination
+        // of breaks that got us that far.  If we use up all possible break
+        // combinations, the text contains an error or a word that's not in the
+        // dictionary.  In this case, we "bless" the break positions that got us the
+        // farthest as real break positions, and then start over from scratch with
+        // the character where the error occurred.
+        int farthestEndPoint = text.getIndex();
+        Stack<Integer> bestBreakPositions = null;
+
+        // initialize (we always exit the loop with a break statement)
+        c = getCurrent();
+        while (true) {
+
+            // if we can transition to state "-1" from our current state, we're
+            // on the last character of a legal word.  Push that position onto
+            // the possible-break-positions stack
+            if (dictionary.getNextState(state, 0) == -1) {
+                possibleBreakPositions.push(text.getIndex());
+            }
+
+            // look up the new state to transition to in the dictionary
+            state = dictionary.getNextStateFromCharacter(state, c);
+
+            // if the character we're sitting on causes us to transition to
+            // the "end of word" state, then it was a non-dictionary character
+            // and we've successfully traversed the whole range.  Drop out
+            // of the loop.
+            if (state == -1) {
+                currentBreakPositions.push(text.getIndex());
+                break;
+            }
+
+            // if the character we're sitting on causes us to transition to
+            // the error state, or if we've gone off the end of the range
+            // without transitioning to the "end of word" state, we've hit
+            // an error...
+            else if (state == 0 || text.getIndex() >= endPos) {
+
+                // if this is the farthest we've gotten, take note of it in
+                // case there's an error in the text
+                if (text.getIndex() > farthestEndPoint) {
+                    farthestEndPoint = text.getIndex();
+
+                    @SuppressWarnings("unchecked")
+                    Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
+
+                    bestBreakPositions = currentBreakPositionsCopy;
+                }
+
+                // wrongBreakPositions is a list of all break positions
+                // we've tried starting that didn't allow us to traverse
+                // all the way through the text.  Every time we pop a
+                // break position off of currentBreakPositions, we put it
+                // into wrongBreakPositions to avoid trying it again later.
+                // If we make it to this spot, we're either going to back
+                // up to a break in possibleBreakPositions and try starting
+                // over from there, or we've exhausted all possible break
+                // positions and are going to do the fallback procedure.
+                // This loop prevents us from messing with anything in
+                // possibleBreakPositions that didn't work as a starting
+                // point the last time we tried it (this is to prevent a bunch of
+                // repetitive checks from slowing down some extreme cases)
+                while (!possibleBreakPositions.isEmpty()
+                        && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
+                    possibleBreakPositions.pop();
+                }
+
+                // if we've used up all possible break-position combinations, there's
+                // an error or an unknown word in the text.  In this case, we start
+                // over, treating the farthest character we've reached as the beginning
+                // of the range, and "blessing" the break positions that got us that
+                // far as real break positions
+                if (possibleBreakPositions.isEmpty()) {
+                    if (bestBreakPositions != null) {
+                        currentBreakPositions = bestBreakPositions;
+                        if (farthestEndPoint < endPos) {
+                            text.setIndex(farthestEndPoint + 1);
+                        }
+                        else {
+                            break;
+                        }
+                    }
+                    else {
+                        if ((currentBreakPositions.size() == 0 ||
+                             currentBreakPositions.peek().intValue() != text.getIndex())
+                            && text.getIndex() != startPos) {
+                            currentBreakPositions.push(text.getIndex());
+                        }
+                        getNext();
+                        currentBreakPositions.push(text.getIndex());
+                    }
+                }
+
+                // if we still have more break positions we can try, then promote the
+                // last break in possibleBreakPositions into currentBreakPositions,
+                // and get rid of all entries in currentBreakPositions that come after
+                // it.  Then back up to that position and start over from there (i.e.,
+                // treat that position as the beginning of a new word)
+                else {
+                    Integer temp = possibleBreakPositions.pop();
+                    Integer temp2 = null;
+                    while (!currentBreakPositions.isEmpty() && temp.intValue() <
+                           currentBreakPositions.peek().intValue()) {
+                        temp2 = currentBreakPositions.pop();
+                        wrongBreakPositions.add(temp2);
+                    }
+                    currentBreakPositions.push(temp);
+                    text.setIndex(currentBreakPositions.peek().intValue());
+                }
+
+                // re-sync "c" for the next go-round, and drop out of the loop if
+                // we've made it off the end of the range
+                c = getCurrent();
+                if (text.getIndex() >= endPos) {
+                    break;
+                }
+            }
+
+            // if we didn't hit any exceptional conditions on this last iteration,
+            // just advance to the next character and loop
+            else {
+                c = getNext();
+            }
+        }
+
+        // dump the last break position in the list, and replace it with the actual
+        // end of the range (which may be the same character, or may be further on
+        // because the range actually ended with non-dictionary characters we want to
+        // keep with the word)
+        if (!currentBreakPositions.isEmpty()) {
+            currentBreakPositions.pop();
+        }
+        currentBreakPositions.push(endPos);
+
+        // create a regular array to hold the break positions and copy
+        // the break positions from the stack to the array (in addition,
+        // our starting position goes into this array as a break position).
+        // This array becomes the cache of break positions used by next()
+        // and previous(), so this is where we actually refresh the cache.
+        cachedBreakPositions = new int[currentBreakPositions.size() + 1];
+        cachedBreakPositions[0] = startPos;
+
+        for (int i = 0; i < currentBreakPositions.size(); i++) {
+            cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
+        }
+        positionInCache = 0;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/RuleBasedBreakIterator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,1144 @@
+/*
+ * 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.
+ */
+
+/*
+ *
+ * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
+ * (C) Copyright IBM Corp. 1996 - 2002 - 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.text;
+
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.text.BreakIterator;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+import java.util.MissingResourceException;
+import sun.text.CompactByteArray;
+import sun.text.SupplementaryCharacterData;
+
+/**
+ * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
+ *
+ * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
+ * and <i>regular expressions.</i></p>
+ *
+ * <p>A substitution rule defines a name that can be used in place of an expression. It
+ * consists of a name, which is a string of characters contained in angle brackets, an equals
+ * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
+ * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
+ * square brackets. A substitution is visible after its definition, and is filled in using
+ * simple textual substitution. Substitution definitions can contain other substitutions, as
+ * long as those substitutions have been defined first. Substitutions are generally used to
+ * make the regular expressions (which can get quite complex) shorted and easier to read.
+ * They typically define either character categories or commonly-used subexpressions.</p>
+ *
+ * <p>There is one special substitution.&nbsp; If the description defines a substitution
+ * called &quot;&lt;ignore&gt;&quot;, the expression must be a [] expression, and the
+ * expression defines a set of characters (the &quot;<em>ignore characters</em>&quot;) that
+ * will be transparent to the BreakIterator.&nbsp; A sequence of characters will break the
+ * same way it would if any ignore characters it contains are taken out.&nbsp; Break
+ * positions never occur befoer ignore characters.</p>
+ *
+ * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
+ * defines a sequence of characters to be kept together. With one significant exception, the
+ * iterator uses a longest-possible-match algorithm when matching text to regular
+ * expressions. The iterator also treats descriptions containing multiple regular expressions
+ * as if they were ORed together (i.e., as if they were separated by |).</p>
+ *
+ * <p>The special characters recognized by the regular-expression parser are as follows:</p>
+ *
+ * <blockquote>
+ *   <table border="1" width="100%">
+ *     <tr>
+ *       <td width="6%">*</td>
+ *       <td width="94%">Specifies that the expression preceding the asterisk may occur any number
+ *       of times (including not at all).</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">{}</td>
+ *       <td width="94%">Encloses a sequence of characters that is optional.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">()</td>
+ *       <td width="94%">Encloses a sequence of characters.&nbsp; If followed by *, the sequence
+ *       repeats.&nbsp; Otherwise, the parentheses are just a grouping device and a way to delimit
+ *       the ends of expressions containing |.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">|</td>
+ *       <td width="94%">Separates two alternative sequences of characters.&nbsp; Either one
+ *       sequence or the other, but not both, matches this expression.&nbsp; The | character can
+ *       only occur inside ().</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">.</td>
+ *       <td width="94%">Matches any character.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">*?</td>
+ *       <td width="94%">Specifies a non-greedy asterisk.&nbsp; *? works the same way as *, except
+ *       when there is overlap between the last group of characters in the expression preceding the
+ *       * and the first group of characters following the *.&nbsp; When there is this kind of
+ *       overlap, * will match the longest sequence of characters that match the expression before
+ *       the *, and *? will match the shortest sequence of characters matching the expression
+ *       before the *?.&nbsp; For example, if you have &quot;xxyxyyyxyxyxxyxyxyy&quot; in the text,
+ *       &quot;x[xy]*x&quot; will match through to the last x (i.e., &quot;<strong>xxyxyyyxyxyxxyxyx</strong>yy&quot;,
+ *       but &quot;x[xy]*?x&quot; will only match the first two xes (&quot;<strong>xx</strong>yxyyyxyxyxxyxyxyy&quot;).</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">[]</td>
+ *       <td width="94%">Specifies a group of alternative characters.&nbsp; A [] expression will
+ *       match any single character that is specified in the [] expression.&nbsp; For more on the
+ *       syntax of [] expressions, see below.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">/</td>
+ *       <td width="94%">Specifies where the break position should go if text matches this
+ *       expression.&nbsp; (e.g., &quot;[a-z]&#42;/[:Zs:]*[1-0]&quot; will match if the iterator sees a run
+ *       of letters, followed by a run of whitespace, followed by a digit, but the break position
+ *       will actually go before the whitespace).&nbsp; Expressions that don't contain / put the
+ *       break position at the end of the matching text.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">\</td>
+ *       <td width="94%">Escape character.&nbsp; The \ itself is ignored, but causes the next
+ *       character to be treated as literal character.&nbsp; This has no effect for many
+ *       characters, but for the characters listed above, this deprives them of their special
+ *       meaning.&nbsp; (There are no special escape sequences for Unicode characters, or tabs and
+ *       newlines; these are all handled by a higher-level protocol.&nbsp; In a Java string,
+ *       &quot;\n&quot; will be converted to a literal newline character by the time the
+ *       regular-expression parser sees it.&nbsp; Of course, this means that \ sequences that are
+ *       visible to the regexp parser must be written as \\ when inside a Java string.)&nbsp; All
+ *       characters in the ASCII range except for letters, digits, and control characters are
+ *       reserved characters to the parser and must be preceded by \ even if they currently don't
+ *       mean anything.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">!</td>
+ *       <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
+ *       parser that this expression specifies the backwards-iteration behavior of the iterator,
+ *       and not its normal iteration behavior.&nbsp; This is generally only used in situations
+ *       where the automatically-generated backwards-iteration brhavior doesn't produce
+ *       satisfactory results and must be supplemented with extra client-specified rules.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%"><em>(all others)</em></td>
+ *       <td width="94%">All other characters are treated as literal characters, which must match
+ *       the corresponding character(s) in the text exactly.</td>
+ *     </tr>
+ *   </table>
+ * </blockquote>
+ *
+ * <p>Within a [] expression, a number of other special characters can be used to specify
+ * groups of characters:</p>
+ *
+ * <blockquote>
+ *   <table border="1" width="100%">
+ *     <tr>
+ *       <td width="6%">-</td>
+ *       <td width="94%">Specifies a range of matching characters.&nbsp; For example
+ *       &quot;[a-p]&quot; matches all lowercase Latin letters from a to p (inclusive).&nbsp; The -
+ *       sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
+ *       language's alphabetical order: &quot;[a-z]&quot; doesn't include capital letters, nor does
+ *       it include accented letters such as a-umlaut.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">::</td>
+ *       <td width="94%">A pair of colons containing a one- or two-letter code matches all
+ *       characters in the corresponding Unicode category.&nbsp; The two-letter codes are the same
+ *       as the two-letter codes in the Unicode database (for example, &quot;[:Sc::Sm:]&quot;
+ *       matches all currency symbols and all math symbols).&nbsp; Specifying a one-letter code is
+ *       the same as specifying all two-letter codes that begin with that letter (for example,
+ *       &quot;[:L:]&quot; matches all letters, and is equivalent to
+ *       &quot;[:Lu::Ll::Lo::Lm::Lt:]&quot;).&nbsp; Anything other than a valid two-letter Unicode
+ *       category code or a single letter that begins a Unicode category code is illegal within
+ *       colons.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">[]</td>
+ *       <td width="94%">[] expressions can nest.&nbsp; This has no effect, except when used in
+ *       conjunction with the ^ token.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%">^</td>
+ *       <td width="94%">Excludes the character (or the characters in the [] expression) following
+ *       it from the group of characters.&nbsp; For example, &quot;[a-z^p]&quot; matches all Latin
+ *       lowercase letters except p.&nbsp; &quot;[:L:^[&#92;u4e00-&#92;u9fff]]&quot; matches all letters
+ *       except the Han ideographs.</td>
+ *     </tr>
+ *     <tr>
+ *       <td width="6%"><em>(all others)</em></td>
+ *       <td width="94%">All other characters are treated as literal characters.&nbsp; (For
+ *       example, &quot;[aeiou]&quot; specifies just the letters a, e, i, o, and u.)</td>
+ *     </tr>
+ *   </table>
+ * </blockquote>
+ *
+ * <p>For a more complete explanation, see <a
+ * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
+ * &nbsp; For examples, see the resource data (which is annotated).</p>
+ *
+ * @author Richard Gillam
+ */
+public class RuleBasedBreakIterator extends BreakIterator {
+
+    /**
+     * A token used as a character-category value to identify ignore characters
+     */
+    protected static final byte IGNORE = -1;
+
+    /**
+     * The state number of the starting state
+     */
+    private static final short START_STATE = 1;
+
+    /**
+     * The state-transition value indicating "stop"
+     */
+    private static final short STOP_STATE = 0;
+
+    /**
+     * Magic number for the BreakIterator data file format.
+     */
+    static final byte[] LABEL = {
+        (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
+        (byte)'\0'
+    };
+    static final int    LABEL_LENGTH = LABEL.length;
+
+    /**
+     * Version number of the dictionary that was read in.
+     */
+    static final byte supportedVersion = 1;
+
+    /**
+     * An array length of indices for BMP characters
+     */
+    private static final int BMP_INDICES_LENGTH = 512;
+
+    /**
+     * Tables that indexes from character values to character category numbers
+     */
+    private CompactByteArray charCategoryTable = null;
+    private SupplementaryCharacterData supplementaryCharCategoryTable = null;
+
+    /**
+     * The table of state transitions used for forward iteration
+     */
+    private short[] stateTable = null;
+
+    /**
+     * The table of state transitions used to sync up the iterator with the
+     * text in backwards and random-access iteration
+     */
+    private short[] backwardsStateTable = null;
+
+    /**
+     * A list of flags indicating which states in the state table are accepting
+     * ("end") states
+     */
+    private boolean[] endStates = null;
+
+    /**
+     * A list of flags indicating which states in the state table are
+     * lookahead states (states which turn lookahead on and off)
+     */
+    private boolean[] lookaheadStates = null;
+
+    /**
+     * A table for additional data. May be used by a subclass of
+     * RuleBasedBreakIterator.
+     */
+    private byte[] additionalData = null;
+
+    /**
+     * The number of character categories (and, thus, the number of columns in
+     * the state tables)
+     */
+    private int numCategories;
+
+    /**
+     * The character iterator through which this BreakIterator accesses the text
+     */
+    private CharacterIterator text = null;
+
+    /**
+     * A CRC32 value of all data in datafile
+     */
+    private long checksum;
+
+    //=======================================================================
+    // constructors
+    //=======================================================================
+
+    /**
+     * Constructs a RuleBasedBreakIterator using the given rule data.
+     *
+     * @throws MissingResourceException if the rule data is invalid or corrupted
+     */
+    public RuleBasedBreakIterator(String ruleFile, byte[] ruleData) {
+        ByteBuffer bb = ByteBuffer.wrap(ruleData);
+        try {
+            validateRuleData(ruleFile, bb);
+            setupTables(ruleFile, bb);
+        } catch (BufferUnderflowException bue) {
+            MissingResourceException e;
+            e = new MissingResourceException("Corrupted rule data file", ruleFile, "");
+            e.initCause(bue);
+            throw e;
+        }
+    }
+
+    /**
+     * Initializes the fields with the given rule data.
+     * The data format is as follows:
+     * <pre>
+     *   BreakIteratorData {
+     *       u1           magic[7];
+     *       u1           version;
+     *       u4           totalDataSize;
+     *       header_info  header;
+     *       body         value;
+     *   }
+     * </pre>
+     * <code>totalDataSize</code> is the summation of the size of
+     * <code>header_info</code> and <code>body</code> in byte count.
+     * <p>
+     * In <code>header</code>, each field except for checksum implies the
+     * length of each field. Since <code>BMPdataLength</code> is a fixed-length
+     *  data(512 entries), its length isn't included in <code>header</code>.
+     * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
+     * <pre>
+     *   header_info {
+     *       u4           stateTableLength;
+     *       u4           backwardsStateTableLength;
+     *       u4           endStatesLength;
+     *       u4           lookaheadStatesLength;
+     *       u4           BMPdataLength;
+     *       u4           nonBMPdataLength;
+     *       u4           additionalDataLength;
+     *       u8           checksum;
+     *   }
+     * </pre>
+     * <p>
+     *
+     * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
+     * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
+     * <code>supplementaryCharCategoryTable</code>.
+     * <pre>
+     *   body {
+     *       u2           stateTable[stateTableLength];
+     *       u2           backwardsStateTable[backwardsStateTableLength];
+     *       u1           endStates[endStatesLength];
+     *       u1           lookaheadStates[lookaheadStatesLength];
+     *       u2           BMPindices[512];
+     *       u1           BMPdata[BMPdataLength];
+     *       u4           nonBMPdata[numNonBMPdataLength];
+     *       u1           additionalData[additionalDataLength];
+     *   }
+     * </pre>
+     *
+     * @throws BufferUnderflowException if the end-of-data is reached before
+     *                                  setting up all the tables
+     */
+    private void setupTables(String ruleFile, ByteBuffer bb) {
+        /* Read header_info. */
+        int stateTableLength = bb.getInt();
+        int backwardsStateTableLength = bb.getInt();
+        int endStatesLength = bb.getInt();
+        int lookaheadStatesLength = bb.getInt();
+        int BMPdataLength = bb.getInt();
+        int nonBMPdataLength = bb.getInt();
+        int additionalDataLength = bb.getInt();
+        checksum = bb.getLong();
+
+        /* Read stateTable[numCategories * numRows] */
+        stateTable = new short[stateTableLength];
+        for (int i = 0; i < stateTableLength; i++) {
+            stateTable[i] = bb.getShort();
+        }
+
+        /* Read backwardsStateTable[numCategories * numRows] */
+        backwardsStateTable = new short[backwardsStateTableLength];
+        for (int i = 0; i < backwardsStateTableLength; i++) {
+            backwardsStateTable[i] = bb.getShort();
+        }
+
+        /* Read endStates[numRows] */
+        endStates = new boolean[endStatesLength];
+        for (int i = 0; i < endStatesLength; i++) {
+            endStates[i] = bb.get() == 1;
+        }
+
+        /* Read lookaheadStates[numRows] */
+        lookaheadStates = new boolean[lookaheadStatesLength];
+        for (int i = 0; i < lookaheadStatesLength; i++) {
+            lookaheadStates[i] = bb.get() == 1;
+        }
+
+        /* Read a category table and indices for BMP characters. */
+        short[] temp1 = new short[BMP_INDICES_LENGTH];  // BMPindices
+        for (int i = 0; i < BMP_INDICES_LENGTH; i++) {
+            temp1[i] = bb.getShort();
+        }
+        byte[] temp2 = new byte[BMPdataLength];  // BMPdata
+        bb.get(temp2);
+        charCategoryTable = new CompactByteArray(temp1, temp2);
+
+        /* Read a category table for non-BMP characters. */
+        int[] temp3 = new int[nonBMPdataLength];
+        for (int i = 0; i < nonBMPdataLength; i++) {
+            temp3[i] = bb.getInt();
+        }
+        supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
+
+        /* Read additional data */
+        if (additionalDataLength > 0) {
+            additionalData = new byte[additionalDataLength];
+            bb.get(additionalData);
+        }
+        assert bb.position() == bb.limit();
+
+        /* Set numCategories */
+        numCategories = stateTable.length / endStates.length;
+    }
+
+    /**
+     * Validates the magic number, version, and the length of the given data.
+     *
+     * @throws BufferUnderflowException if the end-of-data is reached while
+     *                                  validating data
+     * @throws MissingResourceException if valification failed
+     */
+    void validateRuleData(String ruleFile, ByteBuffer bb) {
+        /* Verify the magic number. */
+        for (int i = 0; i < LABEL_LENGTH; i++) {
+            if (bb.get() != LABEL[i]) {
+                throw new MissingResourceException("Wrong magic number",
+                                                   ruleFile, "");
+            }
+        }
+
+        /* Verify the version number. */
+        byte version = bb.get();
+        if (version != supportedVersion) {
+            throw new MissingResourceException("Unsupported version(" + version + ")",
+                                               ruleFile, "");
+        }
+
+        // Check the length of the rest of data
+        int len = bb.getInt();
+        if (bb.position() + len != bb.limit()) {
+            throw new MissingResourceException("Wrong data length",
+                                               ruleFile, "");
+        }
+    }
+
+    byte[] getAdditionalData() {
+        return additionalData;
+    }
+
+    void setAdditionalData(byte[] b) {
+        additionalData = b;
+    }
+
+    //=======================================================================
+    // boilerplate
+    //=======================================================================
+    /**
+     * Clones this iterator.
+     * @return A newly-constructed RuleBasedBreakIterator with the same
+     * behavior as this one.
+     */
+    @Override
+    public Object clone() {
+        RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
+        if (text != null) {
+            result.text = (CharacterIterator) text.clone();
+        }
+        return result;
+    }
+
+    /**
+     * Returns true if both BreakIterators are of the same class, have the same
+     * rules, and iterate over the same text.
+     */
+    @Override
+    public boolean equals(Object that) {
+        try {
+            if (that == null) {
+                return false;
+            }
+
+            RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
+            if (checksum != other.checksum) {
+                return false;
+            }
+            if (text == null) {
+                return other.text == null;
+            } else {
+                return text.equals(other.text);
+            }
+        }
+        catch(ClassCastException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns text
+     */
+    @Override
+    public String toString() {
+        return "[checksum=0x" + Long.toHexString(checksum) + ']';
+    }
+
+    /**
+     * Compute a hashcode for this BreakIterator
+     * @return A hash code
+     */
+    @Override
+    public int hashCode() {
+        return (int)checksum;
+    }
+
+    //=======================================================================
+    // BreakIterator overrides
+    //=======================================================================
+
+    /**
+     * Sets the current iteration position to the beginning of the text.
+     * (i.e., the CharacterIterator's starting offset).
+     * @return The offset of the beginning of the text.
+     */
+    @Override
+    public int first() {
+        CharacterIterator t = getText();
+
+        t.first();
+        return t.getIndex();
+    }
+
+    /**
+     * Sets the current iteration position to the end of the text.
+     * (i.e., the CharacterIterator's ending offset).
+     * @return The text's past-the-end offset.
+     */
+    @Override
+    public int last() {
+        CharacterIterator t = getText();
+
+        // I'm not sure why, but t.last() returns the offset of the last character,
+        // rather than the past-the-end offset
+        t.setIndex(t.getEndIndex());
+        return t.getIndex();
+    }
+
+    /**
+     * Advances the iterator either forward or backward the specified number of steps.
+     * Negative values move backward, and positive values move forward.  This is
+     * equivalent to repeatedly calling next() or previous().
+     * @param n The number of steps to move.  The sign indicates the direction
+     * (negative is backwards, and positive is forwards).
+     * @return The character offset of the boundary position n boundaries away from
+     * the current one.
+     */
+    @Override
+    public int next(int n) {
+        int result = current();
+        while (n > 0) {
+            result = handleNext();
+            --n;
+        }
+        while (n < 0) {
+            result = previous();
+            ++n;
+        }
+        return result;
+    }
+
+    /**
+     * Advances the iterator to the next boundary position.
+     * @return The position of the first boundary after this one.
+     */
+    @Override
+    public int next() {
+        return handleNext();
+    }
+
+    private int cachedLastKnownBreak = BreakIterator.DONE;
+
+    /**
+     * Advances the iterator backwards, to the last boundary preceding this one.
+     * @return The position of the last boundary position preceding this one.
+     */
+    @Override
+    public int previous() {
+        // if we're already sitting at the beginning of the text, return DONE
+        CharacterIterator text = getText();
+        if (current() == text.getBeginIndex()) {
+            return BreakIterator.DONE;
+        }
+
+        // set things up.  handlePrevious() will back us up to some valid
+        // break position before the current position (we back our internal
+        // iterator up one step to prevent handlePrevious() from returning
+        // the current position), but not necessarily the last one before
+        // where we started
+        int start = current();
+        int lastResult = cachedLastKnownBreak;
+        if (lastResult >= start || lastResult <= BreakIterator.DONE) {
+            getPrevious();
+            lastResult = handlePrevious();
+        } else {
+            //it might be better to check if handlePrevious() give us closer
+            //safe value but handlePrevious() is slow too
+            //So, this has to be done carefully
+            text.setIndex(lastResult);
+        }
+        int result = lastResult;
+
+        // iterate forward from the known break position until we pass our
+        // starting point.  The last break position before the starting
+        // point is our return value
+        while (result != BreakIterator.DONE && result < start) {
+            lastResult = result;
+            result = handleNext();
+        }
+
+        // set the current iteration position to be the last break position
+        // before where we started, and then return that value
+        text.setIndex(lastResult);
+        cachedLastKnownBreak = lastResult;
+        return lastResult;
+    }
+
+    /**
+     * Returns previous character
+     */
+    private int getPrevious() {
+        char c2 = text.previous();
+        if (Character.isLowSurrogate(c2) &&
+            text.getIndex() > text.getBeginIndex()) {
+            char c1 = text.previous();
+            if (Character.isHighSurrogate(c1)) {
+                return Character.toCodePoint(c1, c2);
+            } else {
+                text.next();
+            }
+        }
+        return (int)c2;
+    }
+
+    /**
+     * Returns current character
+     */
+    int getCurrent() {
+        char c1 = text.current();
+        if (Character.isHighSurrogate(c1) &&
+            text.getIndex() < text.getEndIndex()) {
+            char c2 = text.next();
+            text.previous();
+            if (Character.isLowSurrogate(c2)) {
+                return Character.toCodePoint(c1, c2);
+            }
+        }
+        return (int)c1;
+    }
+
+    /**
+     * Returns the count of next character.
+     */
+    private int getCurrentCodePointCount() {
+        char c1 = text.current();
+        if (Character.isHighSurrogate(c1) &&
+            text.getIndex() < text.getEndIndex()) {
+            char c2 = text.next();
+            text.previous();
+            if (Character.isLowSurrogate(c2)) {
+                return 2;
+            }
+        }
+        return 1;
+    }
+
+    /**
+     * Returns next character
+     */
+    int getNext() {
+        int index = text.getIndex();
+        int endIndex = text.getEndIndex();
+        if (index == endIndex ||
+            (index += getCurrentCodePointCount()) >= endIndex) {
+            return CharacterIterator.DONE;
+        }
+        text.setIndex(index);
+        return getCurrent();
+    }
+
+    /**
+     * Returns the position of next character.
+     */
+    private int getNextIndex() {
+        int index = text.getIndex() + getCurrentCodePointCount();
+        int endIndex = text.getEndIndex();
+        if (index > endIndex) {
+            return endIndex;
+        } else {
+            return index;
+        }
+    }
+
+    /**
+     * Throw IllegalArgumentException unless begin <= offset < end.
+     */
+    protected static final void checkOffset(int offset, CharacterIterator text) {
+        if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
+            throw new IllegalArgumentException("offset out of bounds");
+        }
+    }
+
+    /**
+     * Sets the iterator to refer to the first boundary position following
+     * the specified position.
+     * @offset The position from which to begin searching for a break position.
+     * @return The position of the first break after the current position.
+     */
+    @Override
+    public int following(int offset) {
+
+        CharacterIterator text = getText();
+        checkOffset(offset, text);
+
+        // Set our internal iteration position (temporarily)
+        // to the position passed in.  If this is the _beginning_ position,
+        // then we can just use next() to get our return value
+        text.setIndex(offset);
+        if (offset == text.getBeginIndex()) {
+            cachedLastKnownBreak = handleNext();
+            return cachedLastKnownBreak;
+        }
+
+        // otherwise, we have to sync up first.  Use handlePrevious() to back
+        // us up to a known break position before the specified position (if
+        // we can determine that the specified position is a break position,
+        // we don't back up at all).  This may or may not be the last break
+        // position at or before our starting position.  Advance forward
+        // from here until we've passed the starting position.  The position
+        // we stop on will be the first break position after the specified one.
+        int result = cachedLastKnownBreak;
+        if (result >= offset || result <= BreakIterator.DONE) {
+            result = handlePrevious();
+        } else {
+            //it might be better to check if handlePrevious() give us closer
+            //safe value but handlePrevious() is slow too
+            //So, this has to be done carefully
+            text.setIndex(result);
+        }
+        while (result != BreakIterator.DONE && result <= offset) {
+            result = handleNext();
+        }
+        cachedLastKnownBreak = result;
+        return result;
+    }
+
+    /**
+     * Sets the iterator to refer to the last boundary position before the
+     * specified position.
+     * @offset The position to begin searching for a break from.
+     * @return The position of the last boundary before the starting position.
+     */
+    @Override
+    public int preceding(int offset) {
+        // if we start by updating the current iteration position to the
+        // position specified by the caller, we can just use previous()
+        // to carry out this operation
+        CharacterIterator text = getText();
+        checkOffset(offset, text);
+        text.setIndex(offset);
+        return previous();
+    }
+
+    /**
+     * Returns true if the specified position is a boundary position.  As a side
+     * effect, leaves the iterator pointing to the first boundary position at
+     * or after "offset".
+     * @param offset the offset to check.
+     * @return True if "offset" is a boundary position.
+     */
+    @Override
+    public boolean isBoundary(int offset) {
+        CharacterIterator text = getText();
+        checkOffset(offset, text);
+        if (offset == text.getBeginIndex()) {
+            return true;
+        }
+
+        // to check whether this is a boundary, we can use following() on the
+        // position before the specified one and return true if the position we
+        // get back is the one the user specified
+        else {
+            return following(offset - 1) == offset;
+        }
+    }
+
+    /**
+     * Returns the current iteration position.
+     * @return The current iteration position.
+     */
+    @Override
+    public int current() {
+        return getText().getIndex();
+    }
+
+    /**
+     * Return a CharacterIterator over the text being analyzed.  This version
+     * of this method returns the actual CharacterIterator we're using internally.
+     * Changing the state of this iterator can have undefined consequences.  If
+     * you need to change it, clone it first.
+     * @return An iterator over the text being analyzed.
+     */
+    @Override
+    public CharacterIterator getText() {
+        // The iterator is initialized pointing to no text at all, so if this
+        // function is called while we're in that state, we have to fudge an
+        // iterator to return.
+        if (text == null) {
+            text = new StringCharacterIterator("");
+        }
+        return text;
+    }
+
+    /**
+     * Set the iterator to analyze a new piece of text.  This function resets
+     * the current iteration position to the beginning of the text.
+     * @param newText An iterator over the text to analyze.
+     */
+    @Override
+    public void setText(CharacterIterator newText) {
+        // Test iterator to see if we need to wrap it in a SafeCharIterator.
+        // The correct behavior for CharacterIterators is to allow the
+        // position to be set to the endpoint of the iterator.  Many
+        // CharacterIterators do not uphold this, so this is a workaround
+        // to permit them to use this class.
+        int end = newText.getEndIndex();
+        boolean goodIterator;
+        try {
+            newText.setIndex(end);  // some buggy iterators throw an exception here
+            goodIterator = newText.getIndex() == end;
+        }
+        catch(IllegalArgumentException e) {
+            goodIterator = false;
+        }
+
+        if (goodIterator) {
+            text = newText;
+        }
+        else {
+            text = new SafeCharIterator(newText);
+        }
+        text.first();
+
+        cachedLastKnownBreak = BreakIterator.DONE;
+    }
+
+
+    //=======================================================================
+    // implementation
+    //=======================================================================
+
+    /**
+     * This method is the actual implementation of the next() method.  All iteration
+     * vectors through here.  This method initializes the state machine to state 1
+     * and advances through the text character by character until we reach the end
+     * of the text or the state machine transitions to state 0.  We update our return
+     * value every time the state machine passes through a possible end state.
+     */
+    protected int handleNext() {
+        // if we're already at the end of the text, return DONE.
+        CharacterIterator text = getText();
+        if (text.getIndex() == text.getEndIndex()) {
+            return BreakIterator.DONE;
+        }
+
+        // no matter what, we always advance at least one character forward
+        int result = getNextIndex();
+        int lookaheadResult = 0;
+
+        // begin in state 1
+        int state = START_STATE;
+        int category;
+        int c = getCurrent();
+
+        // loop until we reach the end of the text or transition to state 0
+        while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+            // look up the current character's character category (which tells us
+            // which column in the state table to look at)
+            category = lookupCategory(c);
+
+            // if the character isn't an ignore character, look up a state
+            // transition in the state table
+            if (category != IGNORE) {
+                state = lookupState(state, category);
+            }
+
+            // if the state we've just transitioned to is a lookahead state,
+            // (but not also an end state), save its position.  If it's
+            // both a lookahead state and an end state, update the break position
+            // to the last saved lookup-state position
+            if (lookaheadStates[state]) {
+                if (endStates[state]) {
+                    result = lookaheadResult;
+                }
+                else {
+                    lookaheadResult = getNextIndex();
+                }
+            }
+
+            // otherwise, if the state we've just transitioned to is an accepting
+            // state, update the break position to be the current iteration position
+            else {
+                if (endStates[state]) {
+                    result = getNextIndex();
+                }
+            }
+
+            c = getNext();
+        }
+
+        // if we've run off the end of the text, and the very last character took us into
+        // a lookahead state, advance the break position to the lookahead position
+        // (the theory here is that if there are no characters at all after the lookahead
+        // position, that always matches the lookahead criteria)
+        if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
+            result = lookaheadResult;
+        }
+
+        text.setIndex(result);
+        return result;
+    }
+
+    /**
+     * This method backs the iterator back up to a "safe position" in the text.
+     * This is a position that we know, without any context, must be a break position.
+     * The various calling methods then iterate forward from this safe position to
+     * the appropriate position to return.  (For more information, see the description
+     * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
+     */
+    protected int handlePrevious() {
+        CharacterIterator text = getText();
+        int state = START_STATE;
+        int category = 0;
+        int lastCategory = 0;
+        int c = getCurrent();
+
+        // loop until we reach the beginning of the text or transition to state 0
+        while (c != CharacterIterator.DONE && state != STOP_STATE) {
+
+            // save the last character's category and look up the current
+            // character's category
+            lastCategory = category;
+            category = lookupCategory(c);
+
+            // if the current character isn't an ignore character, look up a
+            // state transition in the backwards state table
+            if (category != IGNORE) {
+                state = lookupBackwardState(state, category);
+            }
+
+            // then advance one character backwards
+            c = getPrevious();
+        }
+
+        // if we didn't march off the beginning of the text, we're either one or two
+        // positions away from the real break position.  (One because of the call to
+        // previous() at the end of the loop above, and another because the character
+        // that takes us into the stop state will always be the character BEFORE
+        // the break position.)
+        if (c != CharacterIterator.DONE) {
+            if (lastCategory != IGNORE) {
+                getNext();
+                getNext();
+            }
+            else {
+                getNext();
+            }
+        }
+        return text.getIndex();
+    }
+
+    /**
+     * Looks up a character's category (i.e., its category for breaking purposes,
+     * not its Unicode category)
+     */
+    protected int lookupCategory(int c) {
+        if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+            return charCategoryTable.elementAt((char)c);
+        } else {
+            return supplementaryCharCategoryTable.getValue(c);
+        }
+    }
+
+    /**
+     * Given a current state and a character category, looks up the
+     * next state to transition to in the state table.
+     */
+    protected int lookupState(int state, int category) {
+        return stateTable[state * numCategories + category];
+    }
+
+    /**
+     * Given a current state and a character category, looks up the
+     * next state to transition to in the backwards state table.
+     */
+    protected int lookupBackwardState(int state, int category) {
+        return backwardsStateTable[state * numCategories + category];
+    }
+
+    /*
+     * This class exists to work around a bug in incorrect implementations
+     * of CharacterIterator, which incorrectly handle setIndex(endIndex).
+     * This iterator relies only on base.setIndex(n) where n is less than
+     * endIndex.
+     *
+     * One caveat:  if the base iterator's begin and end indices change
+     * the change will not be reflected by this wrapper.  Does that matter?
+     */
+    // TODO: Review this class to see if it's still required.
+    private static final class SafeCharIterator implements CharacterIterator,
+                                                           Cloneable {
+
+        private CharacterIterator base;
+        private int rangeStart;
+        private int rangeLimit;
+        private int currentIndex;
+
+        SafeCharIterator(CharacterIterator base) {
+            this.base = base;
+            this.rangeStart = base.getBeginIndex();
+            this.rangeLimit = base.getEndIndex();
+            this.currentIndex = base.getIndex();
+        }
+
+        @Override
+        public char first() {
+            return setIndex(rangeStart);
+        }
+
+        @Override
+        public char last() {
+            return setIndex(rangeLimit - 1);
+        }
+
+        @Override
+        public char current() {
+            if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
+                return DONE;
+            }
+            else {
+                return base.setIndex(currentIndex);
+            }
+        }
+
+        @Override
+        public char next() {
+
+            currentIndex++;
+            if (currentIndex >= rangeLimit) {
+                currentIndex = rangeLimit;
+                return DONE;
+            }
+            else {
+                return base.setIndex(currentIndex);
+            }
+        }
+
+        @Override
+        public char previous() {
+
+            currentIndex--;
+            if (currentIndex < rangeStart) {
+                currentIndex = rangeStart;
+                return DONE;
+            }
+            else {
+                return base.setIndex(currentIndex);
+            }
+        }
+
+        @Override
+        public char setIndex(int i) {
+
+            if (i < rangeStart || i > rangeLimit) {
+                throw new IllegalArgumentException("Invalid position");
+            }
+            currentIndex = i;
+            return current();
+        }
+
+        @Override
+        public int getBeginIndex() {
+            return rangeStart;
+        }
+
+        @Override
+        public int getEndIndex() {
+            return rangeLimit;
+        }
+
+        @Override
+        public int getIndex() {
+            return currentIndex;
+        }
+
+        @Override
+        public Object clone() {
+
+            SafeCharIterator copy = null;
+            try {
+                copy = (SafeCharIterator) super.clone();
+            }
+            catch(CloneNotSupportedException e) {
+                throw new Error("Clone not supported: " + e);
+            }
+
+            CharacterIterator copyOfBase = (CharacterIterator) base.clone();
+            copy.base = copyOfBase;
+            return copy;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/text/resources/BreakIteratorResources.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources extends BreakIteratorResourceBundle {
+    @Override
+    protected ResourceBundle getBreakIteratorInfo() {
+        return new BreakIteratorInfo();
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakDictionary.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,352 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 - 2002 - 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.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;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * This is the class that represents the list of known words used by
- * DictionaryBasedBreakIterator.  The conceptual data structure used
- * here is a trie: there is a node hanging off the root node for every
- * letter that can start a word.  Each of these nodes has a node hanging
- * off of it for every letter that can be the second letter of a word
- * if this node is the first letter, and so on.  The trie is represented
- * as a two-dimensional array that can be treated as a table of state
- * transitions.  Indexes are used to compress this array, taking
- * advantage of the fact that this array will always be very sparse.
- */
-class BreakDictionary {
-
-    //=========================================================================
-    // data members
-    //=========================================================================
-
-    /**
-      * The version of the dictionary that was read in.
-      */
-    private static int supportedVersion = 1;
-
-    /**
-     * Maps from characters to column numbers.  The main use of this is to
-     * avoid making room in the array for empty columns.
-     */
-    private CompactByteArray columnMap = null;
-    private SupplementaryCharacterData supplementaryCharColumnMap = null;
-
-    /**
-     * The number of actual columns in the table
-     */
-    private int numCols;
-
-    /**
-     * Columns are organized into groups of 32.  This says how many
-     * column groups.  (We could calculate this, but we store the
-     * value to avoid having to repeatedly calculate it.)
-     */
-    private int numColGroups;
-
-    /**
-     * The actual compressed state table.  Each conceptual row represents
-     * a state, and the cells in it contain the row numbers of the states
-     * to transition to for each possible letter.  0 is used to indicate
-     * an illegal combination of letters (i.e., the error state).  The
-     * table is compressed by eliminating all the unpopulated (i.e., zero)
-     * cells.  Multiple conceptual rows can then be doubled up in a single
-     * physical row by sliding them up and possibly shifting them to one
-     * side or the other so the populated cells don't collide.  Indexes
-     * are used to identify unpopulated cells and to locate populated cells.
-     */
-    private short[] table = null;
-
-    /**
-     * This index maps logical row numbers to physical row numbers
-     */
-    private short[] rowIndex = null;
-
-    /**
-     * A bitmap is used to tell which cells in the comceptual table are
-     * populated.  This array contains all the unique bit combinations
-     * in that bitmap.  If the table is more than 32 columns wide,
-     * successive entries in this array are used for a single row.
-     */
-    private int[] rowIndexFlags = null;
-
-    /**
-     * This index maps from a logical row number into the bitmap table above.
-     * (This keeps us from storing duplicate bitmap combinations.)  Since there
-     * are a lot of rows with only one populated cell, instead of wasting space
-     * in the bitmap table, we just store a negative number in this index for
-     * rows with one populated cell.  The absolute value of that number is
-     * the column number of the populated cell.
-     */
-    private short[] rowIndexFlagsIndex = null;
-
-    /**
-     * For each logical row, this index contains a constant that is added to
-     * the logical column number to get the physical column number
-     */
-    private byte[] rowIndexShifts = null;
-
-    //=========================================================================
-    // deserialization
-    //=========================================================================
-
-    BreakDictionary(Module module, String dictionaryName)
-        throws IOException, MissingResourceException {
-
-        readDictionaryFile(module, dictionaryName);
-    }
-
-    private void readDictionaryFile(final Module module, final String dictionaryName)
-        throws IOException, MissingResourceException {
-
-        BufferedInputStream in;
-        try {
-            PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
-                String pathName = "jdk.localedata".equals(module.getName()) ?
-                     "sun/text/resources/ext/" :
-                     "sun/text/resources/";
-                InputStream is = module.getResourceAsStream(pathName + 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);
-        }
-
-        byte[] buf = new byte[8];
-        if (in.read(buf) != 8) {
-            throw new MissingResourceException("Wrong data length",
-                                               dictionaryName, "");
-        }
-
-        // check version
-        int version = RuleBasedBreakIterator.getInt(buf, 0);
-        if (version != supportedVersion) {
-            throw new MissingResourceException("Dictionary version(" + version + ") is unsupported",
-                                                           dictionaryName, "");
-        }
-
-        // get data size
-        int len = RuleBasedBreakIterator.getInt(buf, 4);
-        buf = new byte[len];
-        if (in.read(buf) != len) {
-            throw new MissingResourceException("Wrong data length",
-                                               dictionaryName, "");
-        }
-
-        // close the stream
-        in.close();
-
-        int l;
-        int offset = 0;
-
-        // read in the column map for BMP characteres (this is serialized in
-        // its internal form: an index array followed by a data array)
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        short[] temp = new short[l];
-        for (int i = 0; i < l; i++, offset+=2) {
-            temp[i] = RuleBasedBreakIterator.getShort(buf, offset);
-        }
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        byte[] temp2 = new byte[l];
-        for (int i = 0; i < l; i++, offset++) {
-            temp2[i] = buf[offset];
-        }
-        columnMap = new CompactByteArray(temp, temp2);
-
-        // read in numCols and numColGroups
-        numCols = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        numColGroups = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-
-        // read in the row-number index
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        rowIndex = new short[l];
-        for (int i = 0; i < l; i++, offset+=2) {
-            rowIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
-        }
-
-        // load in the populated-cells bitmap: index first, then bitmap list
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        rowIndexFlagsIndex = new short[l];
-        for (int i = 0; i < l; i++, offset+=2) {
-            rowIndexFlagsIndex[i] = RuleBasedBreakIterator.getShort(buf, offset);
-        }
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        rowIndexFlags = new int[l];
-        for (int i = 0; i < l; i++, offset+=4) {
-            rowIndexFlags[i] = RuleBasedBreakIterator.getInt(buf, offset);
-        }
-
-        // load in the row-shift index
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        rowIndexShifts = new byte[l];
-        for (int i = 0; i < l; i++, offset++) {
-            rowIndexShifts[i] = buf[offset];
-        }
-
-        // load in the actual state table
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        table = new short[l];
-        for (int i = 0; i < l; i++, offset+=2) {
-            table[i] = RuleBasedBreakIterator.getShort(buf, offset);
-        }
-
-        // finally, prepare the column map for supplementary characters
-        l = RuleBasedBreakIterator.getInt(buf, offset);
-        offset += 4;
-        int[] temp3 = new int[l];
-        for (int i = 0; i < l; i++, offset+=4) {
-            temp3[i] = RuleBasedBreakIterator.getInt(buf, offset);
-        }
-        supplementaryCharColumnMap = new SupplementaryCharacterData(temp3);
-    }
-
-    //=========================================================================
-    // access to the words
-    //=========================================================================
-
-    /**
-     * Uses the column map to map the character to a column number, then
-     * passes the row and column number to getNextState()
-     * @param row The current state
-     * @param ch The character whose column we're interested in
-     * @return The new state to transition to
-     */
-    public final short getNextStateFromCharacter(int row, int ch) {
-        int col;
-        if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            col = columnMap.elementAt((char)ch);
-        } else {
-            col = supplementaryCharColumnMap.getValue(ch);
-        }
-        return getNextState(row, col);
-    }
-
-    /**
-     * Returns the value in the cell with the specified (logical) row and
-     * column numbers.  In DictionaryBasedBreakIterator, the row number is
-     * a state number, the column number is an input, and the return value
-     * is the row number of the new state to transition to.  (0 is the
-     * "error" state, and -1 is the "end of word" state in a dictionary)
-     * @param row The row number of the current state
-     * @param col The column number of the input character (0 means "not a
-     * dictionary character")
-     * @return The row number of the new state to transition to
-     */
-    public final short getNextState(int row, int col) {
-        if (cellIsPopulated(row, col)) {
-            // we map from logical to physical row number by looking up the
-            // mapping in rowIndex; we map from logical column number to
-            // physical column number by looking up a shift value for this
-            // logical row and offsetting the logical column number by
-            // the shift amount.  Then we can use internalAt() to actually
-            // get the value out of the table.
-            return internalAt(rowIndex[row], col + rowIndexShifts[row]);
-        }
-        else {
-            return 0;
-        }
-    }
-
-    /**
-     * Given (logical) row and column numbers, returns true if the
-     * cell in that position is populated
-     */
-    private boolean cellIsPopulated(int row, int col) {
-        // look up the entry in the bitmap index for the specified row.
-        // If it's a negative number, it's the column number of the only
-        // populated cell in the row
-        if (rowIndexFlagsIndex[row] < 0) {
-            return col == -rowIndexFlagsIndex[row];
-        }
-
-        // if it's a positive number, it's the offset of an entry in the bitmap
-        // list.  If the table is more than 32 columns wide, the bitmap is stored
-        // successive entries in the bitmap list, so we have to divide the column
-        // number by 32 and offset the number we got out of the index by the result.
-        // Once we have the appropriate piece of the bitmap, test the appropriate
-        // bit and return the result.
-        else {
-            int flags = rowIndexFlags[rowIndexFlagsIndex[row] + (col >> 5)];
-            return (flags & (1 << (col & 0x1f))) != 0;
-        }
-    }
-
-    /**
-     * Implementation of getNextState() when we know the specified cell is
-     * populated.
-     * @param row The PHYSICAL row number of the cell
-     * @param col The PHYSICAL column number of the cell
-     * @return The value stored in the cell
-     */
-    private short internalAt(int row, int col) {
-        // the table is a one-dimensional array, so this just does the math necessary
-        // to treat it as a two-dimensional array (we don't just use a two-dimensional
-        // array because two-dimensional arrays are inefficient in Java)
-        return table[row * numCols + col];
-    }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/BreakIteratorProviderImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -32,6 +32,8 @@
 import java.util.MissingResourceException;
 import java.util.Objects;
 import java.util.Set;
+import sun.text.DictionaryBasedBreakIterator;
+import sun.text.RuleBasedBreakIterator;
 
 /**
  * Concrete implementation of the  {@link java.text.spi.BreakIteratorProvider
@@ -153,29 +155,31 @@
     }
 
     private BreakIterator getBreakInstance(Locale locale,
-                                                  int type,
-                                                  String dataName,
-                                                  String dictionaryName) {
+                                           int type,
+                                           String ruleName,
+                                           String dictionaryName) {
         Objects.requireNonNull(locale);
 
         LocaleResources lr = LocaleProviderAdapter.forJRE().getLocaleResources(locale);
         String[] classNames = (String[]) lr.getBreakIteratorInfo("BreakIteratorClasses");
-        String dataFile = (String) lr.getBreakIteratorInfo(dataName);
+        String ruleFile = (String) lr.getBreakIteratorInfo(ruleName);
+        byte[] ruleData = lr.getBreakIteratorResources(ruleName);
 
         try {
             switch (classNames[type]) {
             case "RuleBasedBreakIterator":
-                return new RuleBasedBreakIterator(
-                    lr.getBreakIteratorDataModule(), dataFile);
+                return new RuleBasedBreakIterator(ruleFile, ruleData);
+
             case "DictionaryBasedBreakIterator":
                 String dictionaryFile = (String) lr.getBreakIteratorInfo(dictionaryName);
-                return new DictionaryBasedBreakIterator(
-                    lr.getBreakIteratorDataModule(), dataFile, dictionaryFile);
+                byte[] dictionaryData = lr.getBreakIteratorResources(dictionaryName);
+                return new DictionaryBasedBreakIterator(ruleFile, ruleData,
+                                                        dictionaryFile, dictionaryData);
             default:
                 throw new IllegalArgumentException("Invalid break iterator class \"" +
                                 classNames[type] + "\"");
             }
-        } catch (IOException | MissingResourceException | IllegalArgumentException e) {
+        } catch (MissingResourceException | IllegalArgumentException e) {
             throw new InternalError(e.toString(), e);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/DictionaryBasedBreakIterator.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,524 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 - 2002 - 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.locale.provider;
-
-import java.io.IOException;
-import java.lang.reflect.Module;
-import java.text.CharacterIterator;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-
-/**
- * A subclass of RuleBasedBreakIterator that adds the ability to use a dictionary
- * to further subdivide ranges of text beyond what is possible using just the
- * state-table-based algorithm.  This is necessary, for example, to handle
- * word and line breaking in Thai, which doesn't use spaces between words.  The
- * state-table-based algorithm used by RuleBasedBreakIterator is used to divide
- * up text as far as possible, and then contiguous ranges of letters are
- * repeatedly compared against a list of known words (i.e., the dictionary)
- * to divide them up into words.
- *
- * DictionaryBasedBreakIterator uses the same rule language as RuleBasedBreakIterator,
- * but adds one more special substitution name: &lt;dictionary&gt;.  This substitution
- * name is used to identify characters in words in the dictionary.  The idea is that
- * if the iterator passes over a chunk of text that includes two or more characters
- * in a row that are included in &lt;dictionary&gt;, it goes back through that range and
- * derives additional break positions (if possible) using the dictionary.
- *
- * DictionaryBasedBreakIterator is also constructed with the filename of a dictionary
- * file.  It follows a prescribed search path to locate the dictionary (right now,
- * it looks for it in /com/ibm/text/resources in each directory in the classpath,
- * and won't find it in JAR files, but this location is likely to change).  The
- * dictionary file is in a serialized binary format.  We have a very primitive (and
- * slow) BuildDictionaryFile utility for creating dictionary files, but aren't
- * currently making it public.  Contact us for help.
- */
-class DictionaryBasedBreakIterator extends RuleBasedBreakIterator {
-
-    /**
-     * a list of known words that is used to divide up contiguous ranges of letters,
-     * stored in a compressed, indexed, format that offers fast access
-     */
-    private BreakDictionary dictionary;
-
-    /**
-     * a list of flags indicating which character categories are contained in
-     * the dictionary file (this is used to determine which ranges of characters
-     * to apply the dictionary to)
-     */
-    private boolean[] categoryFlags;
-
-    /**
-     * a temporary hiding place for the number of dictionary characters in the
-     * last range passed over by next()
-     */
-    private int dictionaryCharCount;
-
-    /**
-     * when a range of characters is divided up using the dictionary, the break
-     * positions that are discovered are stored here, preventing us from having
-     * to use either the dictionary or the state table again until the iterator
-     * leaves this range of text
-     */
-    private int[] cachedBreakPositions;
-
-    /**
-     * if cachedBreakPositions is not null, this indicates which item in the
-     * cache the current iteration position refers to
-     */
-    private int positionInCache;
-
-    /**
-     * Constructs a DictionaryBasedBreakIterator.
-     * @param module The module where the dictionary file resides
-     * @param dictionaryFilename The filename of the dictionary file to use
-     */
-    DictionaryBasedBreakIterator(Module module, String dataFile, String dictionaryFile)
-                                        throws IOException {
-        super(module, dataFile);
-        byte[] tmp = super.getAdditionalData();
-        if (tmp != null) {
-            prepareCategoryFlags(tmp);
-            super.setAdditionalData(null);
-        }
-        dictionary = new BreakDictionary(module, dictionaryFile);
-    }
-
-    private void prepareCategoryFlags(byte[] data) {
-        categoryFlags = new boolean[data.length];
-        for (int i = 0; i < data.length; i++) {
-            categoryFlags[i] = (data[i] == (byte)1) ? true : false;
-        }
-    }
-
-    @Override
-    public void setText(CharacterIterator newText) {
-        super.setText(newText);
-        cachedBreakPositions = null;
-        dictionaryCharCount = 0;
-        positionInCache = 0;
-    }
-
-    /**
-     * Sets the current iteration position to the beginning of the text.
-     * (i.e., the CharacterIterator's starting offset).
-     * @return The offset of the beginning of the text.
-     */
-    @Override
-    public int first() {
-        cachedBreakPositions = null;
-        dictionaryCharCount = 0;
-        positionInCache = 0;
-        return super.first();
-    }
-
-    /**
-     * Sets the current iteration position to the end of the text.
-     * (i.e., the CharacterIterator's ending offset).
-     * @return The text's past-the-end offset.
-     */
-    @Override
-    public int last() {
-        cachedBreakPositions = null;
-        dictionaryCharCount = 0;
-        positionInCache = 0;
-        return super.last();
-    }
-
-    /**
-     * Advances the iterator one step backwards.
-     * @return The position of the last boundary position before the
-     * current iteration position
-     */
-    @Override
-    public int previous() {
-        CharacterIterator text = getText();
-
-        // if we have cached break positions and we're still in the range
-        // covered by them, just move one step backward in the cache
-        if (cachedBreakPositions != null && positionInCache > 0) {
-            --positionInCache;
-            text.setIndex(cachedBreakPositions[positionInCache]);
-            return cachedBreakPositions[positionInCache];
-        }
-
-        // otherwise, dump the cache and use the inherited previous() method to move
-        // backward.  This may fill up the cache with new break positions, in which
-        // case we have to mark our position in the cache
-        else {
-            cachedBreakPositions = null;
-            int result = super.previous();
-            if (cachedBreakPositions != null) {
-                positionInCache = cachedBreakPositions.length - 2;
-            }
-            return result;
-        }
-    }
-
-    /**
-     * Sets the current iteration position to the last boundary position
-     * before the specified position.
-     * @param offset The position to begin searching from
-     * @return The position of the last boundary before "offset"
-     */
-    @Override
-    public int preceding(int offset) {
-        CharacterIterator text = getText();
-        checkOffset(offset, text);
-
-        // if we have no cached break positions, or "offset" is outside the
-        // range covered by the cache, we can just call the inherited routine
-        // (which will eventually call other routines in this class that may
-        // refresh the cache)
-        if (cachedBreakPositions == null || offset <= cachedBreakPositions[0] ||
-                offset > cachedBreakPositions[cachedBreakPositions.length - 1]) {
-            cachedBreakPositions = null;
-            return super.preceding(offset);
-        }
-
-        // on the other hand, if "offset" is within the range covered by the cache,
-        // then all we have to do is search the cache for the last break position
-        // before "offset"
-        else {
-            positionInCache = 0;
-            while (positionInCache < cachedBreakPositions.length
-                   && offset > cachedBreakPositions[positionInCache]) {
-                ++positionInCache;
-            }
-            --positionInCache;
-            text.setIndex(cachedBreakPositions[positionInCache]);
-            return text.getIndex();
-        }
-    }
-
-    /**
-     * Sets the current iteration position to the first boundary position after
-     * the specified position.
-     * @param offset The position to begin searching forward from
-     * @return The position of the first boundary after "offset"
-     */
-    @Override
-    public int following(int offset) {
-        CharacterIterator text = getText();
-        checkOffset(offset, text);
-
-        // if we have no cached break positions, or if "offset" is outside the
-        // range covered by the cache, then dump the cache and call our
-        // inherited following() method.  This will call other methods in this
-        // class that may refresh the cache.
-        if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
-                offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
-            cachedBreakPositions = null;
-            return super.following(offset);
-        }
-
-        // on the other hand, if "offset" is within the range covered by the
-        // cache, then just search the cache for the first break position
-        // after "offset"
-        else {
-            positionInCache = 0;
-            while (positionInCache < cachedBreakPositions.length
-                   && offset >= cachedBreakPositions[positionInCache]) {
-                ++positionInCache;
-            }
-            text.setIndex(cachedBreakPositions[positionInCache]);
-            return text.getIndex();
-        }
-    }
-
-    /**
-     * This is the implementation function for next().
-     */
-    @Override
-    protected int handleNext() {
-        CharacterIterator text = getText();
-
-        // if there are no cached break positions, or if we've just moved
-        // off the end of the range covered by the cache, we have to dump
-        // and possibly regenerate the cache
-        if (cachedBreakPositions == null ||
-            positionInCache == cachedBreakPositions.length - 1) {
-
-            // start by using the inherited handleNext() to find a tentative return
-            // value.   dictionaryCharCount tells us how many dictionary characters
-            // we passed over on our way to the tentative return value
-            int startPos = text.getIndex();
-            dictionaryCharCount = 0;
-            int result = super.handleNext();
-
-            // if we passed over more than one dictionary character, then we use
-            // divideUpDictionaryRange() to regenerate the cached break positions
-            // for the new range
-            if (dictionaryCharCount > 1 && result - startPos > 1) {
-                divideUpDictionaryRange(startPos, result);
-            }
-
-            // otherwise, the value we got back from the inherited fuction
-            // is our return value, and we can dump the cache
-            else {
-                cachedBreakPositions = null;
-                return result;
-            }
-        }
-
-        // if the cache of break positions has been regenerated (or existed all
-        // along), then just advance to the next break position in the cache
-        // and return it
-        if (cachedBreakPositions != null) {
-            ++positionInCache;
-            text.setIndex(cachedBreakPositions[positionInCache]);
-            return cachedBreakPositions[positionInCache];
-        }
-        return -9999;   // SHOULD NEVER GET HERE!
-    }
-
-    /**
-     * Looks up a character category for a character.
-     */
-    @Override
-    protected int lookupCategory(int c) {
-        // this override of lookupCategory() exists only to keep track of whether we've
-        // passed over any dictionary characters.  It calls the inherited lookupCategory()
-        // to do the real work, and then checks whether its return value is one of the
-        // categories represented in the dictionary.  If it is, bump the dictionary-
-        // character count.
-        int result = super.lookupCategory(c);
-        if (result != RuleBasedBreakIterator.IGNORE && categoryFlags[result]) {
-            ++dictionaryCharCount;
-        }
-        return result;
-    }
-
-    /**
-     * This is the function that actually implements the dictionary-based
-     * algorithm.  Given the endpoints of a range of text, it uses the
-     * dictionary to determine the positions of any boundaries in this
-     * range.  It stores all the boundary positions it discovers in
-     * cachedBreakPositions so that we only have to do this work once
-     * for each time we enter the range.
-     */
-    @SuppressWarnings("unchecked")
-    private void divideUpDictionaryRange(int startPos, int endPos) {
-        CharacterIterator text = getText();
-
-        // the range we're dividing may begin or end with non-dictionary characters
-        // (i.e., for line breaking, we may have leading or trailing punctuation
-        // that needs to be kept with the word).  Seek from the beginning of the
-        // range to the first dictionary character
-        text.setIndex(startPos);
-        int c = getCurrent();
-        int category = lookupCategory(c);
-        while (category == IGNORE || !categoryFlags[category]) {
-            c = getNext();
-            category = lookupCategory(c);
-        }
-
-        // initialize.  We maintain two stacks: currentBreakPositions contains
-        // the list of break positions that will be returned if we successfully
-        // finish traversing the whole range now.  possibleBreakPositions lists
-        // all other possible word ends we've passed along the way.  (Whenever
-        // we reach an error [a sequence of characters that can't begin any word
-        // in the dictionary], we back up, possibly delete some breaks from
-        // currentBreakPositions, move a break from possibleBreakPositions
-        // to currentBreakPositions, and start over from there.  This process
-        // continues in this way until we either successfully make it all the way
-        // across the range, or exhaust all of our combinations of break
-        // positions.)
-        Stack<Integer> currentBreakPositions = new Stack<>();
-        Stack<Integer> possibleBreakPositions = new Stack<>();
-        List<Integer> wrongBreakPositions = new ArrayList<>();
-
-        // the dictionary is implemented as a trie, which is treated as a state
-        // machine.  -1 represents the end of a legal word.  Every word in the
-        // dictionary is represented by a path from the root node to -1.  A path
-        // that ends in state 0 is an illegal combination of characters.
-        int state = 0;
-
-        // these two variables are used for error handling.  We keep track of the
-        // farthest we've gotten through the range being divided, and the combination
-        // of breaks that got us that far.  If we use up all possible break
-        // combinations, the text contains an error or a word that's not in the
-        // dictionary.  In this case, we "bless" the break positions that got us the
-        // farthest as real break positions, and then start over from scratch with
-        // the character where the error occurred.
-        int farthestEndPoint = text.getIndex();
-        Stack<Integer> bestBreakPositions = null;
-
-        // initialize (we always exit the loop with a break statement)
-        c = getCurrent();
-        while (true) {
-
-            // if we can transition to state "-1" from our current state, we're
-            // on the last character of a legal word.  Push that position onto
-            // the possible-break-positions stack
-            if (dictionary.getNextState(state, 0) == -1) {
-                possibleBreakPositions.push(text.getIndex());
-            }
-
-            // look up the new state to transition to in the dictionary
-            state = dictionary.getNextStateFromCharacter(state, c);
-
-            // if the character we're sitting on causes us to transition to
-            // the "end of word" state, then it was a non-dictionary character
-            // and we've successfully traversed the whole range.  Drop out
-            // of the loop.
-            if (state == -1) {
-                currentBreakPositions.push(text.getIndex());
-                break;
-            }
-
-            // if the character we're sitting on causes us to transition to
-            // the error state, or if we've gone off the end of the range
-            // without transitioning to the "end of word" state, we've hit
-            // an error...
-            else if (state == 0 || text.getIndex() >= endPos) {
-
-                // if this is the farthest we've gotten, take note of it in
-                // case there's an error in the text
-                if (text.getIndex() > farthestEndPoint) {
-                    farthestEndPoint = text.getIndex();
-
-                    @SuppressWarnings("unchecked")
-                    Stack<Integer> currentBreakPositionsCopy = (Stack<Integer>) currentBreakPositions.clone();
-
-                    bestBreakPositions = currentBreakPositionsCopy;
-                }
-
-                // wrongBreakPositions is a list of all break positions
-                // we've tried starting that didn't allow us to traverse
-                // all the way through the text.  Every time we pop a
-                // break position off of currentBreakPositions, we put it
-                // into wrongBreakPositions to avoid trying it again later.
-                // If we make it to this spot, we're either going to back
-                // up to a break in possibleBreakPositions and try starting
-                // over from there, or we've exhausted all possible break
-                // positions and are going to do the fallback procedure.
-                // This loop prevents us from messing with anything in
-                // possibleBreakPositions that didn't work as a starting
-                // point the last time we tried it (this is to prevent a bunch of
-                // repetitive checks from slowing down some extreme cases)
-                while (!possibleBreakPositions.isEmpty()
-                        && wrongBreakPositions.contains(possibleBreakPositions.peek())) {
-                    possibleBreakPositions.pop();
-                }
-
-                // if we've used up all possible break-position combinations, there's
-                // an error or an unknown word in the text.  In this case, we start
-                // over, treating the farthest character we've reached as the beginning
-                // of the range, and "blessing" the break positions that got us that
-                // far as real break positions
-                if (possibleBreakPositions.isEmpty()) {
-                    if (bestBreakPositions != null) {
-                        currentBreakPositions = bestBreakPositions;
-                        if (farthestEndPoint < endPos) {
-                            text.setIndex(farthestEndPoint + 1);
-                        }
-                        else {
-                            break;
-                        }
-                    }
-                    else {
-                        if ((currentBreakPositions.size() == 0 ||
-                             currentBreakPositions.peek().intValue() != text.getIndex())
-                            && text.getIndex() != startPos) {
-                            currentBreakPositions.push(text.getIndex());
-                        }
-                        getNext();
-                        currentBreakPositions.push(text.getIndex());
-                    }
-                }
-
-                // if we still have more break positions we can try, then promote the
-                // last break in possibleBreakPositions into currentBreakPositions,
-                // and get rid of all entries in currentBreakPositions that come after
-                // it.  Then back up to that position and start over from there (i.e.,
-                // treat that position as the beginning of a new word)
-                else {
-                    Integer temp = possibleBreakPositions.pop();
-                    Integer temp2 = null;
-                    while (!currentBreakPositions.isEmpty() && temp.intValue() <
-                           currentBreakPositions.peek().intValue()) {
-                        temp2 = currentBreakPositions.pop();
-                        wrongBreakPositions.add(temp2);
-                    }
-                    currentBreakPositions.push(temp);
-                    text.setIndex(currentBreakPositions.peek().intValue());
-                }
-
-                // re-sync "c" for the next go-round, and drop out of the loop if
-                // we've made it off the end of the range
-                c = getCurrent();
-                if (text.getIndex() >= endPos) {
-                    break;
-                }
-            }
-
-            // if we didn't hit any exceptional conditions on this last iteration,
-            // just advance to the next character and loop
-            else {
-                c = getNext();
-            }
-        }
-
-        // dump the last break position in the list, and replace it with the actual
-        // end of the range (which may be the same character, or may be further on
-        // because the range actually ended with non-dictionary characters we want to
-        // keep with the word)
-        if (!currentBreakPositions.isEmpty()) {
-            currentBreakPositions.pop();
-        }
-        currentBreakPositions.push(endPos);
-
-        // create a regular array to hold the break positions and copy
-        // the break positions from the stack to the array (in addition,
-        // our starting position goes into this array as a break position).
-        // This array becomes the cache of break positions used by next()
-        // and previous(), so this is where we actually refresh the cache.
-        cachedBreakPositions = new int[currentBreakPositions.size() + 1];
-        cachedBreakPositions[0] = startPos;
-
-        for (int i = 0; i < currentBreakPositions.size(); i++) {
-            cachedBreakPositions[i + 1] = currentBreakPositions.elementAt(i).intValue();
-        }
-        positionInCache = 0;
-    }
-}
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -42,7 +42,6 @@
 
 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;
@@ -113,13 +112,14 @@
         if (data == null || ((biInfo = data.get()) == null)) {
            biInfo = localeData.getBreakIteratorInfo(locale).getObject(key);
            cache.put(cacheKey, new ResourceReference(cacheKey, biInfo, referenceQueue));
-       }
+        }
 
        return biInfo;
     }
 
-    Module getBreakIteratorDataModule() {
-       return localeData.getBreakIteratorInfo(locale).getClass().getModule();
+    @SuppressWarnings("unchecked")
+    byte[] getBreakIteratorResources(String key) {
+        return (byte[]) localeData.getBreakIteratorResources(locale).getObject(key);
     }
 
     int getCalendarData(String key) {
--- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1198 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 - 2002 - 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.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;
-import java.text.BreakIterator;
-import java.text.CharacterIterator;
-import java.text.StringCharacterIterator;
-import java.util.MissingResourceException;
-import sun.text.CompactByteArray;
-import sun.text.SupplementaryCharacterData;
-
-/**
- * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p>
- *
- * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i>
- * and <i>regular expressions.</i></p>
- *
- * <p>A substitution rule defines a name that can be used in place of an expression. It
- * consists of a name, which is a string of characters contained in angle brackets, an equals
- * sign, and an expression. (There can be no whitespace on either side of the equals sign.)
- * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or
- * square brackets. A substitution is visible after its definition, and is filled in using
- * simple textual substitution. Substitution definitions can contain other substitutions, as
- * long as those substitutions have been defined first. Substitutions are generally used to
- * make the regular expressions (which can get quite complex) shorted and easier to read.
- * They typically define either character categories or commonly-used subexpressions.</p>
- *
- * <p>There is one special substitution.&nbsp; If the description defines a substitution
- * called &quot;&lt;ignore&gt;&quot;, the expression must be a [] expression, and the
- * expression defines a set of characters (the &quot;<em>ignore characters</em>&quot;) that
- * will be transparent to the BreakIterator.&nbsp; A sequence of characters will break the
- * same way it would if any ignore characters it contains are taken out.&nbsp; Break
- * positions never occur befoer ignore characters.</p>
- *
- * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and
- * defines a sequence of characters to be kept together. With one significant exception, the
- * iterator uses a longest-possible-match algorithm when matching text to regular
- * expressions. The iterator also treats descriptions containing multiple regular expressions
- * as if they were ORed together (i.e., as if they were separated by |).</p>
- *
- * <p>The special characters recognized by the regular-expression parser are as follows:</p>
- *
- * <blockquote>
- *   <table border="1" width="100%">
- *     <tr>
- *       <td width="6%">*</td>
- *       <td width="94%">Specifies that the expression preceding the asterisk may occur any number
- *       of times (including not at all).</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">{}</td>
- *       <td width="94%">Encloses a sequence of characters that is optional.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">()</td>
- *       <td width="94%">Encloses a sequence of characters.&nbsp; If followed by *, the sequence
- *       repeats.&nbsp; Otherwise, the parentheses are just a grouping device and a way to delimit
- *       the ends of expressions containing |.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">|</td>
- *       <td width="94%">Separates two alternative sequences of characters.&nbsp; Either one
- *       sequence or the other, but not both, matches this expression.&nbsp; The | character can
- *       only occur inside ().</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">.</td>
- *       <td width="94%">Matches any character.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">*?</td>
- *       <td width="94%">Specifies a non-greedy asterisk.&nbsp; *? works the same way as *, except
- *       when there is overlap between the last group of characters in the expression preceding the
- *       * and the first group of characters following the *.&nbsp; When there is this kind of
- *       overlap, * will match the longest sequence of characters that match the expression before
- *       the *, and *? will match the shortest sequence of characters matching the expression
- *       before the *?.&nbsp; For example, if you have &quot;xxyxyyyxyxyxxyxyxyy&quot; in the text,
- *       &quot;x[xy]*x&quot; will match through to the last x (i.e., &quot;<strong>xxyxyyyxyxyxxyxyx</strong>yy&quot;,
- *       but &quot;x[xy]*?x&quot; will only match the first two xes (&quot;<strong>xx</strong>yxyyyxyxyxxyxyxyy&quot;).</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">[]</td>
- *       <td width="94%">Specifies a group of alternative characters.&nbsp; A [] expression will
- *       match any single character that is specified in the [] expression.&nbsp; For more on the
- *       syntax of [] expressions, see below.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">/</td>
- *       <td width="94%">Specifies where the break position should go if text matches this
- *       expression.&nbsp; (e.g., &quot;[a-z]&#42;/[:Zs:]*[1-0]&quot; will match if the iterator sees a run
- *       of letters, followed by a run of whitespace, followed by a digit, but the break position
- *       will actually go before the whitespace).&nbsp; Expressions that don't contain / put the
- *       break position at the end of the matching text.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">\</td>
- *       <td width="94%">Escape character.&nbsp; The \ itself is ignored, but causes the next
- *       character to be treated as literal character.&nbsp; This has no effect for many
- *       characters, but for the characters listed above, this deprives them of their special
- *       meaning.&nbsp; (There are no special escape sequences for Unicode characters, or tabs and
- *       newlines; these are all handled by a higher-level protocol.&nbsp; In a Java string,
- *       &quot;\n&quot; will be converted to a literal newline character by the time the
- *       regular-expression parser sees it.&nbsp; Of course, this means that \ sequences that are
- *       visible to the regexp parser must be written as \\ when inside a Java string.)&nbsp; All
- *       characters in the ASCII range except for letters, digits, and control characters are
- *       reserved characters to the parser and must be preceded by \ even if they currently don't
- *       mean anything.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">!</td>
- *       <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp
- *       parser that this expression specifies the backwards-iteration behavior of the iterator,
- *       and not its normal iteration behavior.&nbsp; This is generally only used in situations
- *       where the automatically-generated backwards-iteration brhavior doesn't produce
- *       satisfactory results and must be supplemented with extra client-specified rules.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%"><em>(all others)</em></td>
- *       <td width="94%">All other characters are treated as literal characters, which must match
- *       the corresponding character(s) in the text exactly.</td>
- *     </tr>
- *   </table>
- * </blockquote>
- *
- * <p>Within a [] expression, a number of other special characters can be used to specify
- * groups of characters:</p>
- *
- * <blockquote>
- *   <table border="1" width="100%">
- *     <tr>
- *       <td width="6%">-</td>
- *       <td width="94%">Specifies a range of matching characters.&nbsp; For example
- *       &quot;[a-p]&quot; matches all lowercase Latin letters from a to p (inclusive).&nbsp; The -
- *       sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a
- *       language's alphabetical order: &quot;[a-z]&quot; doesn't include capital letters, nor does
- *       it include accented letters such as a-umlaut.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">::</td>
- *       <td width="94%">A pair of colons containing a one- or two-letter code matches all
- *       characters in the corresponding Unicode category.&nbsp; The two-letter codes are the same
- *       as the two-letter codes in the Unicode database (for example, &quot;[:Sc::Sm:]&quot;
- *       matches all currency symbols and all math symbols).&nbsp; Specifying a one-letter code is
- *       the same as specifying all two-letter codes that begin with that letter (for example,
- *       &quot;[:L:]&quot; matches all letters, and is equivalent to
- *       &quot;[:Lu::Ll::Lo::Lm::Lt:]&quot;).&nbsp; Anything other than a valid two-letter Unicode
- *       category code or a single letter that begins a Unicode category code is illegal within
- *       colons.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">[]</td>
- *       <td width="94%">[] expressions can nest.&nbsp; This has no effect, except when used in
- *       conjunction with the ^ token.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%">^</td>
- *       <td width="94%">Excludes the character (or the characters in the [] expression) following
- *       it from the group of characters.&nbsp; For example, &quot;[a-z^p]&quot; matches all Latin
- *       lowercase letters except p.&nbsp; &quot;[:L:^[&#92;u4e00-&#92;u9fff]]&quot; matches all letters
- *       except the Han ideographs.</td>
- *     </tr>
- *     <tr>
- *       <td width="6%"><em>(all others)</em></td>
- *       <td width="94%">All other characters are treated as literal characters.&nbsp; (For
- *       example, &quot;[aeiou]&quot; specifies just the letters a, e, i, o, and u.)</td>
- *     </tr>
- *   </table>
- * </blockquote>
- *
- * <p>For a more complete explanation, see <a
- * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>.
- * &nbsp; For examples, see the resource data (which is annotated).</p>
- *
- * @author Richard Gillam
- */
-class RuleBasedBreakIterator extends BreakIterator {
-
-    /**
-     * A token used as a character-category value to identify ignore characters
-     */
-    protected static final byte IGNORE = -1;
-
-    /**
-     * The state number of the starting state
-     */
-    private static final short START_STATE = 1;
-
-    /**
-     * The state-transition value indicating "stop"
-     */
-    private static final short STOP_STATE = 0;
-
-    /**
-     * Magic number for the BreakIterator data file format.
-     */
-    static final byte[] LABEL = {
-        (byte)'B', (byte)'I', (byte)'d', (byte)'a', (byte)'t', (byte)'a',
-        (byte)'\0'
-    };
-    static final int    LABEL_LENGTH = LABEL.length;
-
-    /**
-     * Version number of the dictionary that was read in.
-     */
-    static final byte supportedVersion = 1;
-
-    /**
-     * Header size in byte count
-     */
-    private static final int HEADER_LENGTH = 36;
-
-    /**
-     * An array length of indices for BMP characters
-     */
-    private static final int BMP_INDICES_LENGTH = 512;
-
-    /**
-     * Tables that indexes from character values to character category numbers
-     */
-    private CompactByteArray charCategoryTable = null;
-    private SupplementaryCharacterData supplementaryCharCategoryTable = null;
-
-    /**
-     * The table of state transitions used for forward iteration
-     */
-    private short[] stateTable = null;
-
-    /**
-     * The table of state transitions used to sync up the iterator with the
-     * text in backwards and random-access iteration
-     */
-    private short[] backwardsStateTable = null;
-
-    /**
-     * A list of flags indicating which states in the state table are accepting
-     * ("end") states
-     */
-    private boolean[] endStates = null;
-
-    /**
-     * A list of flags indicating which states in the state table are
-     * lookahead states (states which turn lookahead on and off)
-     */
-    private boolean[] lookaheadStates = null;
-
-    /**
-     * A table for additional data. May be used by a subclass of
-     * RuleBasedBreakIterator.
-     */
-    private byte[] additionalData = null;
-
-    /**
-     * The number of character categories (and, thus, the number of columns in
-     * the state tables)
-     */
-    private int numCategories;
-
-    /**
-     * The character iterator through which this BreakIterator accesses the text
-     */
-    private CharacterIterator text = null;
-
-    /**
-     * A CRC32 value of all data in datafile
-     */
-    private long checksum;
-
-    //=======================================================================
-    // constructors
-    //=======================================================================
-
-    /**
-     * Constructs a RuleBasedBreakIterator according to the module and the datafile
-     * provided.
-     */
-    RuleBasedBreakIterator(Module module, String datafile)
-        throws IOException, MissingResourceException {
-        readTables(module, datafile);
-    }
-
-    /**
-     * Read datafile. The datafile's format is as follows:
-     * <pre>
-     *   BreakIteratorData {
-     *       u1           magic[7];
-     *       u1           version;
-     *       u4           totalDataSize;
-     *       header_info  header;
-     *       body         value;
-     *   }
-     * </pre>
-     * <code>totalDataSize</code> is the summation of the size of
-     * <code>header_info</code> and <code>body</code> in byte count.
-     * <p>
-     * In <code>header</code>, each field except for checksum implies the
-     * length of each field. Since <code>BMPdataLength</code> is a fixed-length
-     *  data(512 entries), its length isn't included in <code>header</code>.
-     * <code>checksum</code> is a CRC32 value of all in <code>body</code>.
-     * <pre>
-     *   header_info {
-     *       u4           stateTableLength;
-     *       u4           backwardsStateTableLength;
-     *       u4           endStatesLength;
-     *       u4           lookaheadStatesLength;
-     *       u4           BMPdataLength;
-     *       u4           nonBMPdataLength;
-     *       u4           additionalDataLength;
-     *       u8           checksum;
-     *   }
-     * </pre>
-     * <p>
-     *
-     * Finally, <code>BMPindices</code> and <code>BMPdata</code> are set to
-     * <code>charCategoryTable</code>. <code>nonBMPdata</code> is set to
-     * <code>supplementaryCharCategoryTable</code>.
-     * <pre>
-     *   body {
-     *       u2           stateTable[stateTableLength];
-     *       u2           backwardsStateTable[backwardsStateTableLength];
-     *       u1           endStates[endStatesLength];
-     *       u1           lookaheadStates[lookaheadStatesLength];
-     *       u2           BMPindices[512];
-     *       u1           BMPdata[BMPdataLength];
-     *       u4           nonBMPdata[numNonBMPdataLength];
-     *       u1           additionalData[additionalDataLength];
-     *   }
-     * </pre>
-     */
-    protected final void readTables(Module module, String datafile)
-        throws IOException, MissingResourceException {
-
-        byte[] buffer = readFile(module, datafile);
-
-        /* Read header_info. */
-        int stateTableLength = getInt(buffer, 0);
-        int backwardsStateTableLength = getInt(buffer, 4);
-        int endStatesLength = getInt(buffer, 8);
-        int lookaheadStatesLength = getInt(buffer, 12);
-        int BMPdataLength = getInt(buffer, 16);
-        int nonBMPdataLength = getInt(buffer, 20);
-        int additionalDataLength = getInt(buffer, 24);
-        checksum = getLong(buffer, 28);
-
-        /* Read stateTable[numCategories * numRows] */
-        stateTable = new short[stateTableLength];
-        int offset = HEADER_LENGTH;
-        for (int i = 0; i < stateTableLength; i++, offset+=2) {
-           stateTable[i] = getShort(buffer, offset);
-        }
-
-        /* Read backwardsStateTable[numCategories * numRows] */
-        backwardsStateTable = new short[backwardsStateTableLength];
-        for (int i = 0; i < backwardsStateTableLength; i++, offset+=2) {
-           backwardsStateTable[i] = getShort(buffer, offset);
-        }
-
-        /* Read endStates[numRows] */
-        endStates = new boolean[endStatesLength];
-        for (int i = 0; i < endStatesLength; i++, offset++) {
-           endStates[i] = buffer[offset] == 1;
-        }
-
-        /* Read lookaheadStates[numRows] */
-        lookaheadStates = new boolean[lookaheadStatesLength];
-        for (int i = 0; i < lookaheadStatesLength; i++, offset++) {
-           lookaheadStates[i] = buffer[offset] == 1;
-        }
-
-        /* Read a category table and indices for BMP characters. */
-        short[] temp1 = new short[BMP_INDICES_LENGTH];  // BMPindices
-        for (int i = 0; i < BMP_INDICES_LENGTH; i++, offset+=2) {
-            temp1[i] = getShort(buffer, offset);
-        }
-        byte[] temp2 = new byte[BMPdataLength];  // BMPdata
-        System.arraycopy(buffer, offset, temp2, 0, BMPdataLength);
-        offset += BMPdataLength;
-        charCategoryTable = new CompactByteArray(temp1, temp2);
-
-        /* Read a category table for non-BMP characters. */
-        int[] temp3 = new int[nonBMPdataLength];
-        for (int i = 0; i < nonBMPdataLength; i++, offset+=4) {
-            temp3[i] = getInt(buffer, offset);
-        }
-        supplementaryCharCategoryTable = new SupplementaryCharacterData(temp3);
-
-        /* Read additional data */
-        if (additionalDataLength > 0) {
-            additionalData = new byte[additionalDataLength];
-            System.arraycopy(buffer, offset, additionalData, 0, additionalDataLength);
-        }
-
-        /* Set numCategories */
-        numCategories = stateTable.length / endStates.length;
-    }
-
-    protected byte[] readFile(final Module module, final String datafile)
-        throws IOException, MissingResourceException {
-
-        BufferedInputStream is;
-        try {
-            PrivilegedExceptionAction<BufferedInputStream> pa = () -> {
-                String pathName = "jdk.localedata".equals(module.getName()) ?
-                     "sun/text/resources/ext/" :
-                     "sun/text/resources/";
-                InputStream in = module.getResourceAsStream(pathName + 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);
-                }
-
-                return new BufferedInputStream(in);
-            };
-            is = AccessController.doPrivileged(pa);
-        } catch (PrivilegedActionException e) {
-            throw new InternalError(e.toString(), e);
-        }
-
-        int offset = 0;
-
-        /* First, read magic, version, and header_info. */
-        int len = LABEL_LENGTH + 5;
-        byte[] buf = new byte[len];
-        if (is.read(buf) != len) {
-            throw new MissingResourceException("Wrong header length",
-                                               datafile, "");
-        }
-
-        /* Validate the magic number. */
-        for (int i = 0; i < LABEL_LENGTH; i++, offset++) {
-            if (buf[offset] != LABEL[offset]) {
-                throw new MissingResourceException("Wrong magic number",
-                                                   datafile, "");
-            }
-        }
-
-        /* Validate the version number. */
-        if (buf[offset] != supportedVersion) {
-            throw new MissingResourceException("Unsupported version(" + buf[offset] + ")",
-                                               datafile, "");
-        }
-
-        /* Read data: totalDataSize + 8(for checksum) */
-        len = getInt(buf, ++offset);
-        buf = new byte[len];
-        if (is.read(buf) != len) {
-            throw new MissingResourceException("Wrong data length",
-                                               datafile, "");
-        }
-
-        is.close();
-
-        return buf;
-    }
-
-    byte[] getAdditionalData() {
-        return additionalData;
-    }
-
-    void setAdditionalData(byte[] b) {
-        additionalData = b;
-    }
-
-    //=======================================================================
-    // boilerplate
-    //=======================================================================
-    /**
-     * Clones this iterator.
-     * @return A newly-constructed RuleBasedBreakIterator with the same
-     * behavior as this one.
-     */
-    @Override
-    public Object clone() {
-        RuleBasedBreakIterator result = (RuleBasedBreakIterator) super.clone();
-        if (text != null) {
-            result.text = (CharacterIterator) text.clone();
-        }
-        return result;
-    }
-
-    /**
-     * Returns true if both BreakIterators are of the same class, have the same
-     * rules, and iterate over the same text.
-     */
-    @Override
-    public boolean equals(Object that) {
-        try {
-            if (that == null) {
-                return false;
-            }
-
-            RuleBasedBreakIterator other = (RuleBasedBreakIterator) that;
-            if (checksum != other.checksum) {
-                return false;
-            }
-            if (text == null) {
-                return other.text == null;
-            } else {
-                return text.equals(other.text);
-            }
-        }
-        catch(ClassCastException e) {
-            return false;
-        }
-    }
-
-    /**
-     * Returns text
-     */
-    @Override
-    public String toString() {
-        return "[checksum=0x" + Long.toHexString(checksum) + ']';
-    }
-
-    /**
-     * Compute a hashcode for this BreakIterator
-     * @return A hash code
-     */
-    @Override
-    public int hashCode() {
-        return (int)checksum;
-    }
-
-    //=======================================================================
-    // BreakIterator overrides
-    //=======================================================================
-
-    /**
-     * Sets the current iteration position to the beginning of the text.
-     * (i.e., the CharacterIterator's starting offset).
-     * @return The offset of the beginning of the text.
-     */
-    @Override
-    public int first() {
-        CharacterIterator t = getText();
-
-        t.first();
-        return t.getIndex();
-    }
-
-    /**
-     * Sets the current iteration position to the end of the text.
-     * (i.e., the CharacterIterator's ending offset).
-     * @return The text's past-the-end offset.
-     */
-    @Override
-    public int last() {
-        CharacterIterator t = getText();
-
-        // I'm not sure why, but t.last() returns the offset of the last character,
-        // rather than the past-the-end offset
-        t.setIndex(t.getEndIndex());
-        return t.getIndex();
-    }
-
-    /**
-     * Advances the iterator either forward or backward the specified number of steps.
-     * Negative values move backward, and positive values move forward.  This is
-     * equivalent to repeatedly calling next() or previous().
-     * @param n The number of steps to move.  The sign indicates the direction
-     * (negative is backwards, and positive is forwards).
-     * @return The character offset of the boundary position n boundaries away from
-     * the current one.
-     */
-    @Override
-    public int next(int n) {
-        int result = current();
-        while (n > 0) {
-            result = handleNext();
-            --n;
-        }
-        while (n < 0) {
-            result = previous();
-            ++n;
-        }
-        return result;
-    }
-
-    /**
-     * Advances the iterator to the next boundary position.
-     * @return The position of the first boundary after this one.
-     */
-    @Override
-    public int next() {
-        return handleNext();
-    }
-
-    private int cachedLastKnownBreak = BreakIterator.DONE;
-
-    /**
-     * Advances the iterator backwards, to the last boundary preceding this one.
-     * @return The position of the last boundary position preceding this one.
-     */
-    @Override
-    public int previous() {
-        // if we're already sitting at the beginning of the text, return DONE
-        CharacterIterator text = getText();
-        if (current() == text.getBeginIndex()) {
-            return BreakIterator.DONE;
-        }
-
-        // set things up.  handlePrevious() will back us up to some valid
-        // break position before the current position (we back our internal
-        // iterator up one step to prevent handlePrevious() from returning
-        // the current position), but not necessarily the last one before
-        // where we started
-        int start = current();
-        int lastResult = cachedLastKnownBreak;
-        if (lastResult >= start || lastResult <= BreakIterator.DONE) {
-            getPrevious();
-            lastResult = handlePrevious();
-        } else {
-            //it might be better to check if handlePrevious() give us closer
-            //safe value but handlePrevious() is slow too
-            //So, this has to be done carefully
-            text.setIndex(lastResult);
-        }
-        int result = lastResult;
-
-        // iterate forward from the known break position until we pass our
-        // starting point.  The last break position before the starting
-        // point is our return value
-        while (result != BreakIterator.DONE && result < start) {
-            lastResult = result;
-            result = handleNext();
-        }
-
-        // set the current iteration position to be the last break position
-        // before where we started, and then return that value
-        text.setIndex(lastResult);
-        cachedLastKnownBreak = lastResult;
-        return lastResult;
-    }
-
-    /**
-     * Returns previous character
-     */
-    private int getPrevious() {
-        char c2 = text.previous();
-        if (Character.isLowSurrogate(c2) &&
-            text.getIndex() > text.getBeginIndex()) {
-            char c1 = text.previous();
-            if (Character.isHighSurrogate(c1)) {
-                return Character.toCodePoint(c1, c2);
-            } else {
-                text.next();
-            }
-        }
-        return (int)c2;
-    }
-
-    /**
-     * Returns current character
-     */
-    int getCurrent() {
-        char c1 = text.current();
-        if (Character.isHighSurrogate(c1) &&
-            text.getIndex() < text.getEndIndex()) {
-            char c2 = text.next();
-            text.previous();
-            if (Character.isLowSurrogate(c2)) {
-                return Character.toCodePoint(c1, c2);
-            }
-        }
-        return (int)c1;
-    }
-
-    /**
-     * Returns the count of next character.
-     */
-    private int getCurrentCodePointCount() {
-        char c1 = text.current();
-        if (Character.isHighSurrogate(c1) &&
-            text.getIndex() < text.getEndIndex()) {
-            char c2 = text.next();
-            text.previous();
-            if (Character.isLowSurrogate(c2)) {
-                return 2;
-            }
-        }
-        return 1;
-    }
-
-    /**
-     * Returns next character
-     */
-    int getNext() {
-        int index = text.getIndex();
-        int endIndex = text.getEndIndex();
-        if (index == endIndex ||
-            (index += getCurrentCodePointCount()) >= endIndex) {
-            return CharacterIterator.DONE;
-        }
-        text.setIndex(index);
-        return getCurrent();
-    }
-
-    /**
-     * Returns the position of next character.
-     */
-    private int getNextIndex() {
-        int index = text.getIndex() + getCurrentCodePointCount();
-        int endIndex = text.getEndIndex();
-        if (index > endIndex) {
-            return endIndex;
-        } else {
-            return index;
-        }
-    }
-
-    /**
-     * Throw IllegalArgumentException unless begin <= offset < end.
-     */
-    protected static final void checkOffset(int offset, CharacterIterator text) {
-        if (offset < text.getBeginIndex() || offset > text.getEndIndex()) {
-            throw new IllegalArgumentException("offset out of bounds");
-        }
-    }
-
-    /**
-     * Sets the iterator to refer to the first boundary position following
-     * the specified position.
-     * @offset The position from which to begin searching for a break position.
-     * @return The position of the first break after the current position.
-     */
-    @Override
-    public int following(int offset) {
-
-        CharacterIterator text = getText();
-        checkOffset(offset, text);
-
-        // Set our internal iteration position (temporarily)
-        // to the position passed in.  If this is the _beginning_ position,
-        // then we can just use next() to get our return value
-        text.setIndex(offset);
-        if (offset == text.getBeginIndex()) {
-            cachedLastKnownBreak = handleNext();
-            return cachedLastKnownBreak;
-        }
-
-        // otherwise, we have to sync up first.  Use handlePrevious() to back
-        // us up to a known break position before the specified position (if
-        // we can determine that the specified position is a break position,
-        // we don't back up at all).  This may or may not be the last break
-        // position at or before our starting position.  Advance forward
-        // from here until we've passed the starting position.  The position
-        // we stop on will be the first break position after the specified one.
-        int result = cachedLastKnownBreak;
-        if (result >= offset || result <= BreakIterator.DONE) {
-            result = handlePrevious();
-        } else {
-            //it might be better to check if handlePrevious() give us closer
-            //safe value but handlePrevious() is slow too
-            //So, this has to be done carefully
-            text.setIndex(result);
-        }
-        while (result != BreakIterator.DONE && result <= offset) {
-            result = handleNext();
-        }
-        cachedLastKnownBreak = result;
-        return result;
-    }
-
-    /**
-     * Sets the iterator to refer to the last boundary position before the
-     * specified position.
-     * @offset The position to begin searching for a break from.
-     * @return The position of the last boundary before the starting position.
-     */
-    @Override
-    public int preceding(int offset) {
-        // if we start by updating the current iteration position to the
-        // position specified by the caller, we can just use previous()
-        // to carry out this operation
-        CharacterIterator text = getText();
-        checkOffset(offset, text);
-        text.setIndex(offset);
-        return previous();
-    }
-
-    /**
-     * Returns true if the specified position is a boundary position.  As a side
-     * effect, leaves the iterator pointing to the first boundary position at
-     * or after "offset".
-     * @param offset the offset to check.
-     * @return True if "offset" is a boundary position.
-     */
-    @Override
-    public boolean isBoundary(int offset) {
-        CharacterIterator text = getText();
-        checkOffset(offset, text);
-        if (offset == text.getBeginIndex()) {
-            return true;
-        }
-
-        // to check whether this is a boundary, we can use following() on the
-        // position before the specified one and return true if the position we
-        // get back is the one the user specified
-        else {
-            return following(offset - 1) == offset;
-        }
-    }
-
-    /**
-     * Returns the current iteration position.
-     * @return The current iteration position.
-     */
-    @Override
-    public int current() {
-        return getText().getIndex();
-    }
-
-    /**
-     * Return a CharacterIterator over the text being analyzed.  This version
-     * of this method returns the actual CharacterIterator we're using internally.
-     * Changing the state of this iterator can have undefined consequences.  If
-     * you need to change it, clone it first.
-     * @return An iterator over the text being analyzed.
-     */
-    @Override
-    public CharacterIterator getText() {
-        // The iterator is initialized pointing to no text at all, so if this
-        // function is called while we're in that state, we have to fudge an
-        // iterator to return.
-        if (text == null) {
-            text = new StringCharacterIterator("");
-        }
-        return text;
-    }
-
-    /**
-     * Set the iterator to analyze a new piece of text.  This function resets
-     * the current iteration position to the beginning of the text.
-     * @param newText An iterator over the text to analyze.
-     */
-    @Override
-    public void setText(CharacterIterator newText) {
-        // Test iterator to see if we need to wrap it in a SafeCharIterator.
-        // The correct behavior for CharacterIterators is to allow the
-        // position to be set to the endpoint of the iterator.  Many
-        // CharacterIterators do not uphold this, so this is a workaround
-        // to permit them to use this class.
-        int end = newText.getEndIndex();
-        boolean goodIterator;
-        try {
-            newText.setIndex(end);  // some buggy iterators throw an exception here
-            goodIterator = newText.getIndex() == end;
-        }
-        catch(IllegalArgumentException e) {
-            goodIterator = false;
-        }
-
-        if (goodIterator) {
-            text = newText;
-        }
-        else {
-            text = new SafeCharIterator(newText);
-        }
-        text.first();
-
-        cachedLastKnownBreak = BreakIterator.DONE;
-    }
-
-
-    //=======================================================================
-    // implementation
-    //=======================================================================
-
-    /**
-     * This method is the actual implementation of the next() method.  All iteration
-     * vectors through here.  This method initializes the state machine to state 1
-     * and advances through the text character by character until we reach the end
-     * of the text or the state machine transitions to state 0.  We update our return
-     * value every time the state machine passes through a possible end state.
-     */
-    protected int handleNext() {
-        // if we're already at the end of the text, return DONE.
-        CharacterIterator text = getText();
-        if (text.getIndex() == text.getEndIndex()) {
-            return BreakIterator.DONE;
-        }
-
-        // no matter what, we always advance at least one character forward
-        int result = getNextIndex();
-        int lookaheadResult = 0;
-
-        // begin in state 1
-        int state = START_STATE;
-        int category;
-        int c = getCurrent();
-
-        // loop until we reach the end of the text or transition to state 0
-        while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
-            // look up the current character's character category (which tells us
-            // which column in the state table to look at)
-            category = lookupCategory(c);
-
-            // if the character isn't an ignore character, look up a state
-            // transition in the state table
-            if (category != IGNORE) {
-                state = lookupState(state, category);
-            }
-
-            // if the state we've just transitioned to is a lookahead state,
-            // (but not also an end state), save its position.  If it's
-            // both a lookahead state and an end state, update the break position
-            // to the last saved lookup-state position
-            if (lookaheadStates[state]) {
-                if (endStates[state]) {
-                    result = lookaheadResult;
-                }
-                else {
-                    lookaheadResult = getNextIndex();
-                }
-            }
-
-            // otherwise, if the state we've just transitioned to is an accepting
-            // state, update the break position to be the current iteration position
-            else {
-                if (endStates[state]) {
-                    result = getNextIndex();
-                }
-            }
-
-            c = getNext();
-        }
-
-        // if we've run off the end of the text, and the very last character took us into
-        // a lookahead state, advance the break position to the lookahead position
-        // (the theory here is that if there are no characters at all after the lookahead
-        // position, that always matches the lookahead criteria)
-        if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
-            result = lookaheadResult;
-        }
-
-        text.setIndex(result);
-        return result;
-    }
-
-    /**
-     * This method backs the iterator back up to a "safe position" in the text.
-     * This is a position that we know, without any context, must be a break position.
-     * The various calling methods then iterate forward from this safe position to
-     * the appropriate position to return.  (For more information, see the description
-     * of buildBackwardsStateTable() in RuleBasedBreakIterator.Builder.)
-     */
-    protected int handlePrevious() {
-        CharacterIterator text = getText();
-        int state = START_STATE;
-        int category = 0;
-        int lastCategory = 0;
-        int c = getCurrent();
-
-        // loop until we reach the beginning of the text or transition to state 0
-        while (c != CharacterIterator.DONE && state != STOP_STATE) {
-
-            // save the last character's category and look up the current
-            // character's category
-            lastCategory = category;
-            category = lookupCategory(c);
-
-            // if the current character isn't an ignore character, look up a
-            // state transition in the backwards state table
-            if (category != IGNORE) {
-                state = lookupBackwardState(state, category);
-            }
-
-            // then advance one character backwards
-            c = getPrevious();
-        }
-
-        // if we didn't march off the beginning of the text, we're either one or two
-        // positions away from the real break position.  (One because of the call to
-        // previous() at the end of the loop above, and another because the character
-        // that takes us into the stop state will always be the character BEFORE
-        // the break position.)
-        if (c != CharacterIterator.DONE) {
-            if (lastCategory != IGNORE) {
-                getNext();
-                getNext();
-            }
-            else {
-                getNext();
-            }
-        }
-        return text.getIndex();
-    }
-
-    /**
-     * Looks up a character's category (i.e., its category for breaking purposes,
-     * not its Unicode category)
-     */
-    protected int lookupCategory(int c) {
-        if (c < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
-            return charCategoryTable.elementAt((char)c);
-        } else {
-            return supplementaryCharCategoryTable.getValue(c);
-        }
-    }
-
-    /**
-     * Given a current state and a character category, looks up the
-     * next state to transition to in the state table.
-     */
-    protected int lookupState(int state, int category) {
-        return stateTable[state * numCategories + category];
-    }
-
-    /**
-     * Given a current state and a character category, looks up the
-     * next state to transition to in the backwards state table.
-     */
-    protected int lookupBackwardState(int state, int category) {
-        return backwardsStateTable[state * numCategories + category];
-    }
-
-    static long getLong(byte[] buf, int offset) {
-        long num = buf[offset]&0xFF;
-        for (int i = 1; i < 8; i++) {
-            num = num<<8 | (buf[offset+i]&0xFF);
-        }
-        return num;
-    }
-
-    static int getInt(byte[] buf, int offset) {
-        int num = buf[offset]&0xFF;
-        for (int i = 1; i < 4; i++) {
-            num = num<<8 | (buf[offset+i]&0xFF);
-        }
-        return num;
-    }
-
-    static short getShort(byte[] buf, int offset) {
-        short num = (short)(buf[offset]&0xFF);
-        num = (short)(num<<8 | (buf[offset+1]&0xFF));
-        return num;
-    }
-
-    /*
-     * This class exists to work around a bug in incorrect implementations
-     * of CharacterIterator, which incorrectly handle setIndex(endIndex).
-     * This iterator relies only on base.setIndex(n) where n is less than
-     * endIndex.
-     *
-     * One caveat:  if the base iterator's begin and end indices change
-     * the change will not be reflected by this wrapper.  Does that matter?
-     */
-    // TODO: Review this class to see if it's still required.
-    private static final class SafeCharIterator implements CharacterIterator,
-                                                           Cloneable {
-
-        private CharacterIterator base;
-        private int rangeStart;
-        private int rangeLimit;
-        private int currentIndex;
-
-        SafeCharIterator(CharacterIterator base) {
-            this.base = base;
-            this.rangeStart = base.getBeginIndex();
-            this.rangeLimit = base.getEndIndex();
-            this.currentIndex = base.getIndex();
-        }
-
-        @Override
-        public char first() {
-            return setIndex(rangeStart);
-        }
-
-        @Override
-        public char last() {
-            return setIndex(rangeLimit - 1);
-        }
-
-        @Override
-        public char current() {
-            if (currentIndex < rangeStart || currentIndex >= rangeLimit) {
-                return DONE;
-            }
-            else {
-                return base.setIndex(currentIndex);
-            }
-        }
-
-        @Override
-        public char next() {
-
-            currentIndex++;
-            if (currentIndex >= rangeLimit) {
-                currentIndex = rangeLimit;
-                return DONE;
-            }
-            else {
-                return base.setIndex(currentIndex);
-            }
-        }
-
-        @Override
-        public char previous() {
-
-            currentIndex--;
-            if (currentIndex < rangeStart) {
-                currentIndex = rangeStart;
-                return DONE;
-            }
-            else {
-                return base.setIndex(currentIndex);
-            }
-        }
-
-        @Override
-        public char setIndex(int i) {
-
-            if (i < rangeStart || i > rangeLimit) {
-                throw new IllegalArgumentException("Invalid position");
-            }
-            currentIndex = i;
-            return current();
-        }
-
-        @Override
-        public int getBeginIndex() {
-            return rangeStart;
-        }
-
-        @Override
-        public int getEndIndex() {
-            return rangeLimit;
-        }
-
-        @Override
-        public int getIndex() {
-            return currentIndex;
-        }
-
-        @Override
-        public Object clone() {
-
-            SafeCharIterator copy = null;
-            try {
-                copy = (SafeCharIterator) super.clone();
-            }
-            catch(CloneNotSupportedException e) {
-                throw new Error("Clone not supported: " + e);
-            }
-
-            CharacterIterator copyOfBase = (CharacterIterator) base.clone();
-            copy.base = copyOfBase;
-            return copy;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/util/resources/BreakIteratorResourceBundle.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.io.InputStream;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+/**
+ * BreakIteratorResourceBundle is an abstract class for loading BreakIterator
+ * data (rules or dictionary) from each module. An implementation class must
+ * implement getBreakIteratorInfo() that returns an instance of the
+ * corresponding BreakIteratorInfo (basename).  The data name is taken from the
+ * BreakIteratorInfo instance.
+ *
+ * <p>For example, if the given key is "WordDictionary" and Locale is "th", the
+ * data name is taken from a BreakIteratorInfo_th and the key's value is
+ * "thai_dict".  Its data thai_dict is loaded from the Module of the
+ * implementation class of this class.
+ */
+
+public abstract class BreakIteratorResourceBundle extends ResourceBundle {
+    // If any keys that are not for data names are added to BreakIteratorInfo*,
+    // those keys must be added to NON_DATA_KEYS.
+    private static final Set<String> NON_DATA_KEYS = Set.of("BreakIteratorClasses");
+
+    private volatile Set<String> keys;
+
+    /**
+     * Returns an instance of the corresponding {@code BreakIteratorInfo} (basename).
+     * The instance shouldn't have its parent.
+     */
+    protected abstract ResourceBundle getBreakIteratorInfo();
+
+    @Override
+    protected Object handleGetObject(String key) {
+        if (NON_DATA_KEYS.contains(key)) {
+            return null;
+        }
+        ResourceBundle info = getBreakIteratorInfo();
+        if (!info.containsKey(key)) {
+            return null;
+        }
+        String path = getClass().getPackage().getName().replace('.', '/')
+                      + '/' + info.getString(key);
+        byte[] data;
+        try (InputStream is = getResourceAsStream(path)) {
+            data = is.readAllBytes();
+        } catch (Exception e) {
+            throw new InternalError("Can't load " + path, e);
+        }
+        return data;
+    }
+
+    private InputStream getResourceAsStream(String path) throws Exception {
+        PrivilegedExceptionAction<InputStream> pa;
+        pa = () -> getClass().getModule().getResourceAsStream(path);
+        InputStream is;
+        try {
+            is = AccessController.doPrivileged(pa);
+        } catch (PrivilegedActionException e) {
+            throw e.getException();
+        }
+        return is;
+    }
+
+    @Override
+    public Enumeration<String> getKeys() {
+        return Collections.enumeration(keySet());
+    }
+
+    @Override
+    protected Set<String> handleKeySet() {
+        if (keys == null) {
+            ResourceBundle info = getBreakIteratorInfo();
+            Set<String> k = info.keySet();
+            k.removeAll(NON_DATA_KEYS);
+            synchronized (this) {
+                if (keys == null) {
+                    keys = k;
+                }
+            }
+        }
+        return keys;
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java	Fri Nov 11 16:44:36 2016 +0100
@@ -123,6 +123,14 @@
     }
 
     /**
+     * Gets a break iterator resources resource bundle, using
+     * privileges to allow accessing a sun.* package.
+     */
+    public ResourceBundle getBreakIteratorResources(Locale locale) {
+        return getBundle(type.getTextResourcesPackage() + ".BreakIteratorResources", locale);
+    }
+
+    /**
      * Gets a collation data resource bundle, using privileges
      * to allow accessing a sun.* package.
      */
--- a/jdk/src/java.base/share/conf/security/java.security	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/conf/security/java.security	Fri Nov 11 16:44:36 2016 +0100
@@ -645,6 +645,9 @@
 # before larger keysize constraints of the same algorithm.  For example:
 # "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
 #
+# Note: The algorithm restrictions do not apply to trust anchors or
+# self-signed certificates.
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
@@ -714,6 +717,9 @@
 # See the specification of "jdk.certpath.disabledAlgorithms" for the
 # syntax of the disabled algorithm string.
 #
+# Note: The algorithm restrictions do not apply to trust anchors or
+# self-signed certificates.
+#
 # Note: This property is currently used by Oracle's JSSE implementation.
 # It is not guaranteed to be examined and used by other implementations.
 #
--- a/jdk/src/java.base/share/lib/security/default.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/lib/security/default.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -32,8 +32,22 @@
     permission javax.smartcardio.CardPermission "*", "*";
     permission java.lang.RuntimePermission "loadLibrary.j2pcsc";
     permission java.lang.RuntimePermission
-                   "accessClassInPackage.sun.security.*";
-    permission java.util.PropertyPermission "*", "read";
+                   "accessClassInPackage.sun.security.jca";
+    permission java.lang.RuntimePermission
+                   "accessClassInPackage.sun.security.util";
+    permission java.util.PropertyPermission
+                   "javax.smartcardio.TerminalFactory.DefaultType", "read";
+    permission java.util.PropertyPermission "os.name", "read";
+    permission java.util.PropertyPermission "os.arch", "read";
+    permission java.util.PropertyPermission "sun.arch.data.model", "read";
+    permission java.util.PropertyPermission
+                   "sun.security.smartcardio.library", "read";
+    permission java.util.PropertyPermission
+                   "sun.security.smartcardio.t0GetResponse", "read";
+    permission java.util.PropertyPermission
+                   "sun.security.smartcardio.t1GetResponse", "read";
+    permission java.util.PropertyPermission
+                   "sun.security.smartcardio.t1StripLe", "read";
     // needed for looking up native PC/SC library
     permission java.io.FilePermission "<<ALL FILES>>","read";
     permission java.security.SecurityPermission "putProviderProperty.SunPCSC";
--- a/jdk/src/java.base/share/native/include/jvm.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/include/jvm.h	Fri Nov 11 16:44:36 2016 +0100
@@ -165,14 +165,24 @@
 JNIEXPORT jboolean JNICALL
 JVM_IsSupportedJNIVersion(jint version);
 
+JNIEXPORT jobjectArray JNICALL
+JVM_GetVmArguments(JNIEnv *env);
+
+
 /*
  * java.lang.Throwable
  */
 JNIEXPORT void JNICALL
 JVM_FillInStackTrace(JNIEnv *env, jobject throwable);
 
+/*
+ * java.lang.StackTraceElement
+ */
 JNIEXPORT void JNICALL
-JVM_GetStackTraceElements(JNIEnv *env, jobject throwable, jobjectArray elements);
+JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable);
+
+JNIEXPORT void JNICALL
+JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo);
 
 /*
  * java.lang.StackWalker
@@ -194,12 +204,6 @@
                   jint frame_count, jint start_index,
                   jobjectArray frames);
 
-JNIEXPORT void JNICALL
-JVM_ToStackTraceElement(JNIEnv* env, jobject frame, jobject stackElement);
-
-JNIEXPORT jobjectArray JNICALL
-JVM_GetVmArguments(JNIEnv *env);
-
 /*
  * java.lang.Thread
  */
--- a/jdk/src/java.base/share/native/include/jvmti.h	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2551 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
- /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
-
-    /* Include file for the Java(tm) Virtual Machine Tool Interface */
-
-#ifndef _JAVA_JVMTI_H_
-#define _JAVA_JVMTI_H_
-
-#include "jni.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum {
-    JVMTI_VERSION_1   = 0x30010000,
-    JVMTI_VERSION_1_0 = 0x30010000,
-    JVMTI_VERSION_1_1 = 0x30010100,
-    JVMTI_VERSION_1_2 = 0x30010200,
-    JVMTI_VERSION_9   = 0x30090000,
-
-    JVMTI_VERSION = 0x30000000 + (9 * 0x10000) + (0 * 0x100) + 0  /* version: 9.0.0 */
-};
-
-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
-Agent_OnUnload(JavaVM *vm);
-
-    /* Forward declaration of the environment */
-
-struct _jvmtiEnv;
-
-struct jvmtiInterface_1_;
-
-#ifdef __cplusplus
-typedef _jvmtiEnv jvmtiEnv;
-#else
-typedef const struct jvmtiInterface_1_ *jvmtiEnv;
-#endif /* __cplusplus */
-
-/* Derived Base Types */
-
-typedef jobject jthread;
-typedef jobject jthreadGroup;
-typedef jlong jlocation;
-struct _jrawMonitorID;
-typedef struct _jrawMonitorID *jrawMonitorID;
-typedef struct JNINativeInterface_ jniNativeInterface;
-
-    /* Constants */
-
-
-    /* Thread State Flags */
-
-enum {
-    JVMTI_THREAD_STATE_ALIVE = 0x0001,
-    JVMTI_THREAD_STATE_TERMINATED = 0x0002,
-    JVMTI_THREAD_STATE_RUNNABLE = 0x0004,
-    JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400,
-    JVMTI_THREAD_STATE_WAITING = 0x0080,
-    JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010,
-    JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020,
-    JVMTI_THREAD_STATE_SLEEPING = 0x0040,
-    JVMTI_THREAD_STATE_IN_OBJECT_WAIT = 0x0100,
-    JVMTI_THREAD_STATE_PARKED = 0x0200,
-    JVMTI_THREAD_STATE_SUSPENDED = 0x100000,
-    JVMTI_THREAD_STATE_INTERRUPTED = 0x200000,
-    JVMTI_THREAD_STATE_IN_NATIVE = 0x400000,
-    JVMTI_THREAD_STATE_VENDOR_1 = 0x10000000,
-    JVMTI_THREAD_STATE_VENDOR_2 = 0x20000000,
-    JVMTI_THREAD_STATE_VENDOR_3 = 0x40000000
-};
-
-    /* java.lang.Thread.State Conversion Masks */
-
-enum {
-    JVMTI_JAVA_LANG_THREAD_STATE_MASK = JVMTI_THREAD_STATE_TERMINATED | JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT,
-    JVMTI_JAVA_LANG_THREAD_STATE_NEW = 0,
-    JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED = JVMTI_THREAD_STATE_TERMINATED,
-    JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_RUNNABLE,
-    JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
-    JVMTI_JAVA_LANG_THREAD_STATE_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_INDEFINITELY,
-    JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING = JVMTI_THREAD_STATE_ALIVE | JVMTI_THREAD_STATE_WAITING | JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT
-};
-
-    /* Thread Priority Constants */
-
-enum {
-    JVMTI_THREAD_MIN_PRIORITY = 1,
-    JVMTI_THREAD_NORM_PRIORITY = 5,
-    JVMTI_THREAD_MAX_PRIORITY = 10
-};
-
-    /* Heap Filter Flags */
-
-enum {
-    JVMTI_HEAP_FILTER_TAGGED = 0x4,
-    JVMTI_HEAP_FILTER_UNTAGGED = 0x8,
-    JVMTI_HEAP_FILTER_CLASS_TAGGED = 0x10,
-    JVMTI_HEAP_FILTER_CLASS_UNTAGGED = 0x20
-};
-
-    /* Heap Visit Control Flags */
-
-enum {
-    JVMTI_VISIT_OBJECTS = 0x100,
-    JVMTI_VISIT_ABORT = 0x8000
-};
-
-    /* Heap Reference Enumeration */
-
-typedef enum {
-    JVMTI_HEAP_REFERENCE_CLASS = 1,
-    JVMTI_HEAP_REFERENCE_FIELD = 2,
-    JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT = 3,
-    JVMTI_HEAP_REFERENCE_CLASS_LOADER = 4,
-    JVMTI_HEAP_REFERENCE_SIGNERS = 5,
-    JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN = 6,
-    JVMTI_HEAP_REFERENCE_INTERFACE = 7,
-    JVMTI_HEAP_REFERENCE_STATIC_FIELD = 8,
-    JVMTI_HEAP_REFERENCE_CONSTANT_POOL = 9,
-    JVMTI_HEAP_REFERENCE_SUPERCLASS = 10,
-    JVMTI_HEAP_REFERENCE_JNI_GLOBAL = 21,
-    JVMTI_HEAP_REFERENCE_SYSTEM_CLASS = 22,
-    JVMTI_HEAP_REFERENCE_MONITOR = 23,
-    JVMTI_HEAP_REFERENCE_STACK_LOCAL = 24,
-    JVMTI_HEAP_REFERENCE_JNI_LOCAL = 25,
-    JVMTI_HEAP_REFERENCE_THREAD = 26,
-    JVMTI_HEAP_REFERENCE_OTHER = 27
-} jvmtiHeapReferenceKind;
-
-    /* Primitive Type Enumeration */
-
-typedef enum {
-    JVMTI_PRIMITIVE_TYPE_BOOLEAN = 90,
-    JVMTI_PRIMITIVE_TYPE_BYTE = 66,
-    JVMTI_PRIMITIVE_TYPE_CHAR = 67,
-    JVMTI_PRIMITIVE_TYPE_SHORT = 83,
-    JVMTI_PRIMITIVE_TYPE_INT = 73,
-    JVMTI_PRIMITIVE_TYPE_LONG = 74,
-    JVMTI_PRIMITIVE_TYPE_FLOAT = 70,
-    JVMTI_PRIMITIVE_TYPE_DOUBLE = 68
-} jvmtiPrimitiveType;
-
-    /* Heap Object Filter Enumeration */
-
-typedef enum {
-    JVMTI_HEAP_OBJECT_TAGGED = 1,
-    JVMTI_HEAP_OBJECT_UNTAGGED = 2,
-    JVMTI_HEAP_OBJECT_EITHER = 3
-} jvmtiHeapObjectFilter;
-
-    /* Heap Root Kind Enumeration */
-
-typedef enum {
-    JVMTI_HEAP_ROOT_JNI_GLOBAL = 1,
-    JVMTI_HEAP_ROOT_SYSTEM_CLASS = 2,
-    JVMTI_HEAP_ROOT_MONITOR = 3,
-    JVMTI_HEAP_ROOT_STACK_LOCAL = 4,
-    JVMTI_HEAP_ROOT_JNI_LOCAL = 5,
-    JVMTI_HEAP_ROOT_THREAD = 6,
-    JVMTI_HEAP_ROOT_OTHER = 7
-} jvmtiHeapRootKind;
-
-    /* Object Reference Enumeration */
-
-typedef enum {
-    JVMTI_REFERENCE_CLASS = 1,
-    JVMTI_REFERENCE_FIELD = 2,
-    JVMTI_REFERENCE_ARRAY_ELEMENT = 3,
-    JVMTI_REFERENCE_CLASS_LOADER = 4,
-    JVMTI_REFERENCE_SIGNERS = 5,
-    JVMTI_REFERENCE_PROTECTION_DOMAIN = 6,
-    JVMTI_REFERENCE_INTERFACE = 7,
-    JVMTI_REFERENCE_STATIC_FIELD = 8,
-    JVMTI_REFERENCE_CONSTANT_POOL = 9
-} jvmtiObjectReferenceKind;
-
-    /* Iteration Control Enumeration */
-
-typedef enum {
-    JVMTI_ITERATION_CONTINUE = 1,
-    JVMTI_ITERATION_IGNORE = 2,
-    JVMTI_ITERATION_ABORT = 0
-} jvmtiIterationControl;
-
-    /* Class Status Flags */
-
-enum {
-    JVMTI_CLASS_STATUS_VERIFIED = 1,
-    JVMTI_CLASS_STATUS_PREPARED = 2,
-    JVMTI_CLASS_STATUS_INITIALIZED = 4,
-    JVMTI_CLASS_STATUS_ERROR = 8,
-    JVMTI_CLASS_STATUS_ARRAY = 16,
-    JVMTI_CLASS_STATUS_PRIMITIVE = 32
-};
-
-    /* Event Enable/Disable */
-
-typedef enum {
-    JVMTI_ENABLE = 1,
-    JVMTI_DISABLE = 0
-} jvmtiEventMode;
-
-    /* Extension Function/Event Parameter Types */
-
-typedef enum {
-    JVMTI_TYPE_JBYTE = 101,
-    JVMTI_TYPE_JCHAR = 102,
-    JVMTI_TYPE_JSHORT = 103,
-    JVMTI_TYPE_JINT = 104,
-    JVMTI_TYPE_JLONG = 105,
-    JVMTI_TYPE_JFLOAT = 106,
-    JVMTI_TYPE_JDOUBLE = 107,
-    JVMTI_TYPE_JBOOLEAN = 108,
-    JVMTI_TYPE_JOBJECT = 109,
-    JVMTI_TYPE_JTHREAD = 110,
-    JVMTI_TYPE_JCLASS = 111,
-    JVMTI_TYPE_JVALUE = 112,
-    JVMTI_TYPE_JFIELDID = 113,
-    JVMTI_TYPE_JMETHODID = 114,
-    JVMTI_TYPE_CCHAR = 115,
-    JVMTI_TYPE_CVOID = 116,
-    JVMTI_TYPE_JNIENV = 117
-} jvmtiParamTypes;
-
-    /* Extension Function/Event Parameter Kinds */
-
-typedef enum {
-    JVMTI_KIND_IN = 91,
-    JVMTI_KIND_IN_PTR = 92,
-    JVMTI_KIND_IN_BUF = 93,
-    JVMTI_KIND_ALLOC_BUF = 94,
-    JVMTI_KIND_ALLOC_ALLOC_BUF = 95,
-    JVMTI_KIND_OUT = 96,
-    JVMTI_KIND_OUT_BUF = 97
-} jvmtiParamKind;
-
-    /* Timer Kinds */
-
-typedef enum {
-    JVMTI_TIMER_USER_CPU = 30,
-    JVMTI_TIMER_TOTAL_CPU = 31,
-    JVMTI_TIMER_ELAPSED = 32
-} jvmtiTimerKind;
-
-    /* Phases of execution */
-
-typedef enum {
-    JVMTI_PHASE_ONLOAD = 1,
-    JVMTI_PHASE_PRIMORDIAL = 2,
-    JVMTI_PHASE_START = 6,
-    JVMTI_PHASE_LIVE = 4,
-    JVMTI_PHASE_DEAD = 8
-} jvmtiPhase;
-
-    /* Version Interface Types */
-
-enum {
-    JVMTI_VERSION_INTERFACE_JNI = 0x00000000,
-    JVMTI_VERSION_INTERFACE_JVMTI = 0x30000000
-};
-
-    /* Version Masks */
-
-enum {
-    JVMTI_VERSION_MASK_INTERFACE_TYPE = 0x70000000,
-    JVMTI_VERSION_MASK_MAJOR = 0x0FFF0000,
-    JVMTI_VERSION_MASK_MINOR = 0x0000FF00,
-    JVMTI_VERSION_MASK_MICRO = 0x000000FF
-};
-
-    /* Version Shifts */
-
-enum {
-    JVMTI_VERSION_SHIFT_MAJOR = 16,
-    JVMTI_VERSION_SHIFT_MINOR = 8,
-    JVMTI_VERSION_SHIFT_MICRO = 0
-};
-
-    /* Verbose Flag Enumeration */
-
-typedef enum {
-    JVMTI_VERBOSE_OTHER = 0,
-    JVMTI_VERBOSE_GC = 1,
-    JVMTI_VERBOSE_CLASS = 2,
-    JVMTI_VERBOSE_JNI = 4
-} jvmtiVerboseFlag;
-
-    /* JLocation Format Enumeration */
-
-typedef enum {
-    JVMTI_JLOCATION_JVMBCI = 1,
-    JVMTI_JLOCATION_MACHINEPC = 2,
-    JVMTI_JLOCATION_OTHER = 0
-} jvmtiJlocationFormat;
-
-    /* Resource Exhaustion Flags */
-
-enum {
-    JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR = 0x0001,
-    JVMTI_RESOURCE_EXHAUSTED_JAVA_HEAP = 0x0002,
-    JVMTI_RESOURCE_EXHAUSTED_THREADS = 0x0004
-};
-
-    /* Errors */
-
-typedef enum {
-    JVMTI_ERROR_NONE = 0,
-    JVMTI_ERROR_INVALID_THREAD = 10,
-    JVMTI_ERROR_INVALID_THREAD_GROUP = 11,
-    JVMTI_ERROR_INVALID_PRIORITY = 12,
-    JVMTI_ERROR_THREAD_NOT_SUSPENDED = 13,
-    JVMTI_ERROR_THREAD_SUSPENDED = 14,
-    JVMTI_ERROR_THREAD_NOT_ALIVE = 15,
-    JVMTI_ERROR_INVALID_OBJECT = 20,
-    JVMTI_ERROR_INVALID_CLASS = 21,
-    JVMTI_ERROR_CLASS_NOT_PREPARED = 22,
-    JVMTI_ERROR_INVALID_METHODID = 23,
-    JVMTI_ERROR_INVALID_LOCATION = 24,
-    JVMTI_ERROR_INVALID_FIELDID = 25,
-    JVMTI_ERROR_NO_MORE_FRAMES = 31,
-    JVMTI_ERROR_OPAQUE_FRAME = 32,
-    JVMTI_ERROR_TYPE_MISMATCH = 34,
-    JVMTI_ERROR_INVALID_SLOT = 35,
-    JVMTI_ERROR_DUPLICATE = 40,
-    JVMTI_ERROR_NOT_FOUND = 41,
-    JVMTI_ERROR_INVALID_MONITOR = 50,
-    JVMTI_ERROR_NOT_MONITOR_OWNER = 51,
-    JVMTI_ERROR_INTERRUPT = 52,
-    JVMTI_ERROR_INVALID_CLASS_FORMAT = 60,
-    JVMTI_ERROR_CIRCULAR_CLASS_DEFINITION = 61,
-    JVMTI_ERROR_FAILS_VERIFICATION = 62,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_ADDED = 63,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_SCHEMA_CHANGED = 64,
-    JVMTI_ERROR_INVALID_TYPESTATE = 65,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED = 66,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_DELETED = 67,
-    JVMTI_ERROR_UNSUPPORTED_VERSION = 68,
-    JVMTI_ERROR_NAMES_DONT_MATCH = 69,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_CLASS_MODIFIERS_CHANGED = 70,
-    JVMTI_ERROR_UNSUPPORTED_REDEFINITION_METHOD_MODIFIERS_CHANGED = 71,
-    JVMTI_ERROR_UNMODIFIABLE_CLASS = 79,
-    JVMTI_ERROR_NOT_AVAILABLE = 98,
-    JVMTI_ERROR_MUST_POSSESS_CAPABILITY = 99,
-    JVMTI_ERROR_NULL_POINTER = 100,
-    JVMTI_ERROR_ABSENT_INFORMATION = 101,
-    JVMTI_ERROR_INVALID_EVENT_TYPE = 102,
-    JVMTI_ERROR_ILLEGAL_ARGUMENT = 103,
-    JVMTI_ERROR_NATIVE_METHOD = 104,
-    JVMTI_ERROR_CLASS_LOADER_UNSUPPORTED = 106,
-    JVMTI_ERROR_OUT_OF_MEMORY = 110,
-    JVMTI_ERROR_ACCESS_DENIED = 111,
-    JVMTI_ERROR_WRONG_PHASE = 112,
-    JVMTI_ERROR_INTERNAL = 113,
-    JVMTI_ERROR_UNATTACHED_THREAD = 115,
-    JVMTI_ERROR_INVALID_ENVIRONMENT = 116,
-    JVMTI_ERROR_MAX = 116
-} jvmtiError;
-
-    /* Event IDs */
-
-typedef enum {
-    JVMTI_MIN_EVENT_TYPE_VAL = 50,
-    JVMTI_EVENT_VM_INIT = 50,
-    JVMTI_EVENT_VM_DEATH = 51,
-    JVMTI_EVENT_THREAD_START = 52,
-    JVMTI_EVENT_THREAD_END = 53,
-    JVMTI_EVENT_CLASS_FILE_LOAD_HOOK = 54,
-    JVMTI_EVENT_CLASS_LOAD = 55,
-    JVMTI_EVENT_CLASS_PREPARE = 56,
-    JVMTI_EVENT_VM_START = 57,
-    JVMTI_EVENT_EXCEPTION = 58,
-    JVMTI_EVENT_EXCEPTION_CATCH = 59,
-    JVMTI_EVENT_SINGLE_STEP = 60,
-    JVMTI_EVENT_FRAME_POP = 61,
-    JVMTI_EVENT_BREAKPOINT = 62,
-    JVMTI_EVENT_FIELD_ACCESS = 63,
-    JVMTI_EVENT_FIELD_MODIFICATION = 64,
-    JVMTI_EVENT_METHOD_ENTRY = 65,
-    JVMTI_EVENT_METHOD_EXIT = 66,
-    JVMTI_EVENT_NATIVE_METHOD_BIND = 67,
-    JVMTI_EVENT_COMPILED_METHOD_LOAD = 68,
-    JVMTI_EVENT_COMPILED_METHOD_UNLOAD = 69,
-    JVMTI_EVENT_DYNAMIC_CODE_GENERATED = 70,
-    JVMTI_EVENT_DATA_DUMP_REQUEST = 71,
-    JVMTI_EVENT_MONITOR_WAIT = 73,
-    JVMTI_EVENT_MONITOR_WAITED = 74,
-    JVMTI_EVENT_MONITOR_CONTENDED_ENTER = 75,
-    JVMTI_EVENT_MONITOR_CONTENDED_ENTERED = 76,
-    JVMTI_EVENT_RESOURCE_EXHAUSTED = 80,
-    JVMTI_EVENT_GARBAGE_COLLECTION_START = 81,
-    JVMTI_EVENT_GARBAGE_COLLECTION_FINISH = 82,
-    JVMTI_EVENT_OBJECT_FREE = 83,
-    JVMTI_EVENT_VM_OBJECT_ALLOC = 84,
-    JVMTI_MAX_EVENT_TYPE_VAL = 84
-} jvmtiEvent;
-
-
-    /* Pre-Declarations */
-struct _jvmtiThreadInfo;
-typedef struct _jvmtiThreadInfo jvmtiThreadInfo;
-struct _jvmtiMonitorStackDepthInfo;
-typedef struct _jvmtiMonitorStackDepthInfo jvmtiMonitorStackDepthInfo;
-struct _jvmtiThreadGroupInfo;
-typedef struct _jvmtiThreadGroupInfo jvmtiThreadGroupInfo;
-struct _jvmtiFrameInfo;
-typedef struct _jvmtiFrameInfo jvmtiFrameInfo;
-struct _jvmtiStackInfo;
-typedef struct _jvmtiStackInfo jvmtiStackInfo;
-struct _jvmtiHeapReferenceInfoField;
-typedef struct _jvmtiHeapReferenceInfoField jvmtiHeapReferenceInfoField;
-struct _jvmtiHeapReferenceInfoArray;
-typedef struct _jvmtiHeapReferenceInfoArray jvmtiHeapReferenceInfoArray;
-struct _jvmtiHeapReferenceInfoConstantPool;
-typedef struct _jvmtiHeapReferenceInfoConstantPool jvmtiHeapReferenceInfoConstantPool;
-struct _jvmtiHeapReferenceInfoStackLocal;
-typedef struct _jvmtiHeapReferenceInfoStackLocal jvmtiHeapReferenceInfoStackLocal;
-struct _jvmtiHeapReferenceInfoJniLocal;
-typedef struct _jvmtiHeapReferenceInfoJniLocal jvmtiHeapReferenceInfoJniLocal;
-struct _jvmtiHeapReferenceInfoReserved;
-typedef struct _jvmtiHeapReferenceInfoReserved jvmtiHeapReferenceInfoReserved;
-union _jvmtiHeapReferenceInfo;
-typedef union _jvmtiHeapReferenceInfo jvmtiHeapReferenceInfo;
-struct _jvmtiHeapCallbacks;
-typedef struct _jvmtiHeapCallbacks jvmtiHeapCallbacks;
-struct _jvmtiClassDefinition;
-typedef struct _jvmtiClassDefinition jvmtiClassDefinition;
-struct _jvmtiMonitorUsage;
-typedef struct _jvmtiMonitorUsage jvmtiMonitorUsage;
-struct _jvmtiLineNumberEntry;
-typedef struct _jvmtiLineNumberEntry jvmtiLineNumberEntry;
-struct _jvmtiLocalVariableEntry;
-typedef struct _jvmtiLocalVariableEntry jvmtiLocalVariableEntry;
-struct _jvmtiParamInfo;
-typedef struct _jvmtiParamInfo jvmtiParamInfo;
-struct _jvmtiExtensionFunctionInfo;
-typedef struct _jvmtiExtensionFunctionInfo jvmtiExtensionFunctionInfo;
-struct _jvmtiExtensionEventInfo;
-typedef struct _jvmtiExtensionEventInfo jvmtiExtensionEventInfo;
-struct _jvmtiTimerInfo;
-typedef struct _jvmtiTimerInfo jvmtiTimerInfo;
-struct _jvmtiAddrLocationMap;
-typedef struct _jvmtiAddrLocationMap jvmtiAddrLocationMap;
-
-    /* Function Types */
-
-typedef void (JNICALL *jvmtiStartFunction)
-    (jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
-
-typedef jint (JNICALL *jvmtiHeapIterationCallback)
-    (jlong class_tag, jlong size, jlong* tag_ptr, jint length, void* user_data);
-
-typedef jint (JNICALL *jvmtiHeapReferenceCallback)
-    (jvmtiHeapReferenceKind reference_kind, const jvmtiHeapReferenceInfo* reference_info, jlong class_tag, jlong referrer_class_tag, jlong size, jlong* tag_ptr, jlong* referrer_tag_ptr, jint length, void* user_data);
-
-typedef jint (JNICALL *jvmtiPrimitiveFieldCallback)
-    (jvmtiHeapReferenceKind kind, const jvmtiHeapReferenceInfo* info, jlong object_class_tag, jlong* object_tag_ptr, jvalue value, jvmtiPrimitiveType value_type, void* user_data);
-
-typedef jint (JNICALL *jvmtiArrayPrimitiveValueCallback)
-    (jlong class_tag, jlong size, jlong* tag_ptr, jint element_count, jvmtiPrimitiveType element_type, const void* elements, void* user_data);
-
-typedef jint (JNICALL *jvmtiStringPrimitiveValueCallback)
-    (jlong class_tag, jlong size, jlong* tag_ptr, const jchar* value, jint value_length, void* user_data);
-
-typedef jint (JNICALL *jvmtiReservedCallback)
-    ();
-
-typedef jvmtiIterationControl (JNICALL *jvmtiHeapObjectCallback)
-    (jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
-
-typedef jvmtiIterationControl (JNICALL *jvmtiHeapRootCallback)
-    (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, void* user_data);
-
-typedef jvmtiIterationControl (JNICALL *jvmtiStackReferenceCallback)
-    (jvmtiHeapRootKind root_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong thread_tag, jint depth, jmethodID method, jint slot, void* user_data);
-
-typedef jvmtiIterationControl (JNICALL *jvmtiObjectReferenceCallback)
-    (jvmtiObjectReferenceKind reference_kind, jlong class_tag, jlong size, jlong* tag_ptr, jlong referrer_tag, jint referrer_index, void* user_data);
-
-typedef jvmtiError (JNICALL *jvmtiExtensionFunction)
-    (jvmtiEnv* jvmti_env,  ...);
-
-typedef void (JNICALL *jvmtiExtensionEvent)
-    (jvmtiEnv* jvmti_env,  ...);
-
-
-    /* Structure Types */
-struct _jvmtiThreadInfo {
-    char* name;
-    jint priority;
-    jboolean is_daemon;
-    jthreadGroup thread_group;
-    jobject context_class_loader;
-};
-struct _jvmtiMonitorStackDepthInfo {
-    jobject monitor;
-    jint stack_depth;
-};
-struct _jvmtiThreadGroupInfo {
-    jthreadGroup parent;
-    char* name;
-    jint max_priority;
-    jboolean is_daemon;
-};
-struct _jvmtiFrameInfo {
-    jmethodID method;
-    jlocation location;
-};
-struct _jvmtiStackInfo {
-    jthread thread;
-    jint state;
-    jvmtiFrameInfo* frame_buffer;
-    jint frame_count;
-};
-struct _jvmtiHeapReferenceInfoField {
-    jint index;
-};
-struct _jvmtiHeapReferenceInfoArray {
-    jint index;
-};
-struct _jvmtiHeapReferenceInfoConstantPool {
-    jint index;
-};
-struct _jvmtiHeapReferenceInfoStackLocal {
-    jlong thread_tag;
-    jlong thread_id;
-    jint depth;
-    jmethodID method;
-    jlocation location;
-    jint slot;
-};
-struct _jvmtiHeapReferenceInfoJniLocal {
-    jlong thread_tag;
-    jlong thread_id;
-    jint depth;
-    jmethodID method;
-};
-struct _jvmtiHeapReferenceInfoReserved {
-    jlong reserved1;
-    jlong reserved2;
-    jlong reserved3;
-    jlong reserved4;
-    jlong reserved5;
-    jlong reserved6;
-    jlong reserved7;
-    jlong reserved8;
-};
-union _jvmtiHeapReferenceInfo {
-    jvmtiHeapReferenceInfoField field;
-    jvmtiHeapReferenceInfoArray array;
-    jvmtiHeapReferenceInfoConstantPool constant_pool;
-    jvmtiHeapReferenceInfoStackLocal stack_local;
-    jvmtiHeapReferenceInfoJniLocal jni_local;
-    jvmtiHeapReferenceInfoReserved other;
-};
-struct _jvmtiHeapCallbacks {
-    jvmtiHeapIterationCallback heap_iteration_callback;
-    jvmtiHeapReferenceCallback heap_reference_callback;
-    jvmtiPrimitiveFieldCallback primitive_field_callback;
-    jvmtiArrayPrimitiveValueCallback array_primitive_value_callback;
-    jvmtiStringPrimitiveValueCallback string_primitive_value_callback;
-    jvmtiReservedCallback reserved5;
-    jvmtiReservedCallback reserved6;
-    jvmtiReservedCallback reserved7;
-    jvmtiReservedCallback reserved8;
-    jvmtiReservedCallback reserved9;
-    jvmtiReservedCallback reserved10;
-    jvmtiReservedCallback reserved11;
-    jvmtiReservedCallback reserved12;
-    jvmtiReservedCallback reserved13;
-    jvmtiReservedCallback reserved14;
-    jvmtiReservedCallback reserved15;
-};
-struct _jvmtiClassDefinition {
-    jclass klass;
-    jint class_byte_count;
-    const unsigned char* class_bytes;
-};
-struct _jvmtiMonitorUsage {
-    jthread owner;
-    jint entry_count;
-    jint waiter_count;
-    jthread* waiters;
-    jint notify_waiter_count;
-    jthread* notify_waiters;
-};
-struct _jvmtiLineNumberEntry {
-    jlocation start_location;
-    jint line_number;
-};
-struct _jvmtiLocalVariableEntry {
-    jlocation start_location;
-    jint length;
-    char* name;
-    char* signature;
-    char* generic_signature;
-    jint slot;
-};
-struct _jvmtiParamInfo {
-    char* name;
-    jvmtiParamKind kind;
-    jvmtiParamTypes base_type;
-    jboolean null_ok;
-};
-struct _jvmtiExtensionFunctionInfo {
-    jvmtiExtensionFunction func;
-    char* id;
-    char* short_description;
-    jint param_count;
-    jvmtiParamInfo* params;
-    jint error_count;
-    jvmtiError* errors;
-};
-struct _jvmtiExtensionEventInfo {
-    jint extension_event_index;
-    char* id;
-    char* short_description;
-    jint param_count;
-    jvmtiParamInfo* params;
-};
-struct _jvmtiTimerInfo {
-    jlong max_value;
-    jboolean may_skip_forward;
-    jboolean may_skip_backward;
-    jvmtiTimerKind kind;
-    jlong reserved1;
-    jlong reserved2;
-};
-struct _jvmtiAddrLocationMap {
-    const void* start_address;
-    jlocation location;
-};
-
-typedef struct {
-    unsigned int can_tag_objects : 1;
-    unsigned int can_generate_field_modification_events : 1;
-    unsigned int can_generate_field_access_events : 1;
-    unsigned int can_get_bytecodes : 1;
-    unsigned int can_get_synthetic_attribute : 1;
-    unsigned int can_get_owned_monitor_info : 1;
-    unsigned int can_get_current_contended_monitor : 1;
-    unsigned int can_get_monitor_info : 1;
-    unsigned int can_pop_frame : 1;
-    unsigned int can_redefine_classes : 1;
-    unsigned int can_signal_thread : 1;
-    unsigned int can_get_source_file_name : 1;
-    unsigned int can_get_line_numbers : 1;
-    unsigned int can_get_source_debug_extension : 1;
-    unsigned int can_access_local_variables : 1;
-    unsigned int can_maintain_original_method_order : 1;
-    unsigned int can_generate_single_step_events : 1;
-    unsigned int can_generate_exception_events : 1;
-    unsigned int can_generate_frame_pop_events : 1;
-    unsigned int can_generate_breakpoint_events : 1;
-    unsigned int can_suspend : 1;
-    unsigned int can_redefine_any_class : 1;
-    unsigned int can_get_current_thread_cpu_time : 1;
-    unsigned int can_get_thread_cpu_time : 1;
-    unsigned int can_generate_method_entry_events : 1;
-    unsigned int can_generate_method_exit_events : 1;
-    unsigned int can_generate_all_class_hook_events : 1;
-    unsigned int can_generate_compiled_method_load_events : 1;
-    unsigned int can_generate_monitor_events : 1;
-    unsigned int can_generate_vm_object_alloc_events : 1;
-    unsigned int can_generate_native_method_bind_events : 1;
-    unsigned int can_generate_garbage_collection_events : 1;
-    unsigned int can_generate_object_free_events : 1;
-    unsigned int can_force_early_return : 1;
-    unsigned int can_get_owned_monitor_stack_depth_info : 1;
-    unsigned int can_get_constant_pool : 1;
-    unsigned int can_set_native_method_prefix : 1;
-    unsigned int can_retransform_classes : 1;
-    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 can_generate_early_vmstart : 1;
-    unsigned int can_generate_early_class_hook_events : 1;
-    unsigned int : 5;
-    unsigned int : 16;
-    unsigned int : 16;
-    unsigned int : 16;
-    unsigned int : 16;
-    unsigned int : 16;
-} jvmtiCapabilities;
-
-
-    /* Event Definitions */
-
-typedef void (JNICALL *jvmtiEventReserved)(void);
-
-
-typedef void (JNICALL *jvmtiEventBreakpoint)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location);
-
-typedef void (JNICALL *jvmtiEventClassFileLoadHook)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jclass class_being_redefined,
-     jobject loader,
-     const char* name,
-     jobject protection_domain,
-     jint class_data_len,
-     const unsigned char* class_data,
-     jint* new_class_data_len,
-     unsigned char** new_class_data);
-
-typedef void (JNICALL *jvmtiEventClassLoad)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jclass klass);
-
-typedef void (JNICALL *jvmtiEventClassPrepare)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jclass klass);
-
-typedef void (JNICALL *jvmtiEventCompiledMethodLoad)
-    (jvmtiEnv *jvmti_env,
-     jmethodID method,
-     jint code_size,
-     const void* code_addr,
-     jint map_length,
-     const jvmtiAddrLocationMap* map,
-     const void* compile_info);
-
-typedef void (JNICALL *jvmtiEventCompiledMethodUnload)
-    (jvmtiEnv *jvmti_env,
-     jmethodID method,
-     const void* code_addr);
-
-typedef void (JNICALL *jvmtiEventDataDumpRequest)
-    (jvmtiEnv *jvmti_env);
-
-typedef void (JNICALL *jvmtiEventDynamicCodeGenerated)
-    (jvmtiEnv *jvmti_env,
-     const char* name,
-     const void* address,
-     jint length);
-
-typedef void (JNICALL *jvmtiEventException)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location,
-     jobject exception,
-     jmethodID catch_method,
-     jlocation catch_location);
-
-typedef void (JNICALL *jvmtiEventExceptionCatch)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location,
-     jobject exception);
-
-typedef void (JNICALL *jvmtiEventFieldAccess)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location,
-     jclass field_klass,
-     jobject object,
-     jfieldID field);
-
-typedef void (JNICALL *jvmtiEventFieldModification)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location,
-     jclass field_klass,
-     jobject object,
-     jfieldID field,
-     char signature_type,
-     jvalue new_value);
-
-typedef void (JNICALL *jvmtiEventFramePop)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jboolean was_popped_by_exception);
-
-typedef void (JNICALL *jvmtiEventGarbageCollectionFinish)
-    (jvmtiEnv *jvmti_env);
-
-typedef void (JNICALL *jvmtiEventGarbageCollectionStart)
-    (jvmtiEnv *jvmti_env);
-
-typedef void (JNICALL *jvmtiEventMethodEntry)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method);
-
-typedef void (JNICALL *jvmtiEventMethodExit)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jboolean was_popped_by_exception,
-     jvalue return_value);
-
-typedef void (JNICALL *jvmtiEventMonitorContendedEnter)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jobject object);
-
-typedef void (JNICALL *jvmtiEventMonitorContendedEntered)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jobject object);
-
-typedef void (JNICALL *jvmtiEventMonitorWait)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jobject object,
-     jlong timeout);
-
-typedef void (JNICALL *jvmtiEventMonitorWaited)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jobject object,
-     jboolean timed_out);
-
-typedef void (JNICALL *jvmtiEventNativeMethodBind)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     void* address,
-     void** new_address_ptr);
-
-typedef void (JNICALL *jvmtiEventObjectFree)
-    (jvmtiEnv *jvmti_env,
-     jlong tag);
-
-typedef void (JNICALL *jvmtiEventResourceExhausted)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jint flags,
-     const void* reserved,
-     const char* description);
-
-typedef void (JNICALL *jvmtiEventSingleStep)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jmethodID method,
-     jlocation location);
-
-typedef void (JNICALL *jvmtiEventThreadEnd)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread);
-
-typedef void (JNICALL *jvmtiEventThreadStart)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread);
-
-typedef void (JNICALL *jvmtiEventVMDeath)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env);
-
-typedef void (JNICALL *jvmtiEventVMInit)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread);
-
-typedef void (JNICALL *jvmtiEventVMObjectAlloc)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env,
-     jthread thread,
-     jobject object,
-     jclass object_klass,
-     jlong size);
-
-typedef void (JNICALL *jvmtiEventVMStart)
-    (jvmtiEnv *jvmti_env,
-     JNIEnv* jni_env);
-
-    /* Event Callback Structure */
-
-typedef struct {
-                              /*   50 : VM Initialization Event */
-    jvmtiEventVMInit VMInit;
-                              /*   51 : VM Death Event */
-    jvmtiEventVMDeath VMDeath;
-                              /*   52 : Thread Start */
-    jvmtiEventThreadStart ThreadStart;
-                              /*   53 : Thread End */
-    jvmtiEventThreadEnd ThreadEnd;
-                              /*   54 : Class File Load Hook */
-    jvmtiEventClassFileLoadHook ClassFileLoadHook;
-                              /*   55 : Class Load */
-    jvmtiEventClassLoad ClassLoad;
-                              /*   56 : Class Prepare */
-    jvmtiEventClassPrepare ClassPrepare;
-                              /*   57 : VM Start Event */
-    jvmtiEventVMStart VMStart;
-                              /*   58 : Exception */
-    jvmtiEventException Exception;
-                              /*   59 : Exception Catch */
-    jvmtiEventExceptionCatch ExceptionCatch;
-                              /*   60 : Single Step */
-    jvmtiEventSingleStep SingleStep;
-                              /*   61 : Frame Pop */
-    jvmtiEventFramePop FramePop;
-                              /*   62 : Breakpoint */
-    jvmtiEventBreakpoint Breakpoint;
-                              /*   63 : Field Access */
-    jvmtiEventFieldAccess FieldAccess;
-                              /*   64 : Field Modification */
-    jvmtiEventFieldModification FieldModification;
-                              /*   65 : Method Entry */
-    jvmtiEventMethodEntry MethodEntry;
-                              /*   66 : Method Exit */
-    jvmtiEventMethodExit MethodExit;
-                              /*   67 : Native Method Bind */
-    jvmtiEventNativeMethodBind NativeMethodBind;
-                              /*   68 : Compiled Method Load */
-    jvmtiEventCompiledMethodLoad CompiledMethodLoad;
-                              /*   69 : Compiled Method Unload */
-    jvmtiEventCompiledMethodUnload CompiledMethodUnload;
-                              /*   70 : Dynamic Code Generated */
-    jvmtiEventDynamicCodeGenerated DynamicCodeGenerated;
-                              /*   71 : Data Dump Request */
-    jvmtiEventDataDumpRequest DataDumpRequest;
-                              /*   72 */
-    jvmtiEventReserved reserved72;
-                              /*   73 : Monitor Wait */
-    jvmtiEventMonitorWait MonitorWait;
-                              /*   74 : Monitor Waited */
-    jvmtiEventMonitorWaited MonitorWaited;
-                              /*   75 : Monitor Contended Enter */
-    jvmtiEventMonitorContendedEnter MonitorContendedEnter;
-                              /*   76 : Monitor Contended Entered */
-    jvmtiEventMonitorContendedEntered MonitorContendedEntered;
-                              /*   77 */
-    jvmtiEventReserved reserved77;
-                              /*   78 */
-    jvmtiEventReserved reserved78;
-                              /*   79 */
-    jvmtiEventReserved reserved79;
-                              /*   80 : Resource Exhausted */
-    jvmtiEventResourceExhausted ResourceExhausted;
-                              /*   81 : Garbage Collection Start */
-    jvmtiEventGarbageCollectionStart GarbageCollectionStart;
-                              /*   82 : Garbage Collection Finish */
-    jvmtiEventGarbageCollectionFinish GarbageCollectionFinish;
-                              /*   83 : Object Free */
-    jvmtiEventObjectFree ObjectFree;
-                              /*   84 : VM Object Allocation */
-    jvmtiEventVMObjectAlloc VMObjectAlloc;
-} jvmtiEventCallbacks;
-
-
-    /* Function Interface */
-
-typedef struct jvmtiInterface_1_ {
-
-  /*   1 :  RESERVED */
-  void *reserved1;
-
-  /*   2 : Set Event Notification Mode */
-  jvmtiError (JNICALL *SetEventNotificationMode) (jvmtiEnv* env,
-    jvmtiEventMode mode,
-    jvmtiEvent event_type,
-    jthread event_thread,
-     ...);
-
-  /*   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,
-    jint* threads_count_ptr,
-    jthread** threads_ptr);
-
-  /*   5 : Suspend Thread */
-  jvmtiError (JNICALL *SuspendThread) (jvmtiEnv* env,
-    jthread thread);
-
-  /*   6 : Resume Thread */
-  jvmtiError (JNICALL *ResumeThread) (jvmtiEnv* env,
-    jthread thread);
-
-  /*   7 : Stop Thread */
-  jvmtiError (JNICALL *StopThread) (jvmtiEnv* env,
-    jthread thread,
-    jobject exception);
-
-  /*   8 : Interrupt Thread */
-  jvmtiError (JNICALL *InterruptThread) (jvmtiEnv* env,
-    jthread thread);
-
-  /*   9 : Get Thread Info */
-  jvmtiError (JNICALL *GetThreadInfo) (jvmtiEnv* env,
-    jthread thread,
-    jvmtiThreadInfo* info_ptr);
-
-  /*   10 : Get Owned Monitor Info */
-  jvmtiError (JNICALL *GetOwnedMonitorInfo) (jvmtiEnv* env,
-    jthread thread,
-    jint* owned_monitor_count_ptr,
-    jobject** owned_monitors_ptr);
-
-  /*   11 : Get Current Contended Monitor */
-  jvmtiError (JNICALL *GetCurrentContendedMonitor) (jvmtiEnv* env,
-    jthread thread,
-    jobject* monitor_ptr);
-
-  /*   12 : Run Agent Thread */
-  jvmtiError (JNICALL *RunAgentThread) (jvmtiEnv* env,
-    jthread thread,
-    jvmtiStartFunction proc,
-    const void* arg,
-    jint priority);
-
-  /*   13 : Get Top Thread Groups */
-  jvmtiError (JNICALL *GetTopThreadGroups) (jvmtiEnv* env,
-    jint* group_count_ptr,
-    jthreadGroup** groups_ptr);
-
-  /*   14 : Get Thread Group Info */
-  jvmtiError (JNICALL *GetThreadGroupInfo) (jvmtiEnv* env,
-    jthreadGroup group,
-    jvmtiThreadGroupInfo* info_ptr);
-
-  /*   15 : Get Thread Group Children */
-  jvmtiError (JNICALL *GetThreadGroupChildren) (jvmtiEnv* env,
-    jthreadGroup group,
-    jint* thread_count_ptr,
-    jthread** threads_ptr,
-    jint* group_count_ptr,
-    jthreadGroup** groups_ptr);
-
-  /*   16 : Get Frame Count */
-  jvmtiError (JNICALL *GetFrameCount) (jvmtiEnv* env,
-    jthread thread,
-    jint* count_ptr);
-
-  /*   17 : Get Thread State */
-  jvmtiError (JNICALL *GetThreadState) (jvmtiEnv* env,
-    jthread thread,
-    jint* thread_state_ptr);
-
-  /*   18 : Get Current Thread */
-  jvmtiError (JNICALL *GetCurrentThread) (jvmtiEnv* env,
-    jthread* thread_ptr);
-
-  /*   19 : Get Frame Location */
-  jvmtiError (JNICALL *GetFrameLocation) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jmethodID* method_ptr,
-    jlocation* location_ptr);
-
-  /*   20 : Notify Frame Pop */
-  jvmtiError (JNICALL *NotifyFramePop) (jvmtiEnv* env,
-    jthread thread,
-    jint depth);
-
-  /*   21 : Get Local Variable - Object */
-  jvmtiError (JNICALL *GetLocalObject) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jobject* value_ptr);
-
-  /*   22 : Get Local Variable - Int */
-  jvmtiError (JNICALL *GetLocalInt) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jint* value_ptr);
-
-  /*   23 : Get Local Variable - Long */
-  jvmtiError (JNICALL *GetLocalLong) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jlong* value_ptr);
-
-  /*   24 : Get Local Variable - Float */
-  jvmtiError (JNICALL *GetLocalFloat) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jfloat* value_ptr);
-
-  /*   25 : Get Local Variable - Double */
-  jvmtiError (JNICALL *GetLocalDouble) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jdouble* value_ptr);
-
-  /*   26 : Set Local Variable - Object */
-  jvmtiError (JNICALL *SetLocalObject) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jobject value);
-
-  /*   27 : Set Local Variable - Int */
-  jvmtiError (JNICALL *SetLocalInt) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jint value);
-
-  /*   28 : Set Local Variable - Long */
-  jvmtiError (JNICALL *SetLocalLong) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jlong value);
-
-  /*   29 : Set Local Variable - Float */
-  jvmtiError (JNICALL *SetLocalFloat) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jfloat value);
-
-  /*   30 : Set Local Variable - Double */
-  jvmtiError (JNICALL *SetLocalDouble) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jint slot,
-    jdouble value);
-
-  /*   31 : Create Raw Monitor */
-  jvmtiError (JNICALL *CreateRawMonitor) (jvmtiEnv* env,
-    const char* name,
-    jrawMonitorID* monitor_ptr);
-
-  /*   32 : Destroy Raw Monitor */
-  jvmtiError (JNICALL *DestroyRawMonitor) (jvmtiEnv* env,
-    jrawMonitorID monitor);
-
-  /*   33 : Raw Monitor Enter */
-  jvmtiError (JNICALL *RawMonitorEnter) (jvmtiEnv* env,
-    jrawMonitorID monitor);
-
-  /*   34 : Raw Monitor Exit */
-  jvmtiError (JNICALL *RawMonitorExit) (jvmtiEnv* env,
-    jrawMonitorID monitor);
-
-  /*   35 : Raw Monitor Wait */
-  jvmtiError (JNICALL *RawMonitorWait) (jvmtiEnv* env,
-    jrawMonitorID monitor,
-    jlong millis);
-
-  /*   36 : Raw Monitor Notify */
-  jvmtiError (JNICALL *RawMonitorNotify) (jvmtiEnv* env,
-    jrawMonitorID monitor);
-
-  /*   37 : Raw Monitor Notify All */
-  jvmtiError (JNICALL *RawMonitorNotifyAll) (jvmtiEnv* env,
-    jrawMonitorID monitor);
-
-  /*   38 : Set Breakpoint */
-  jvmtiError (JNICALL *SetBreakpoint) (jvmtiEnv* env,
-    jmethodID method,
-    jlocation location);
-
-  /*   39 : Clear Breakpoint */
-  jvmtiError (JNICALL *ClearBreakpoint) (jvmtiEnv* env,
-    jmethodID method,
-    jlocation location);
-
-  /*   40 : Get Named Module */
-  jvmtiError (JNICALL *GetNamedModule) (jvmtiEnv* env,
-    jobject class_loader,
-    const char* package_name,
-    jobject* module_ptr);
-
-  /*   41 : Set Field Access Watch */
-  jvmtiError (JNICALL *SetFieldAccessWatch) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field);
-
-  /*   42 : Clear Field Access Watch */
-  jvmtiError (JNICALL *ClearFieldAccessWatch) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field);
-
-  /*   43 : Set Field Modification Watch */
-  jvmtiError (JNICALL *SetFieldModificationWatch) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field);
-
-  /*   44 : Clear Field Modification Watch */
-  jvmtiError (JNICALL *ClearFieldModificationWatch) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field);
-
-  /*   45 : Is Modifiable Class */
-  jvmtiError (JNICALL *IsModifiableClass) (jvmtiEnv* env,
-    jclass klass,
-    jboolean* is_modifiable_class_ptr);
-
-  /*   46 : Allocate */
-  jvmtiError (JNICALL *Allocate) (jvmtiEnv* env,
-    jlong size,
-    unsigned char** mem_ptr);
-
-  /*   47 : Deallocate */
-  jvmtiError (JNICALL *Deallocate) (jvmtiEnv* env,
-    unsigned char* mem);
-
-  /*   48 : Get Class Signature */
-  jvmtiError (JNICALL *GetClassSignature) (jvmtiEnv* env,
-    jclass klass,
-    char** signature_ptr,
-    char** generic_ptr);
-
-  /*   49 : Get Class Status */
-  jvmtiError (JNICALL *GetClassStatus) (jvmtiEnv* env,
-    jclass klass,
-    jint* status_ptr);
-
-  /*   50 : Get Source File Name */
-  jvmtiError (JNICALL *GetSourceFileName) (jvmtiEnv* env,
-    jclass klass,
-    char** source_name_ptr);
-
-  /*   51 : Get Class Modifiers */
-  jvmtiError (JNICALL *GetClassModifiers) (jvmtiEnv* env,
-    jclass klass,
-    jint* modifiers_ptr);
-
-  /*   52 : Get Class Methods */
-  jvmtiError (JNICALL *GetClassMethods) (jvmtiEnv* env,
-    jclass klass,
-    jint* method_count_ptr,
-    jmethodID** methods_ptr);
-
-  /*   53 : Get Class Fields */
-  jvmtiError (JNICALL *GetClassFields) (jvmtiEnv* env,
-    jclass klass,
-    jint* field_count_ptr,
-    jfieldID** fields_ptr);
-
-  /*   54 : Get Implemented Interfaces */
-  jvmtiError (JNICALL *GetImplementedInterfaces) (jvmtiEnv* env,
-    jclass klass,
-    jint* interface_count_ptr,
-    jclass** interfaces_ptr);
-
-  /*   55 : Is Interface */
-  jvmtiError (JNICALL *IsInterface) (jvmtiEnv* env,
-    jclass klass,
-    jboolean* is_interface_ptr);
-
-  /*   56 : Is Array Class */
-  jvmtiError (JNICALL *IsArrayClass) (jvmtiEnv* env,
-    jclass klass,
-    jboolean* is_array_class_ptr);
-
-  /*   57 : Get Class Loader */
-  jvmtiError (JNICALL *GetClassLoader) (jvmtiEnv* env,
-    jclass klass,
-    jobject* classloader_ptr);
-
-  /*   58 : Get Object Hash Code */
-  jvmtiError (JNICALL *GetObjectHashCode) (jvmtiEnv* env,
-    jobject object,
-    jint* hash_code_ptr);
-
-  /*   59 : Get Object Monitor Usage */
-  jvmtiError (JNICALL *GetObjectMonitorUsage) (jvmtiEnv* env,
-    jobject object,
-    jvmtiMonitorUsage* info_ptr);
-
-  /*   60 : Get Field Name (and Signature) */
-  jvmtiError (JNICALL *GetFieldName) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field,
-    char** name_ptr,
-    char** signature_ptr,
-    char** generic_ptr);
-
-  /*   61 : Get Field Declaring Class */
-  jvmtiError (JNICALL *GetFieldDeclaringClass) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field,
-    jclass* declaring_class_ptr);
-
-  /*   62 : Get Field Modifiers */
-  jvmtiError (JNICALL *GetFieldModifiers) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field,
-    jint* modifiers_ptr);
-
-  /*   63 : Is Field Synthetic */
-  jvmtiError (JNICALL *IsFieldSynthetic) (jvmtiEnv* env,
-    jclass klass,
-    jfieldID field,
-    jboolean* is_synthetic_ptr);
-
-  /*   64 : Get Method Name (and Signature) */
-  jvmtiError (JNICALL *GetMethodName) (jvmtiEnv* env,
-    jmethodID method,
-    char** name_ptr,
-    char** signature_ptr,
-    char** generic_ptr);
-
-  /*   65 : Get Method Declaring Class */
-  jvmtiError (JNICALL *GetMethodDeclaringClass) (jvmtiEnv* env,
-    jmethodID method,
-    jclass* declaring_class_ptr);
-
-  /*   66 : Get Method Modifiers */
-  jvmtiError (JNICALL *GetMethodModifiers) (jvmtiEnv* env,
-    jmethodID method,
-    jint* modifiers_ptr);
-
-  /*   67 :  RESERVED */
-  void *reserved67;
-
-  /*   68 : Get Max Locals */
-  jvmtiError (JNICALL *GetMaxLocals) (jvmtiEnv* env,
-    jmethodID method,
-    jint* max_ptr);
-
-  /*   69 : Get Arguments Size */
-  jvmtiError (JNICALL *GetArgumentsSize) (jvmtiEnv* env,
-    jmethodID method,
-    jint* size_ptr);
-
-  /*   70 : Get Line Number Table */
-  jvmtiError (JNICALL *GetLineNumberTable) (jvmtiEnv* env,
-    jmethodID method,
-    jint* entry_count_ptr,
-    jvmtiLineNumberEntry** table_ptr);
-
-  /*   71 : Get Method Location */
-  jvmtiError (JNICALL *GetMethodLocation) (jvmtiEnv* env,
-    jmethodID method,
-    jlocation* start_location_ptr,
-    jlocation* end_location_ptr);
-
-  /*   72 : Get Local Variable Table */
-  jvmtiError (JNICALL *GetLocalVariableTable) (jvmtiEnv* env,
-    jmethodID method,
-    jint* entry_count_ptr,
-    jvmtiLocalVariableEntry** table_ptr);
-
-  /*   73 : Set Native Method Prefix */
-  jvmtiError (JNICALL *SetNativeMethodPrefix) (jvmtiEnv* env,
-    const char* prefix);
-
-  /*   74 : Set Native Method Prefixes */
-  jvmtiError (JNICALL *SetNativeMethodPrefixes) (jvmtiEnv* env,
-    jint prefix_count,
-    char** prefixes);
-
-  /*   75 : Get Bytecodes */
-  jvmtiError (JNICALL *GetBytecodes) (jvmtiEnv* env,
-    jmethodID method,
-    jint* bytecode_count_ptr,
-    unsigned char** bytecodes_ptr);
-
-  /*   76 : Is Method Native */
-  jvmtiError (JNICALL *IsMethodNative) (jvmtiEnv* env,
-    jmethodID method,
-    jboolean* is_native_ptr);
-
-  /*   77 : Is Method Synthetic */
-  jvmtiError (JNICALL *IsMethodSynthetic) (jvmtiEnv* env,
-    jmethodID method,
-    jboolean* is_synthetic_ptr);
-
-  /*   78 : Get Loaded Classes */
-  jvmtiError (JNICALL *GetLoadedClasses) (jvmtiEnv* env,
-    jint* class_count_ptr,
-    jclass** classes_ptr);
-
-  /*   79 : Get Classloader Classes */
-  jvmtiError (JNICALL *GetClassLoaderClasses) (jvmtiEnv* env,
-    jobject initiating_loader,
-    jint* class_count_ptr,
-    jclass** classes_ptr);
-
-  /*   80 : Pop Frame */
-  jvmtiError (JNICALL *PopFrame) (jvmtiEnv* env,
-    jthread thread);
-
-  /*   81 : Force Early Return - Object */
-  jvmtiError (JNICALL *ForceEarlyReturnObject) (jvmtiEnv* env,
-    jthread thread,
-    jobject value);
-
-  /*   82 : Force Early Return - Int */
-  jvmtiError (JNICALL *ForceEarlyReturnInt) (jvmtiEnv* env,
-    jthread thread,
-    jint value);
-
-  /*   83 : Force Early Return - Long */
-  jvmtiError (JNICALL *ForceEarlyReturnLong) (jvmtiEnv* env,
-    jthread thread,
-    jlong value);
-
-  /*   84 : Force Early Return - Float */
-  jvmtiError (JNICALL *ForceEarlyReturnFloat) (jvmtiEnv* env,
-    jthread thread,
-    jfloat value);
-
-  /*   85 : Force Early Return - Double */
-  jvmtiError (JNICALL *ForceEarlyReturnDouble) (jvmtiEnv* env,
-    jthread thread,
-    jdouble value);
-
-  /*   86 : Force Early Return - Void */
-  jvmtiError (JNICALL *ForceEarlyReturnVoid) (jvmtiEnv* env,
-    jthread thread);
-
-  /*   87 : Redefine Classes */
-  jvmtiError (JNICALL *RedefineClasses) (jvmtiEnv* env,
-    jint class_count,
-    const jvmtiClassDefinition* class_definitions);
-
-  /*   88 : Get Version Number */
-  jvmtiError (JNICALL *GetVersionNumber) (jvmtiEnv* env,
-    jint* version_ptr);
-
-  /*   89 : Get Capabilities */
-  jvmtiError (JNICALL *GetCapabilities) (jvmtiEnv* env,
-    jvmtiCapabilities* capabilities_ptr);
-
-  /*   90 : Get Source Debug Extension */
-  jvmtiError (JNICALL *GetSourceDebugExtension) (jvmtiEnv* env,
-    jclass klass,
-    char** source_debug_extension_ptr);
-
-  /*   91 : Is Method Obsolete */
-  jvmtiError (JNICALL *IsMethodObsolete) (jvmtiEnv* env,
-    jmethodID method,
-    jboolean* is_obsolete_ptr);
-
-  /*   92 : Suspend Thread List */
-  jvmtiError (JNICALL *SuspendThreadList) (jvmtiEnv* env,
-    jint request_count,
-    const jthread* request_list,
-    jvmtiError* results);
-
-  /*   93 : Resume Thread List */
-  jvmtiError (JNICALL *ResumeThreadList) (jvmtiEnv* env,
-    jint request_count,
-    const jthread* request_list,
-    jvmtiError* results);
-
-  /*   94 :  RESERVED */
-  void *reserved94;
-
-  /*   95 :  RESERVED */
-  void *reserved95;
-
-  /*   96 :  RESERVED */
-  void *reserved96;
-
-  /*   97 :  RESERVED */
-  void *reserved97;
-
-  /*   98 :  RESERVED */
-  void *reserved98;
-
-  /*   99 :  RESERVED */
-  void *reserved99;
-
-  /*   100 : Get All Stack Traces */
-  jvmtiError (JNICALL *GetAllStackTraces) (jvmtiEnv* env,
-    jint max_frame_count,
-    jvmtiStackInfo** stack_info_ptr,
-    jint* thread_count_ptr);
-
-  /*   101 : Get Thread List Stack Traces */
-  jvmtiError (JNICALL *GetThreadListStackTraces) (jvmtiEnv* env,
-    jint thread_count,
-    const jthread* thread_list,
-    jint max_frame_count,
-    jvmtiStackInfo** stack_info_ptr);
-
-  /*   102 : Get Thread Local Storage */
-  jvmtiError (JNICALL *GetThreadLocalStorage) (jvmtiEnv* env,
-    jthread thread,
-    void** data_ptr);
-
-  /*   103 : Set Thread Local Storage */
-  jvmtiError (JNICALL *SetThreadLocalStorage) (jvmtiEnv* env,
-    jthread thread,
-    const void* data);
-
-  /*   104 : Get Stack Trace */
-  jvmtiError (JNICALL *GetStackTrace) (jvmtiEnv* env,
-    jthread thread,
-    jint start_depth,
-    jint max_frame_count,
-    jvmtiFrameInfo* frame_buffer,
-    jint* count_ptr);
-
-  /*   105 :  RESERVED */
-  void *reserved105;
-
-  /*   106 : Get Tag */
-  jvmtiError (JNICALL *GetTag) (jvmtiEnv* env,
-    jobject object,
-    jlong* tag_ptr);
-
-  /*   107 : Set Tag */
-  jvmtiError (JNICALL *SetTag) (jvmtiEnv* env,
-    jobject object,
-    jlong tag);
-
-  /*   108 : Force Garbage Collection */
-  jvmtiError (JNICALL *ForceGarbageCollection) (jvmtiEnv* env);
-
-  /*   109 : Iterate Over Objects Reachable From Object */
-  jvmtiError (JNICALL *IterateOverObjectsReachableFromObject) (jvmtiEnv* env,
-    jobject object,
-    jvmtiObjectReferenceCallback object_reference_callback,
-    const void* user_data);
-
-  /*   110 : Iterate Over Reachable Objects */
-  jvmtiError (JNICALL *IterateOverReachableObjects) (jvmtiEnv* env,
-    jvmtiHeapRootCallback heap_root_callback,
-    jvmtiStackReferenceCallback stack_ref_callback,
-    jvmtiObjectReferenceCallback object_ref_callback,
-    const void* user_data);
-
-  /*   111 : Iterate Over Heap */
-  jvmtiError (JNICALL *IterateOverHeap) (jvmtiEnv* env,
-    jvmtiHeapObjectFilter object_filter,
-    jvmtiHeapObjectCallback heap_object_callback,
-    const void* user_data);
-
-  /*   112 : Iterate Over Instances Of Class */
-  jvmtiError (JNICALL *IterateOverInstancesOfClass) (jvmtiEnv* env,
-    jclass klass,
-    jvmtiHeapObjectFilter object_filter,
-    jvmtiHeapObjectCallback heap_object_callback,
-    const void* user_data);
-
-  /*   113 :  RESERVED */
-  void *reserved113;
-
-  /*   114 : Get Objects With Tags */
-  jvmtiError (JNICALL *GetObjectsWithTags) (jvmtiEnv* env,
-    jint tag_count,
-    const jlong* tags,
-    jint* count_ptr,
-    jobject** object_result_ptr,
-    jlong** tag_result_ptr);
-
-  /*   115 : Follow References */
-  jvmtiError (JNICALL *FollowReferences) (jvmtiEnv* env,
-    jint heap_filter,
-    jclass klass,
-    jobject initial_object,
-    const jvmtiHeapCallbacks* callbacks,
-    const void* user_data);
-
-  /*   116 : Iterate Through Heap */
-  jvmtiError (JNICALL *IterateThroughHeap) (jvmtiEnv* env,
-    jint heap_filter,
-    jclass klass,
-    const jvmtiHeapCallbacks* callbacks,
-    const void* user_data);
-
-  /*   117 :  RESERVED */
-  void *reserved117;
-
-  /*   118 :  RESERVED */
-  void *reserved118;
-
-  /*   119 :  RESERVED */
-  void *reserved119;
-
-  /*   120 : Set JNI Function Table */
-  jvmtiError (JNICALL *SetJNIFunctionTable) (jvmtiEnv* env,
-    const jniNativeInterface* function_table);
-
-  /*   121 : Get JNI Function Table */
-  jvmtiError (JNICALL *GetJNIFunctionTable) (jvmtiEnv* env,
-    jniNativeInterface** function_table);
-
-  /*   122 : Set Event Callbacks */
-  jvmtiError (JNICALL *SetEventCallbacks) (jvmtiEnv* env,
-    const jvmtiEventCallbacks* callbacks,
-    jint size_of_callbacks);
-
-  /*   123 : Generate Events */
-  jvmtiError (JNICALL *GenerateEvents) (jvmtiEnv* env,
-    jvmtiEvent event_type);
-
-  /*   124 : Get Extension Functions */
-  jvmtiError (JNICALL *GetExtensionFunctions) (jvmtiEnv* env,
-    jint* extension_count_ptr,
-    jvmtiExtensionFunctionInfo** extensions);
-
-  /*   125 : Get Extension Events */
-  jvmtiError (JNICALL *GetExtensionEvents) (jvmtiEnv* env,
-    jint* extension_count_ptr,
-    jvmtiExtensionEventInfo** extensions);
-
-  /*   126 : Set Extension Event Callback */
-  jvmtiError (JNICALL *SetExtensionEventCallback) (jvmtiEnv* env,
-    jint extension_event_index,
-    jvmtiExtensionEvent callback);
-
-  /*   127 : Dispose Environment */
-  jvmtiError (JNICALL *DisposeEnvironment) (jvmtiEnv* env);
-
-  /*   128 : Get Error Name */
-  jvmtiError (JNICALL *GetErrorName) (jvmtiEnv* env,
-    jvmtiError error,
-    char** name_ptr);
-
-  /*   129 : Get JLocation Format */
-  jvmtiError (JNICALL *GetJLocationFormat) (jvmtiEnv* env,
-    jvmtiJlocationFormat* format_ptr);
-
-  /*   130 : Get System Properties */
-  jvmtiError (JNICALL *GetSystemProperties) (jvmtiEnv* env,
-    jint* count_ptr,
-    char*** property_ptr);
-
-  /*   131 : Get System Property */
-  jvmtiError (JNICALL *GetSystemProperty) (jvmtiEnv* env,
-    const char* property,
-    char** value_ptr);
-
-  /*   132 : Set System Property */
-  jvmtiError (JNICALL *SetSystemProperty) (jvmtiEnv* env,
-    const char* property,
-    const char* value_ptr);
-
-  /*   133 : Get Phase */
-  jvmtiError (JNICALL *GetPhase) (jvmtiEnv* env,
-    jvmtiPhase* phase_ptr);
-
-  /*   134 : Get Current Thread CPU Timer Information */
-  jvmtiError (JNICALL *GetCurrentThreadCpuTimerInfo) (jvmtiEnv* env,
-    jvmtiTimerInfo* info_ptr);
-
-  /*   135 : Get Current Thread CPU Time */
-  jvmtiError (JNICALL *GetCurrentThreadCpuTime) (jvmtiEnv* env,
-    jlong* nanos_ptr);
-
-  /*   136 : Get Thread CPU Timer Information */
-  jvmtiError (JNICALL *GetThreadCpuTimerInfo) (jvmtiEnv* env,
-    jvmtiTimerInfo* info_ptr);
-
-  /*   137 : Get Thread CPU Time */
-  jvmtiError (JNICALL *GetThreadCpuTime) (jvmtiEnv* env,
-    jthread thread,
-    jlong* nanos_ptr);
-
-  /*   138 : Get Timer Information */
-  jvmtiError (JNICALL *GetTimerInfo) (jvmtiEnv* env,
-    jvmtiTimerInfo* info_ptr);
-
-  /*   139 : Get Time */
-  jvmtiError (JNICALL *GetTime) (jvmtiEnv* env,
-    jlong* nanos_ptr);
-
-  /*   140 : Get Potential Capabilities */
-  jvmtiError (JNICALL *GetPotentialCapabilities) (jvmtiEnv* env,
-    jvmtiCapabilities* capabilities_ptr);
-
-  /*   141 :  RESERVED */
-  void *reserved141;
-
-  /*   142 : Add Capabilities */
-  jvmtiError (JNICALL *AddCapabilities) (jvmtiEnv* env,
-    const jvmtiCapabilities* capabilities_ptr);
-
-  /*   143 : Relinquish Capabilities */
-  jvmtiError (JNICALL *RelinquishCapabilities) (jvmtiEnv* env,
-    const jvmtiCapabilities* capabilities_ptr);
-
-  /*   144 : Get Available Processors */
-  jvmtiError (JNICALL *GetAvailableProcessors) (jvmtiEnv* env,
-    jint* processor_count_ptr);
-
-  /*   145 : Get Class Version Numbers */
-  jvmtiError (JNICALL *GetClassVersionNumbers) (jvmtiEnv* env,
-    jclass klass,
-    jint* minor_version_ptr,
-    jint* major_version_ptr);
-
-  /*   146 : Get Constant Pool */
-  jvmtiError (JNICALL *GetConstantPool) (jvmtiEnv* env,
-    jclass klass,
-    jint* constant_pool_count_ptr,
-    jint* constant_pool_byte_count_ptr,
-    unsigned char** constant_pool_bytes_ptr);
-
-  /*   147 : Get Environment Local Storage */
-  jvmtiError (JNICALL *GetEnvironmentLocalStorage) (jvmtiEnv* env,
-    void** data_ptr);
-
-  /*   148 : Set Environment Local Storage */
-  jvmtiError (JNICALL *SetEnvironmentLocalStorage) (jvmtiEnv* env,
-    const void* data);
-
-  /*   149 : Add To Bootstrap Class Loader Search */
-  jvmtiError (JNICALL *AddToBootstrapClassLoaderSearch) (jvmtiEnv* env,
-    const char* segment);
-
-  /*   150 : Set Verbose Flag */
-  jvmtiError (JNICALL *SetVerboseFlag) (jvmtiEnv* env,
-    jvmtiVerboseFlag flag,
-    jboolean value);
-
-  /*   151 : Add To System Class Loader Search */
-  jvmtiError (JNICALL *AddToSystemClassLoaderSearch) (jvmtiEnv* env,
-    const char* segment);
-
-  /*   152 : Retransform Classes */
-  jvmtiError (JNICALL *RetransformClasses) (jvmtiEnv* env,
-    jint class_count,
-    const jclass* classes);
-
-  /*   153 : Get Owned Monitor Stack Depth Info */
-  jvmtiError (JNICALL *GetOwnedMonitorStackDepthInfo) (jvmtiEnv* env,
-    jthread thread,
-    jint* monitor_info_count_ptr,
-    jvmtiMonitorStackDepthInfo** monitor_info_ptr);
-
-  /*   154 : Get Object Size */
-  jvmtiError (JNICALL *GetObjectSize) (jvmtiEnv* env,
-    jobject object,
-    jlong* size_ptr);
-
-  /*   155 : Get Local Instance */
-  jvmtiError (JNICALL *GetLocalInstance) (jvmtiEnv* env,
-    jthread thread,
-    jint depth,
-    jobject* value_ptr);
-
-} jvmtiInterface_1;
-
-struct _jvmtiEnv {
-    const struct jvmtiInterface_1_ *functions;
-#ifdef __cplusplus
-
-
-  jvmtiError Allocate(jlong size,
-            unsigned char** mem_ptr) {
-    return functions->Allocate(this, size, mem_ptr);
-  }
-
-  jvmtiError Deallocate(unsigned char* mem) {
-    return functions->Deallocate(this, mem);
-  }
-
-  jvmtiError GetThreadState(jthread thread,
-            jint* thread_state_ptr) {
-    return functions->GetThreadState(this, thread, thread_state_ptr);
-  }
-
-  jvmtiError GetCurrentThread(jthread* thread_ptr) {
-    return functions->GetCurrentThread(this, thread_ptr);
-  }
-
-  jvmtiError GetAllThreads(jint* threads_count_ptr,
-            jthread** threads_ptr) {
-    return functions->GetAllThreads(this, threads_count_ptr, threads_ptr);
-  }
-
-  jvmtiError SuspendThread(jthread thread) {
-    return functions->SuspendThread(this, thread);
-  }
-
-  jvmtiError SuspendThreadList(jint request_count,
-            const jthread* request_list,
-            jvmtiError* results) {
-    return functions->SuspendThreadList(this, request_count, request_list, results);
-  }
-
-  jvmtiError ResumeThread(jthread thread) {
-    return functions->ResumeThread(this, thread);
-  }
-
-  jvmtiError ResumeThreadList(jint request_count,
-            const jthread* request_list,
-            jvmtiError* results) {
-    return functions->ResumeThreadList(this, request_count, request_list, results);
-  }
-
-  jvmtiError StopThread(jthread thread,
-            jobject exception) {
-    return functions->StopThread(this, thread, exception);
-  }
-
-  jvmtiError InterruptThread(jthread thread) {
-    return functions->InterruptThread(this, thread);
-  }
-
-  jvmtiError GetThreadInfo(jthread thread,
-            jvmtiThreadInfo* info_ptr) {
-    return functions->GetThreadInfo(this, thread, info_ptr);
-  }
-
-  jvmtiError GetOwnedMonitorInfo(jthread thread,
-            jint* owned_monitor_count_ptr,
-            jobject** owned_monitors_ptr) {
-    return functions->GetOwnedMonitorInfo(this, thread, owned_monitor_count_ptr, owned_monitors_ptr);
-  }
-
-  jvmtiError GetOwnedMonitorStackDepthInfo(jthread thread,
-            jint* monitor_info_count_ptr,
-            jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
-    return functions->GetOwnedMonitorStackDepthInfo(this, thread, monitor_info_count_ptr, monitor_info_ptr);
-  }
-
-  jvmtiError GetCurrentContendedMonitor(jthread thread,
-            jobject* monitor_ptr) {
-    return functions->GetCurrentContendedMonitor(this, thread, monitor_ptr);
-  }
-
-  jvmtiError RunAgentThread(jthread thread,
-            jvmtiStartFunction proc,
-            const void* arg,
-            jint priority) {
-    return functions->RunAgentThread(this, thread, proc, arg, priority);
-  }
-
-  jvmtiError SetThreadLocalStorage(jthread thread,
-            const void* data) {
-    return functions->SetThreadLocalStorage(this, thread, data);
-  }
-
-  jvmtiError GetThreadLocalStorage(jthread thread,
-            void** data_ptr) {
-    return functions->GetThreadLocalStorage(this, thread, data_ptr);
-  }
-
-  jvmtiError GetTopThreadGroups(jint* group_count_ptr,
-            jthreadGroup** groups_ptr) {
-    return functions->GetTopThreadGroups(this, group_count_ptr, groups_ptr);
-  }
-
-  jvmtiError GetThreadGroupInfo(jthreadGroup group,
-            jvmtiThreadGroupInfo* info_ptr) {
-    return functions->GetThreadGroupInfo(this, group, info_ptr);
-  }
-
-  jvmtiError GetThreadGroupChildren(jthreadGroup group,
-            jint* thread_count_ptr,
-            jthread** threads_ptr,
-            jint* group_count_ptr,
-            jthreadGroup** groups_ptr) {
-    return functions->GetThreadGroupChildren(this, group, thread_count_ptr, threads_ptr, group_count_ptr, groups_ptr);
-  }
-
-  jvmtiError GetStackTrace(jthread thread,
-            jint start_depth,
-            jint max_frame_count,
-            jvmtiFrameInfo* frame_buffer,
-            jint* count_ptr) {
-    return functions->GetStackTrace(this, thread, start_depth, max_frame_count, frame_buffer, count_ptr);
-  }
-
-  jvmtiError GetAllStackTraces(jint max_frame_count,
-            jvmtiStackInfo** stack_info_ptr,
-            jint* thread_count_ptr) {
-    return functions->GetAllStackTraces(this, max_frame_count, stack_info_ptr, thread_count_ptr);
-  }
-
-  jvmtiError GetThreadListStackTraces(jint thread_count,
-            const jthread* thread_list,
-            jint max_frame_count,
-            jvmtiStackInfo** stack_info_ptr) {
-    return functions->GetThreadListStackTraces(this, thread_count, thread_list, max_frame_count, stack_info_ptr);
-  }
-
-  jvmtiError GetFrameCount(jthread thread,
-            jint* count_ptr) {
-    return functions->GetFrameCount(this, thread, count_ptr);
-  }
-
-  jvmtiError PopFrame(jthread thread) {
-    return functions->PopFrame(this, thread);
-  }
-
-  jvmtiError GetFrameLocation(jthread thread,
-            jint depth,
-            jmethodID* method_ptr,
-            jlocation* location_ptr) {
-    return functions->GetFrameLocation(this, thread, depth, method_ptr, location_ptr);
-  }
-
-  jvmtiError NotifyFramePop(jthread thread,
-            jint depth) {
-    return functions->NotifyFramePop(this, thread, depth);
-  }
-
-  jvmtiError ForceEarlyReturnObject(jthread thread,
-            jobject value) {
-    return functions->ForceEarlyReturnObject(this, thread, value);
-  }
-
-  jvmtiError ForceEarlyReturnInt(jthread thread,
-            jint value) {
-    return functions->ForceEarlyReturnInt(this, thread, value);
-  }
-
-  jvmtiError ForceEarlyReturnLong(jthread thread,
-            jlong value) {
-    return functions->ForceEarlyReturnLong(this, thread, value);
-  }
-
-  jvmtiError ForceEarlyReturnFloat(jthread thread,
-            jfloat value) {
-    return functions->ForceEarlyReturnFloat(this, thread, value);
-  }
-
-  jvmtiError ForceEarlyReturnDouble(jthread thread,
-            jdouble value) {
-    return functions->ForceEarlyReturnDouble(this, thread, value);
-  }
-
-  jvmtiError ForceEarlyReturnVoid(jthread thread) {
-    return functions->ForceEarlyReturnVoid(this, thread);
-  }
-
-  jvmtiError FollowReferences(jint heap_filter,
-            jclass klass,
-            jobject initial_object,
-            const jvmtiHeapCallbacks* callbacks,
-            const void* user_data) {
-    return functions->FollowReferences(this, heap_filter, klass, initial_object, callbacks, user_data);
-  }
-
-  jvmtiError IterateThroughHeap(jint heap_filter,
-            jclass klass,
-            const jvmtiHeapCallbacks* callbacks,
-            const void* user_data) {
-    return functions->IterateThroughHeap(this, heap_filter, klass, callbacks, user_data);
-  }
-
-  jvmtiError GetTag(jobject object,
-            jlong* tag_ptr) {
-    return functions->GetTag(this, object, tag_ptr);
-  }
-
-  jvmtiError SetTag(jobject object,
-            jlong tag) {
-    return functions->SetTag(this, object, tag);
-  }
-
-  jvmtiError GetObjectsWithTags(jint tag_count,
-            const jlong* tags,
-            jint* count_ptr,
-            jobject** object_result_ptr,
-            jlong** tag_result_ptr) {
-    return functions->GetObjectsWithTags(this, tag_count, tags, count_ptr, object_result_ptr, tag_result_ptr);
-  }
-
-  jvmtiError ForceGarbageCollection() {
-    return functions->ForceGarbageCollection(this);
-  }
-
-  jvmtiError IterateOverObjectsReachableFromObject(jobject object,
-            jvmtiObjectReferenceCallback object_reference_callback,
-            const void* user_data) {
-    return functions->IterateOverObjectsReachableFromObject(this, object, object_reference_callback, user_data);
-  }
-
-  jvmtiError IterateOverReachableObjects(jvmtiHeapRootCallback heap_root_callback,
-            jvmtiStackReferenceCallback stack_ref_callback,
-            jvmtiObjectReferenceCallback object_ref_callback,
-            const void* user_data) {
-    return functions->IterateOverReachableObjects(this, heap_root_callback, stack_ref_callback, object_ref_callback, user_data);
-  }
-
-  jvmtiError IterateOverHeap(jvmtiHeapObjectFilter object_filter,
-            jvmtiHeapObjectCallback heap_object_callback,
-            const void* user_data) {
-    return functions->IterateOverHeap(this, object_filter, heap_object_callback, user_data);
-  }
-
-  jvmtiError IterateOverInstancesOfClass(jclass klass,
-            jvmtiHeapObjectFilter object_filter,
-            jvmtiHeapObjectCallback heap_object_callback,
-            const void* user_data) {
-    return functions->IterateOverInstancesOfClass(this, klass, object_filter, heap_object_callback, user_data);
-  }
-
-  jvmtiError GetLocalObject(jthread thread,
-            jint depth,
-            jint slot,
-            jobject* value_ptr) {
-    return functions->GetLocalObject(this, thread, depth, slot, value_ptr);
-  }
-
-  jvmtiError GetLocalInstance(jthread thread,
-            jint depth,
-            jobject* value_ptr) {
-    return functions->GetLocalInstance(this, thread, depth, value_ptr);
-  }
-
-  jvmtiError GetLocalInt(jthread thread,
-            jint depth,
-            jint slot,
-            jint* value_ptr) {
-    return functions->GetLocalInt(this, thread, depth, slot, value_ptr);
-  }
-
-  jvmtiError GetLocalLong(jthread thread,
-            jint depth,
-            jint slot,
-            jlong* value_ptr) {
-    return functions->GetLocalLong(this, thread, depth, slot, value_ptr);
-  }
-
-  jvmtiError GetLocalFloat(jthread thread,
-            jint depth,
-            jint slot,
-            jfloat* value_ptr) {
-    return functions->GetLocalFloat(this, thread, depth, slot, value_ptr);
-  }
-
-  jvmtiError GetLocalDouble(jthread thread,
-            jint depth,
-            jint slot,
-            jdouble* value_ptr) {
-    return functions->GetLocalDouble(this, thread, depth, slot, value_ptr);
-  }
-
-  jvmtiError SetLocalObject(jthread thread,
-            jint depth,
-            jint slot,
-            jobject value) {
-    return functions->SetLocalObject(this, thread, depth, slot, value);
-  }
-
-  jvmtiError SetLocalInt(jthread thread,
-            jint depth,
-            jint slot,
-            jint value) {
-    return functions->SetLocalInt(this, thread, depth, slot, value);
-  }
-
-  jvmtiError SetLocalLong(jthread thread,
-            jint depth,
-            jint slot,
-            jlong value) {
-    return functions->SetLocalLong(this, thread, depth, slot, value);
-  }
-
-  jvmtiError SetLocalFloat(jthread thread,
-            jint depth,
-            jint slot,
-            jfloat value) {
-    return functions->SetLocalFloat(this, thread, depth, slot, value);
-  }
-
-  jvmtiError SetLocalDouble(jthread thread,
-            jint depth,
-            jint slot,
-            jdouble value) {
-    return functions->SetLocalDouble(this, thread, depth, slot, value);
-  }
-
-  jvmtiError SetBreakpoint(jmethodID method,
-            jlocation location) {
-    return functions->SetBreakpoint(this, method, location);
-  }
-
-  jvmtiError ClearBreakpoint(jmethodID method,
-            jlocation location) {
-    return functions->ClearBreakpoint(this, method, location);
-  }
-
-  jvmtiError SetFieldAccessWatch(jclass klass,
-            jfieldID field) {
-    return functions->SetFieldAccessWatch(this, klass, field);
-  }
-
-  jvmtiError ClearFieldAccessWatch(jclass klass,
-            jfieldID field) {
-    return functions->ClearFieldAccessWatch(this, klass, field);
-  }
-
-  jvmtiError SetFieldModificationWatch(jclass klass,
-            jfieldID field) {
-    return functions->SetFieldModificationWatch(this, klass, field);
-  }
-
-  jvmtiError ClearFieldModificationWatch(jclass klass,
-            jfieldID field) {
-    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 GetNamedModule(jobject class_loader,
-            const char* package_name,
-            jobject* module_ptr) {
-    return functions->GetNamedModule(this, class_loader, package_name, module_ptr);
-  }
-
-  jvmtiError GetLoadedClasses(jint* class_count_ptr,
-            jclass** classes_ptr) {
-    return functions->GetLoadedClasses(this, class_count_ptr, classes_ptr);
-  }
-
-  jvmtiError GetClassLoaderClasses(jobject initiating_loader,
-            jint* class_count_ptr,
-            jclass** classes_ptr) {
-    return functions->GetClassLoaderClasses(this, initiating_loader, class_count_ptr, classes_ptr);
-  }
-
-  jvmtiError GetClassSignature(jclass klass,
-            char** signature_ptr,
-            char** generic_ptr) {
-    return functions->GetClassSignature(this, klass, signature_ptr, generic_ptr);
-  }
-
-  jvmtiError GetClassStatus(jclass klass,
-            jint* status_ptr) {
-    return functions->GetClassStatus(this, klass, status_ptr);
-  }
-
-  jvmtiError GetSourceFileName(jclass klass,
-            char** source_name_ptr) {
-    return functions->GetSourceFileName(this, klass, source_name_ptr);
-  }
-
-  jvmtiError GetClassModifiers(jclass klass,
-            jint* modifiers_ptr) {
-    return functions->GetClassModifiers(this, klass, modifiers_ptr);
-  }
-
-  jvmtiError GetClassMethods(jclass klass,
-            jint* method_count_ptr,
-            jmethodID** methods_ptr) {
-    return functions->GetClassMethods(this, klass, method_count_ptr, methods_ptr);
-  }
-
-  jvmtiError GetClassFields(jclass klass,
-            jint* field_count_ptr,
-            jfieldID** fields_ptr) {
-    return functions->GetClassFields(this, klass, field_count_ptr, fields_ptr);
-  }
-
-  jvmtiError GetImplementedInterfaces(jclass klass,
-            jint* interface_count_ptr,
-            jclass** interfaces_ptr) {
-    return functions->GetImplementedInterfaces(this, klass, interface_count_ptr, interfaces_ptr);
-  }
-
-  jvmtiError GetClassVersionNumbers(jclass klass,
-            jint* minor_version_ptr,
-            jint* major_version_ptr) {
-    return functions->GetClassVersionNumbers(this, klass, minor_version_ptr, major_version_ptr);
-  }
-
-  jvmtiError GetConstantPool(jclass klass,
-            jint* constant_pool_count_ptr,
-            jint* constant_pool_byte_count_ptr,
-            unsigned char** constant_pool_bytes_ptr) {
-    return functions->GetConstantPool(this, klass, constant_pool_count_ptr, constant_pool_byte_count_ptr, constant_pool_bytes_ptr);
-  }
-
-  jvmtiError IsInterface(jclass klass,
-            jboolean* is_interface_ptr) {
-    return functions->IsInterface(this, klass, is_interface_ptr);
-  }
-
-  jvmtiError IsArrayClass(jclass klass,
-            jboolean* is_array_class_ptr) {
-    return functions->IsArrayClass(this, klass, is_array_class_ptr);
-  }
-
-  jvmtiError IsModifiableClass(jclass klass,
-            jboolean* is_modifiable_class_ptr) {
-    return functions->IsModifiableClass(this, klass, is_modifiable_class_ptr);
-  }
-
-  jvmtiError GetClassLoader(jclass klass,
-            jobject* classloader_ptr) {
-    return functions->GetClassLoader(this, klass, classloader_ptr);
-  }
-
-  jvmtiError GetSourceDebugExtension(jclass klass,
-            char** source_debug_extension_ptr) {
-    return functions->GetSourceDebugExtension(this, klass, source_debug_extension_ptr);
-  }
-
-  jvmtiError RetransformClasses(jint class_count,
-            const jclass* classes) {
-    return functions->RetransformClasses(this, class_count, classes);
-  }
-
-  jvmtiError RedefineClasses(jint class_count,
-            const jvmtiClassDefinition* class_definitions) {
-    return functions->RedefineClasses(this, class_count, class_definitions);
-  }
-
-  jvmtiError GetObjectSize(jobject object,
-            jlong* size_ptr) {
-    return functions->GetObjectSize(this, object, size_ptr);
-  }
-
-  jvmtiError GetObjectHashCode(jobject object,
-            jint* hash_code_ptr) {
-    return functions->GetObjectHashCode(this, object, hash_code_ptr);
-  }
-
-  jvmtiError GetObjectMonitorUsage(jobject object,
-            jvmtiMonitorUsage* info_ptr) {
-    return functions->GetObjectMonitorUsage(this, object, info_ptr);
-  }
-
-  jvmtiError GetFieldName(jclass klass,
-            jfieldID field,
-            char** name_ptr,
-            char** signature_ptr,
-            char** generic_ptr) {
-    return functions->GetFieldName(this, klass, field, name_ptr, signature_ptr, generic_ptr);
-  }
-
-  jvmtiError GetFieldDeclaringClass(jclass klass,
-            jfieldID field,
-            jclass* declaring_class_ptr) {
-    return functions->GetFieldDeclaringClass(this, klass, field, declaring_class_ptr);
-  }
-
-  jvmtiError GetFieldModifiers(jclass klass,
-            jfieldID field,
-            jint* modifiers_ptr) {
-    return functions->GetFieldModifiers(this, klass, field, modifiers_ptr);
-  }
-
-  jvmtiError IsFieldSynthetic(jclass klass,
-            jfieldID field,
-            jboolean* is_synthetic_ptr) {
-    return functions->IsFieldSynthetic(this, klass, field, is_synthetic_ptr);
-  }
-
-  jvmtiError GetMethodName(jmethodID method,
-            char** name_ptr,
-            char** signature_ptr,
-            char** generic_ptr) {
-    return functions->GetMethodName(this, method, name_ptr, signature_ptr, generic_ptr);
-  }
-
-  jvmtiError GetMethodDeclaringClass(jmethodID method,
-            jclass* declaring_class_ptr) {
-    return functions->GetMethodDeclaringClass(this, method, declaring_class_ptr);
-  }
-
-  jvmtiError GetMethodModifiers(jmethodID method,
-            jint* modifiers_ptr) {
-    return functions->GetMethodModifiers(this, method, modifiers_ptr);
-  }
-
-  jvmtiError GetMaxLocals(jmethodID method,
-            jint* max_ptr) {
-    return functions->GetMaxLocals(this, method, max_ptr);
-  }
-
-  jvmtiError GetArgumentsSize(jmethodID method,
-            jint* size_ptr) {
-    return functions->GetArgumentsSize(this, method, size_ptr);
-  }
-
-  jvmtiError GetLineNumberTable(jmethodID method,
-            jint* entry_count_ptr,
-            jvmtiLineNumberEntry** table_ptr) {
-    return functions->GetLineNumberTable(this, method, entry_count_ptr, table_ptr);
-  }
-
-  jvmtiError GetMethodLocation(jmethodID method,
-            jlocation* start_location_ptr,
-            jlocation* end_location_ptr) {
-    return functions->GetMethodLocation(this, method, start_location_ptr, end_location_ptr);
-  }
-
-  jvmtiError GetLocalVariableTable(jmethodID method,
-            jint* entry_count_ptr,
-            jvmtiLocalVariableEntry** table_ptr) {
-    return functions->GetLocalVariableTable(this, method, entry_count_ptr, table_ptr);
-  }
-
-  jvmtiError GetBytecodes(jmethodID method,
-            jint* bytecode_count_ptr,
-            unsigned char** bytecodes_ptr) {
-    return functions->GetBytecodes(this, method, bytecode_count_ptr, bytecodes_ptr);
-  }
-
-  jvmtiError IsMethodNative(jmethodID method,
-            jboolean* is_native_ptr) {
-    return functions->IsMethodNative(this, method, is_native_ptr);
-  }
-
-  jvmtiError IsMethodSynthetic(jmethodID method,
-            jboolean* is_synthetic_ptr) {
-    return functions->IsMethodSynthetic(this, method, is_synthetic_ptr);
-  }
-
-  jvmtiError IsMethodObsolete(jmethodID method,
-            jboolean* is_obsolete_ptr) {
-    return functions->IsMethodObsolete(this, method, is_obsolete_ptr);
-  }
-
-  jvmtiError SetNativeMethodPrefix(const char* prefix) {
-    return functions->SetNativeMethodPrefix(this, prefix);
-  }
-
-  jvmtiError SetNativeMethodPrefixes(jint prefix_count,
-            char** prefixes) {
-    return functions->SetNativeMethodPrefixes(this, prefix_count, prefixes);
-  }
-
-  jvmtiError CreateRawMonitor(const char* name,
-            jrawMonitorID* monitor_ptr) {
-    return functions->CreateRawMonitor(this, name, monitor_ptr);
-  }
-
-  jvmtiError DestroyRawMonitor(jrawMonitorID monitor) {
-    return functions->DestroyRawMonitor(this, monitor);
-  }
-
-  jvmtiError RawMonitorEnter(jrawMonitorID monitor) {
-    return functions->RawMonitorEnter(this, monitor);
-  }
-
-  jvmtiError RawMonitorExit(jrawMonitorID monitor) {
-    return functions->RawMonitorExit(this, monitor);
-  }
-
-  jvmtiError RawMonitorWait(jrawMonitorID monitor,
-            jlong millis) {
-    return functions->RawMonitorWait(this, monitor, millis);
-  }
-
-  jvmtiError RawMonitorNotify(jrawMonitorID monitor) {
-    return functions->RawMonitorNotify(this, monitor);
-  }
-
-  jvmtiError RawMonitorNotifyAll(jrawMonitorID monitor) {
-    return functions->RawMonitorNotifyAll(this, monitor);
-  }
-
-  jvmtiError SetJNIFunctionTable(const jniNativeInterface* function_table) {
-    return functions->SetJNIFunctionTable(this, function_table);
-  }
-
-  jvmtiError GetJNIFunctionTable(jniNativeInterface** function_table) {
-    return functions->GetJNIFunctionTable(this, function_table);
-  }
-
-  jvmtiError SetEventCallbacks(const jvmtiEventCallbacks* callbacks,
-            jint size_of_callbacks) {
-    return functions->SetEventCallbacks(this, callbacks, size_of_callbacks);
-  }
-
-  jvmtiError SetEventNotificationMode(jvmtiEventMode mode,
-            jvmtiEvent event_type,
-            jthread event_thread,
-             ...) {
-    return functions->SetEventNotificationMode(this, mode, event_type, event_thread);
-  }
-
-  jvmtiError GenerateEvents(jvmtiEvent event_type) {
-    return functions->GenerateEvents(this, event_type);
-  }
-
-  jvmtiError GetExtensionFunctions(jint* extension_count_ptr,
-            jvmtiExtensionFunctionInfo** extensions) {
-    return functions->GetExtensionFunctions(this, extension_count_ptr, extensions);
-  }
-
-  jvmtiError GetExtensionEvents(jint* extension_count_ptr,
-            jvmtiExtensionEventInfo** extensions) {
-    return functions->GetExtensionEvents(this, extension_count_ptr, extensions);
-  }
-
-  jvmtiError SetExtensionEventCallback(jint extension_event_index,
-            jvmtiExtensionEvent callback) {
-    return functions->SetExtensionEventCallback(this, extension_event_index, callback);
-  }
-
-  jvmtiError GetPotentialCapabilities(jvmtiCapabilities* capabilities_ptr) {
-    return functions->GetPotentialCapabilities(this, capabilities_ptr);
-  }
-
-  jvmtiError AddCapabilities(const jvmtiCapabilities* capabilities_ptr) {
-    return functions->AddCapabilities(this, capabilities_ptr);
-  }
-
-  jvmtiError RelinquishCapabilities(const jvmtiCapabilities* capabilities_ptr) {
-    return functions->RelinquishCapabilities(this, capabilities_ptr);
-  }
-
-  jvmtiError GetCapabilities(jvmtiCapabilities* capabilities_ptr) {
-    return functions->GetCapabilities(this, capabilities_ptr);
-  }
-
-  jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
-    return functions->GetCurrentThreadCpuTimerInfo(this, info_ptr);
-  }
-
-  jvmtiError GetCurrentThreadCpuTime(jlong* nanos_ptr) {
-    return functions->GetCurrentThreadCpuTime(this, nanos_ptr);
-  }
-
-  jvmtiError GetThreadCpuTimerInfo(jvmtiTimerInfo* info_ptr) {
-    return functions->GetThreadCpuTimerInfo(this, info_ptr);
-  }
-
-  jvmtiError GetThreadCpuTime(jthread thread,
-            jlong* nanos_ptr) {
-    return functions->GetThreadCpuTime(this, thread, nanos_ptr);
-  }
-
-  jvmtiError GetTimerInfo(jvmtiTimerInfo* info_ptr) {
-    return functions->GetTimerInfo(this, info_ptr);
-  }
-
-  jvmtiError GetTime(jlong* nanos_ptr) {
-    return functions->GetTime(this, nanos_ptr);
-  }
-
-  jvmtiError GetAvailableProcessors(jint* processor_count_ptr) {
-    return functions->GetAvailableProcessors(this, processor_count_ptr);
-  }
-
-  jvmtiError AddToBootstrapClassLoaderSearch(const char* segment) {
-    return functions->AddToBootstrapClassLoaderSearch(this, segment);
-  }
-
-  jvmtiError AddToSystemClassLoaderSearch(const char* segment) {
-    return functions->AddToSystemClassLoaderSearch(this, segment);
-  }
-
-  jvmtiError GetSystemProperties(jint* count_ptr,
-            char*** property_ptr) {
-    return functions->GetSystemProperties(this, count_ptr, property_ptr);
-  }
-
-  jvmtiError GetSystemProperty(const char* property,
-            char** value_ptr) {
-    return functions->GetSystemProperty(this, property, value_ptr);
-  }
-
-  jvmtiError SetSystemProperty(const char* property,
-            const char* value_ptr) {
-    return functions->SetSystemProperty(this, property, value_ptr);
-  }
-
-  jvmtiError GetPhase(jvmtiPhase* phase_ptr) {
-    return functions->GetPhase(this, phase_ptr);
-  }
-
-  jvmtiError DisposeEnvironment() {
-    return functions->DisposeEnvironment(this);
-  }
-
-  jvmtiError SetEnvironmentLocalStorage(const void* data) {
-    return functions->SetEnvironmentLocalStorage(this, data);
-  }
-
-  jvmtiError GetEnvironmentLocalStorage(void** data_ptr) {
-    return functions->GetEnvironmentLocalStorage(this, data_ptr);
-  }
-
-  jvmtiError GetVersionNumber(jint* version_ptr) {
-    return functions->GetVersionNumber(this, version_ptr);
-  }
-
-  jvmtiError GetErrorName(jvmtiError error,
-            char** name_ptr) {
-    return functions->GetErrorName(this, error, name_ptr);
-  }
-
-  jvmtiError SetVerboseFlag(jvmtiVerboseFlag flag,
-            jboolean value) {
-    return functions->SetVerboseFlag(this, flag, value);
-  }
-
-  jvmtiError GetJLocationFormat(jvmtiJlocationFormat* format_ptr) {
-    return functions->GetJLocationFormat(this, format_ptr);
-  }
-
-#endif /* __cplusplus */
-};
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif /* __cplusplus */
-
-#endif /* !_JAVA_JVMTI_H_ */
--- a/jdk/src/java.base/share/native/launcher/defines.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/launcher/defines.h	Fri Nov 11 16:44:36 2016 +0100
@@ -51,16 +51,6 @@
 static char* const_progname = NULL;
 #endif
 static const char* const_jargs[] = JAVA_ARGS;
-/*
- * ApplicationHome is prepended to each of these entries; the resulting
- * strings are concatenated (separated by PATH_SEPARATOR) and used as the
- * value of -cp option to the launcher.
- */
-#ifndef 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
 static const char* const_progname = "java";
--- a/jdk/src/java.base/share/native/launcher/main.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/launcher/main.c	Fri Nov 11 16:44:36 2016 +0100
@@ -83,7 +83,7 @@
 int WINAPI
 WinMain(HINSTANCE inst, HINSTANCE previnst, LPSTR cmdline, int cmdshow)
 {
-    int margc, appclassc;
+    int margc;
     char** margv;
     const jboolean const_javaw = JNI_TRUE;
 
@@ -93,7 +93,7 @@
 int
 main(int argc, char **argv)
 {
-    int margc, appclassc;
+    int margc;
     char** margv;
     const jboolean const_javaw = JNI_FALSE;
 #endif /* JAVAW */
@@ -148,14 +148,9 @@
         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,
-                   appclassc, const_appclasspath,
+                   0, NULL,
                    VERSION_STRING,
                    DOT_VERSION,
                    (const_progname != NULL) ? const_progname : *margv,
--- a/jdk/src/java.base/share/native/libjava/StackFrameInfo.c	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.
- */
-
-/*
- *      Implementation of class StackFrameInfo
- */
-
-#include <stdio.h>
-#include <signal.h>
-
-#include "jni.h"
-#include "jvm.h"
-
-#include "java_lang_StackFrameInfo.h"
-
-
-/*
- * Class:     java_lang_StackFrameInfo
- * Method:    toStackTraceElement0
- * Signature: (Ljava/lang/StackTraceElement;)V
- */
-JNIEXPORT void JNICALL Java_java_lang_StackFrameInfo_toStackTraceElement0
-  (JNIEnv *env, jobject stackframeinfo, jobject stacktraceinfo) {
-     JVM_ToStackTraceElement(env, stackframeinfo, stacktraceinfo);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/native/libjava/StackTraceElement.c	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "jni.h"
+#include "jvm.h"
+
+#include "java_lang_StackTraceElement.h"
+
+JNIEXPORT void JNICALL Java_java_lang_StackTraceElement_initStackTraceElement
+  (JNIEnv *env, jobject dummy, jobject element, jobject stackframeinfo) {
+     JVM_InitStackTraceElement(env, element, stackframeinfo);
+}
+
+JNIEXPORT void JNICALL Java_java_lang_StackTraceElement_initStackTraceElements
+  (JNIEnv *env, jobject dummy, jobjectArray elements, jobject throwable)
+{
+    JVM_InitStackTraceElementArray(env, elements, throwable);
+}
--- a/jdk/src/java.base/share/native/libjava/Throwable.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/libjava/Throwable.c	Fri Nov 11 16:44:36 2016 +0100
@@ -49,10 +49,3 @@
     JVM_FillInStackTrace(env, throwable);
     return throwable;
 }
-
-JNIEXPORT void JNICALL
-Java_java_lang_Throwable_getStackTraceElements(JNIEnv *env,
-                                               jobject throwable, jobjectArray elements)
-{
-    JVM_GetStackTraceElements(env, throwable, elements);
-}
--- a/jdk/src/java.base/share/native/libjli/java.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/libjli/java.c	Fri Nov 11 16:44:36 2016 +0100
@@ -1664,19 +1664,21 @@
     AddOption(apphome, NULL);
 
     /* How big is the application's classpath? */
-    size = 40;                                 /* 40: "-Djava.class.path=" */
-    for (i = 0; i < cpathc; i++) {
-        size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
+    if (cpathc > 0) {
+        size = 40;                                 /* 40: "-Djava.class.path=" */
+        for (i = 0; i < cpathc; i++) {
+            size += (int)JLI_StrLen(home) + (int)JLI_StrLen(cpathv[i]) + 1; /* 1: separator */
+        }
+        appcp = (char *)JLI_MemAlloc(size + 1);
+        JLI_StrCpy(appcp, "-Djava.class.path=");
+        for (i = 0; i < cpathc; i++) {
+            JLI_StrCat(appcp, home);                        /* c:\program files\myapp */
+            JLI_StrCat(appcp, cpathv[i]);           /* \lib\myapp.jar         */
+            JLI_StrCat(appcp, separator);           /* ;                      */
+        }
+        appcp[JLI_StrLen(appcp)-1] = '\0';  /* remove trailing path separator */
+        AddOption(appcp, NULL);
     }
-    appcp = (char *)JLI_MemAlloc(size + 1);
-    JLI_StrCpy(appcp, "-Djava.class.path=");
-    for (i = 0; i < cpathc; i++) {
-        JLI_StrCat(appcp, home);                        /* c:\program files\myapp */
-        JLI_StrCat(appcp, cpathv[i]);           /* \lib\myapp.jar         */
-        JLI_StrCat(appcp, separator);           /* ;                      */
-    }
-    appcp[JLI_StrLen(appcp)-1] = '\0';  /* remove trailing path separator */
-    AddOption(appcp, NULL);
     return JNI_TRUE;
 }
 
--- a/jdk/src/java.base/share/native/libnet/net_util.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.c	Fri Nov 11 16:44:36 2016 +0100
@@ -23,20 +23,19 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
 
-int IPv6_supported() ;
-int reuseport_supported() ;
+#include "java_net_InetAddress.h"
+
+int IPv6_supported();
+int reuseport_supported();
 
 static int IPv6_available;
 static int REUSEPORT_available;
 
 JNIEXPORT jint JNICALL ipv6_available()
 {
-    return IPv6_available ;
+    return IPv6_available;
 }
 
 JNIEXPORT jint JNICALL reuseport_available()
@@ -204,13 +203,8 @@
 JNIEXPORT jobject JNICALL
 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
     jobject iaObj;
-#ifdef AF_INET6
     if (him->sa_family == AF_INET6) {
-#ifdef WIN32
-        struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
         jbyte *caddr = (jbyte *)&(him6->sin6_addr);
         if (NET_IsIPv4Mapped(caddr)) {
             int address;
@@ -218,7 +212,7 @@
             CHECK_NULL_RETURN(iaObj, NULL);
             address = NET_IPv4MappedToIPv4(caddr);
             setInetAddress_addr(env, iaObj, address);
-            setInetAddress_family(env, iaObj, IPv4);
+            setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
         } else {
             jint scope;
             jboolean ret;
@@ -227,21 +221,19 @@
             ret = setInet6Address_ipaddress(env, iaObj, (char *)&(him6->sin6_addr));
             if (ret == JNI_FALSE)
                 return NULL;
-            setInetAddress_family(env, iaObj, IPv6);
+            setInetAddress_family(env, iaObj, java_net_InetAddress_IPv6);
             scope = getScopeID(him);
             setInet6Address_scopeid(env, iaObj, scope);
         }
         *port = ntohs(him6->sin6_port);
-    } else
-#endif /* AF_INET6 */
-        {
-            struct sockaddr_in *him4 = (struct sockaddr_in *)him;
-            iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
-            CHECK_NULL_RETURN(iaObj, NULL);
-            setInetAddress_family(env, iaObj, IPv4);
-            setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
-            *port = ntohs(him4->sin_port);
-        }
+    } else {
+        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
+        iaObj = (*env)->NewObject(env, ia4_class, ia4_ctrID);
+        CHECK_NULL_RETURN(iaObj, NULL);
+        setInetAddress_family(env, iaObj, java_net_InetAddress_IPv4);
+        setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
+        *port = ntohs(him4->sin_port);
+    }
     return iaObj;
 }
 
@@ -250,14 +242,10 @@
 {
     jint family = AF_INET;
 
-#ifdef AF_INET6
-    family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+    family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+        AF_INET : AF_INET6;
     if (him->sa_family == AF_INET6) {
-#ifdef WIN32
-        struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
-#else
         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
-#endif
         jbyte *caddrNew = (jbyte *)&(him6->sin6_addr);
         if (NET_IsIPv4Mapped(caddrNew)) {
             int addrNew;
@@ -287,22 +275,20 @@
                 return JNI_FALSE;
             }
         }
-    } else
-#endif /* AF_INET6 */
-        {
-            struct sockaddr_in *him4 = (struct sockaddr_in *)him;
-            int addrNew, addrCur;
-            if (family != AF_INET) {
-                return JNI_FALSE;
-            }
-            addrNew = ntohl(him4->sin_addr.s_addr);
-            addrCur = getInetAddress_addr(env, iaObj);
-            if (addrNew == addrCur) {
-                return JNI_TRUE;
-            } else {
-                return JNI_FALSE;
-            }
+    } else {
+        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
+        int addrNew, addrCur;
+        if (family != AF_INET) {
+            return JNI_FALSE;
         }
+        addrNew = ntohl(him4->sin_addr.s_addr);
+        addrCur = getInetAddress_addr(env, iaObj);
+        if (addrNew == addrCur) {
+            return JNI_TRUE;
+        } else {
+            return JNI_FALSE;
+        }
+    }
 }
 
 unsigned short
--- a/jdk/src/java.base/share/native/libnet/net_util.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.h	Fri Nov 11 16:44:36 2016 +0100
@@ -36,12 +36,6 @@
 
 #define MAX_PACKET_LEN 65536
 
-#define IPv4 1
-#define IPv6 2
-
-#define NET_ERROR(env, ex, msg) \
-{ if (!(*env)->ExceptionOccurred(env)) JNU_ThrowByName(env, ex, msg); }
-
 #define NET_WAIT_READ    0x01
 #define NET_WAIT_WRITE   0x02
 #define NET_WAIT_CONNECT 0x04
@@ -127,45 +121,43 @@
 JNIEXPORT void JNICALL Java_java_net_NetworkInterface_init(JNIEnv *env, jclass cls);
 
 JNIEXPORT void JNICALL NET_ThrowNew(JNIEnv *env, int errorNum, char *msg);
+
 int NET_GetError();
 
 void NET_ThrowCurrent(JNIEnv *env, char *msg);
 
 jfieldID NET_GetFileDescriptorID(JNIEnv *env);
 
-JNIEXPORT jint JNICALL ipv6_available() ;
+JNIEXPORT jint JNICALL ipv6_available();
 
-JNIEXPORT jint JNICALL reuseport_available() ;
+JNIEXPORT jint JNICALL reuseport_available();
 
 JNIEXPORT int JNICALL
-NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port, struct sockaddr *him, int *len, jboolean v4MappedAddress);
+NET_InetAddressToSockaddr(JNIEnv *env, jobject iaObj, int port,
+                          struct sockaddr *him, int *len,
+                          jboolean v4MappedAddress);
 
 JNIEXPORT jobject JNICALL
 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
 
 void platformInit();
+
 void parseExclusiveBindProperty(JNIEnv *env);
 
-void
-NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+void NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
 
-JNIEXPORT jint JNICALL
-NET_GetPortFromSockaddr(struct sockaddr *him);
+JNIEXPORT jint JNICALL NET_GetPortFromSockaddr(struct sockaddr *him);
 
 JNIEXPORT jint JNICALL
 NET_SockaddrEqualsInetAddress(JNIEnv *env,struct sockaddr *him, jobject iaObj);
 
-int
-NET_IsIPv4Mapped(jbyte* caddr);
+int NET_IsIPv4Mapped(jbyte* caddr);
 
-int
-NET_IPv4MappedToIPv4(jbyte* caddr);
+int NET_IPv4MappedToIPv4(jbyte* caddr);
 
-int
-NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
+int NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
 
-int
-NET_IsZeroAddr(jbyte* caddr);
+int NET_IsZeroAddr(jbyte* caddr);
 
 /* Socket operations
  *
@@ -191,9 +183,9 @@
 JNIEXPORT jint JNICALL
 NET_EnableFastTcpLoopback(int fd);
 
-int getScopeID (struct sockaddr *);
+int getScopeID(struct sockaddr *);
 
-int cmpScopeID (unsigned int, struct sockaddr *);
+int cmpScopeID(unsigned int, struct sockaddr *);
 
 unsigned short in_cksum(unsigned short *addr, int len);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/conf/s390x/jvm.cfg	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,34 @@
+# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+# List of JVMs that can be used as an option to java, javac, etc.
+# Order is important -- first in this list is the default JVM.
+# NOTE that this both this file and its format are UNSUPPORTED and
+# WILL GO AWAY in a future release.
+#
+# You may also select a JVM in an arbitrary location with the
+# "-XXaltjvm=<jvm_dir>" option, but that too is unsupported
+# and may not be available in a future release.
+#
+-server KNOWN
+-client IGNORE
--- a/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/Inet4AddressImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,27 +22,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <ctype.h>
 #include <errno.h>
-#include <sys/time.h>
 #include <sys/types.h>
-#include <sys/socket.h>
+#include <netinet/in.h>
 #include <netinet/in_systm.h>
-#include <netinet/in.h>
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
-#include <netdb.h>
+#include <stdlib.h>
 #include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
+#include <sys/time.h>
 
-#ifdef _ALLBSD_SOURCE
-#include <unistd.h>
-#include <sys/param.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
 
 #include "java_net_Inet4AddressImpl.h"
@@ -293,13 +283,12 @@
     addr |= ((caddr[2] <<8) & 0xff00);
     addr |= (caddr[3] & 0xff);
     memset((char *) &him4, 0, sizeof(him4));
-    him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+    him4.sin_addr.s_addr = htonl(addr);
     him4.sin_family = AF_INET;
     sa = (struct sockaddr *) &him4;
     len = sizeof(him4);
 
-    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
-                               NI_NAMEREQD);
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
 
     if (!error) {
         ret = (*env)->NewStringUTF(env, host);
@@ -443,7 +432,7 @@
 
             if (!skip) {
                 struct addrinfo *next
-                    = (struct addrinfo*) malloc(sizeof(struct addrinfo));
+                    = (struct addrinfo *)malloc(sizeof(struct addrinfo));
                 if (!next) {
                     JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
                     ret = NULL;
@@ -528,13 +517,12 @@
     addr |= ((caddr[2] <<8) & 0xff00);
     addr |= (caddr[3] & 0xff);
     memset((void *) &him4, 0, sizeof(him4));
-    him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+    him4.sin_addr.s_addr = htonl(addr);
     him4.sin_family = AF_INET;
     sa = (struct sockaddr *) &him4;
     len = sizeof(him4);
 
-    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
-                        NI_NAMEREQD);
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
 
     if (!error) {
         ret = (*env)->NewStringUTF(env, host);
--- a/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/Inet6AddressImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,29 +22,21 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <ctype.h>
 #include <errno.h>
+#include <stdlib.h>
+#include <string.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
-#include <netdb.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <ctype.h>
-#ifdef MACOSX
+#include <netinet/icmp6.h>
+
+#if defined(_ALLBSD_SOURCE)
 #include <ifaddrs.h>
 #include <net/if.h>
-#include <unistd.h> /* gethostname */
 #endif
 
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
-#ifndef IPV6_DEFS_H
-#include <netinet/icmp6.h>
-#endif
 
 #include "java_net_Inet4AddressImpl.h"
 #include "java_net_Inet6AddressImpl.h"
@@ -80,7 +72,7 @@
         hostname[NI_MAXHOST] = '\0';
     }
 
-#if defined(__solaris__) && defined(AF_INET6)
+#if defined(__solaris__)
     if (ret == 0) {
         /* Solaris doesn't want to give us a fully qualified domain name.
          * We do a reverse lookup to try and get one.  This works
@@ -259,9 +251,7 @@
     int retLen = 0;
 
     int getaddrinfo_error=0;
-#ifdef AF_INET6
     struct addrinfo hints, *res, *resNew = NULL;
-#endif /* AF_INET6 */
 
     initInetAddressIDs(env);
     JNU_CHECK_EXCEPTION_RETURN(env, NULL);
@@ -273,7 +263,6 @@
     hostname = JNU_GetStringPlatformChars(env, host, JNI_FALSE);
     CHECK_NULL_RETURN(hostname, NULL);
 
-#ifdef AF_INET6
     /* Try once, with our static buffer. */
     memset(&hints, 0, sizeof(hints));
     hints.ai_flags = AI_CANONNAME;
@@ -467,7 +456,6 @@
     }
 
     freeaddrinfo(res);
-#endif /* AF_INET6 */
 
     return ret;
 }
@@ -483,7 +471,6 @@
 
     jstring ret = NULL;
 
-#ifdef AF_INET6
     char host[NI_MAXHOST+1];
     int error = 0;
     int len = 0;
@@ -504,30 +491,28 @@
         addr |= ((caddr[2] <<8) & 0xff00);
         addr |= (caddr[3] & 0xff);
         memset((void *) &him4, 0, sizeof(him4));
-        him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+        him4.sin_addr.s_addr = htonl(addr);
         him4.sin_family = AF_INET;
-        sa = (struct sockaddr *) &him4;
+        sa = (struct sockaddr *)&him4;
         len = sizeof(him4);
     } else {
         /*
          * For IPv6 address construct a sockaddr_in6 structure.
          */
         (*env)->GetByteArrayRegion(env, addrArray, 0, 16, caddr);
-        memset((void *) &him6, 0, sizeof(him6));
-        memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr) );
+        memset((void *)&him6, 0, sizeof(him6));
+        memcpy((void *)&(him6.sin6_addr), caddr, sizeof(struct in6_addr));
         him6.sin6_family = AF_INET6;
-        sa = (struct sockaddr *) &him6 ;
-        len = sizeof(him6) ;
+        sa = (struct sockaddr *)&him6;
+        len = sizeof(him6);
     }
 
-    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0,
-                        NI_NAMEREQD);
+    error = getnameinfo(sa, len, host, NI_MAXHOST, NULL, 0, NI_NAMEREQD);
 
     if (!error) {
         ret = (*env)->NewStringUTF(env, host);
         CHECK_NULL_RETURN(ret, NULL);
     }
-#endif /* AF_INET6 */
 
     if (ret == NULL) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "UnknownHostException", NULL);
@@ -542,7 +527,6 @@
         fcntl(fd, F_SETFL, flags);      \
 }
 
-#ifdef AF_INET6
 static jboolean
 ping6(JNIEnv *env, jint fd, struct sockaddr_in6* him, jint timeout,
       struct sockaddr_in6* netif, jint ttl) {
@@ -649,7 +633,6 @@
     close(fd);
     return JNI_FALSE;
 }
-#endif /* AF_INET6 */
 
 /*
  * Class:     java_net_Inet6AddressImpl
@@ -663,7 +646,6 @@
                                            jint timeout,
                                            jbyteArray ifArray,
                                            jint ttl, jint if_scope) {
-#ifdef AF_INET6
     jbyte caddr[16];
     jint fd, sz;
     struct sockaddr_in6 him6;
@@ -812,7 +794,4 @@
         close(fd);
         return JNI_FALSE;
     }
-#else /* AF_INET6 */
-    return JNI_FALSE;
-#endif /* AF_INET6 */
 }
--- a/jdk/src/java.base/unix/native/libnet/InetAddressImplFactory.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/InetAddressImplFactory.c	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2001, 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
@@ -37,14 +37,10 @@
  * Signature: ()I
  */
 JNIEXPORT jboolean JNICALL
-Java_java_net_InetAddressImplFactory_isIPv6Supported(JNIEnv *env, jclass cls)
-{
-#ifdef AF_INET6
+Java_java_net_InetAddressImplFactory_isIPv6Supported(JNIEnv *env, jclass cls) {
     if (ipv6_available()) {
         return JNI_TRUE;
-    } else
-#endif /* AF_INET6 */
-        {
-            return JNI_FALSE;
-        }
+    } else {
+        return JNI_FALSE;
+    }
 }
--- a/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/NetworkInterface.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,55 +22,36 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <arpa/inet.h>
 #include <errno.h>
-#include <strings.h>
-#include <netinet/in.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
 #include <net/if.h>
 #include <net/if_arp.h>
-
-#if defined(__solaris__)
-#include <sys/dlpi.h>
-#include <fcntl.h>
-#include <stropts.h>
-#include <sys/sockio.h>
-#endif
-
-#if defined(__linux__)
+#include <stdlib.h>
+#include <string.h>
 #include <sys/ioctl.h>
-#include <sys/utsname.h>
-#include <stdio.h>
-#endif
 
 #if defined(_AIX)
-#include <sys/ioctl.h>
 #include <netinet/in6_var.h>
 #include <sys/ndd_var.h>
 #include <sys/kinfo.h>
 #endif
 
-#if defined(_ALLBSD_SOURCE)
-#include <sys/param.h>
-#include <sys/ioctl.h>
+#if defined(__solaris__)
+#include <stropts.h>
+#include <sys/dlpi.h>
 #include <sys/sockio.h>
-#if defined(__APPLE__)
+#endif
+
+#if defined(_ALLBSD_SOURCE)
 #include <net/ethernet.h>
-#include <net/if_var.h>
 #include <net/if_dl.h>
-#include <netinet/in_var.h>
 #include <ifaddrs.h>
 #endif
-#endif
 
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
 
+#include "java_net_InetAddress.h"
+
 #if defined(__linux__)
     #define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
 #elif defined(__solaris__)
@@ -145,10 +126,7 @@
 
 static netif  *enumInterfaces(JNIEnv *env);
 static netif  *enumIPv4Interfaces(JNIEnv *env, int sock, netif *ifs);
-
-#if defined(AF_INET6)
 static netif  *enumIPv6Interfaces(JNIEnv *env, int sock, netif *ifs);
-#endif
 
 static netif  *addif(JNIEnv *env, int sock, const char *if_name, netif *ifs,
                      struct sockaddr *ifr_addrP,
@@ -331,11 +309,8 @@
   (JNIEnv *env, jclass cls, jobject iaObj)
 {
     netif *ifs, *curr;
-#if defined(AF_INET6)
-    int family = (getInetAddress_family(env, iaObj) == IPv4) ? AF_INET : AF_INET6;
-#else
-    int family =  AF_INET;
-#endif
+    int family = (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) ?
+        AF_INET : AF_INET6;
     jobject obj = NULL;
     jboolean match = JNI_FALSE;
 
@@ -361,9 +336,7 @@
                         match = JNI_TRUE;
                         break;
                     }
-                }
-#if defined(AF_INET6)
-                if (family == AF_INET6) {
+                } else if (family == AF_INET6) {
                     jbyte *bytes = (jbyte *)&(
                         ((struct sockaddr_in6*)addrP->addr)->sin6_addr);
                     jbyte caddr[16];
@@ -381,7 +354,6 @@
                         break;
                     }
                 }
-#endif
             }
 
             if (match) {
@@ -725,7 +697,6 @@
                 return NULL;
             }
         }
-#if defined(AF_INET6)
         if (addrP->family == AF_INET6) {
             int scope=0;
             iaObj = (*env)->NewObject(env, ia6_class, ia6_ctrID);
@@ -754,7 +725,6 @@
                 return NULL;
             }
         }
-#endif
 
         (*env)->SetObjectArrayElement(env, addrArr, addr_index++, iaObj);
         addrP = addrP->next;
@@ -815,25 +785,23 @@
     }
 
     // If IPv6 is available then enumerate IPv6 addresses.
-#if defined(AF_INET6)
-        // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
-        // so we have to call ipv6_available()
-        if (ipv6_available()) {
-            sock = openSocket(env, AF_INET6);
-            if (sock < 0 && (*env)->ExceptionOccurred(env)) {
-                freeif(ifs);
-                return NULL;
-            }
+    // User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
+    // so we have to call ipv6_available()
+    if (ipv6_available()) {
+        sock = openSocket(env, AF_INET6);
+        if (sock < 0 && (*env)->ExceptionOccurred(env)) {
+            freeif(ifs);
+            return NULL;
+        }
 
-            ifs = enumIPv6Interfaces(env, sock, ifs);
-            close(sock);
+        ifs = enumIPv6Interfaces(env, sock, ifs);
+        close(sock);
 
-            if ((*env)->ExceptionOccurred(env)) {
-                freeif(ifs);
-                return NULL;
-            }
+        if ((*env)->ExceptionOccurred(env)) {
+            freeif(ifs);
+            return NULL;
         }
-#endif
+    }
 
     return ifs;
 }
@@ -889,12 +857,8 @@
 
     // Allocate for addr and brdcast at once
 
-#if defined(AF_INET6)
     addr_size = (family == AF_INET) ? sizeof(struct sockaddr_in)
                                     : sizeof(struct sockaddr_in6);
-#else
-    addr_size = sizeof(struct sockaddr_in);
-#endif
 
     CHECKED_MALLOC3(addrP, netaddr *, sizeof(netaddr) + 2 * addr_size);
     addrP->addr = (struct sockaddr *)((char *)addrP + sizeof(netaddr));
@@ -1083,7 +1047,6 @@
 /** Linux **/
 #if defined(__linux__)
 
-#if defined(AF_INET6)
 /*
  * Opens a socket for further ioctl calls. Tries AF_INET socket first and
  * if it fails return AF_INET6 socket.
@@ -1109,11 +1072,6 @@
     // IPv6 socket regardless of type of address of an interface.
     return sock;
 }
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
-    return openSocket(env, AF_INET);
-}
-#endif
 
 /*
  * Enumerates and returns all IPv4 interfaces on Linux.
@@ -1197,8 +1155,6 @@
     return ifs;
 }
 
-#if defined(AF_INET6)
-
 /*
  * Enumerates and returns all IPv6 interfaces on Linux.
  */
@@ -1240,8 +1196,6 @@
     return ifs;
 }
 
-#endif /* AF_INET6 */
-
 /*
  * Try to get the interface index.
  */
@@ -1330,7 +1284,6 @@
 /** AIX **/
 #if defined(_AIX)
 
-#if defined(AF_INET6)
 /*
  * Opens a socket for further ioctl calls. Tries AF_INET socket first and
  * if it fails return AF_INET6 socket.
@@ -1354,11 +1307,6 @@
 
     return sock;
 }
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
-    return openSocket(env, AF_INET);
-}
-#endif
 
 /*
  * Enumerates and returns all IPv4 interfaces on AIX.
@@ -1442,8 +1390,6 @@
     return ifs;
 }
 
-#if defined(AF_INET6)
-
 /*
  * Enumerates and returns all IPv6 interfaces on AIX.
  */
@@ -1518,8 +1464,6 @@
     return ifs;
 }
 
-#endif /* AF_INET6 */
-
 /*
  * Try to get the interface index.
  */
@@ -1614,7 +1558,6 @@
 /** Solaris **/
 #if defined(__solaris__)
 
-#if defined(AF_INET6)
 /*
  * Opens a socket for further ioctl calls. Tries AF_INET socket first and
  * if it fails return AF_INET6 socket.
@@ -1659,11 +1602,6 @@
 
     return sock;
 }
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
-    return openSocket(env, AF_INET);
-}
-#endif
 
 /*
  * Enumerates and returns all IPv4 interfaces on Solaris.
@@ -1739,8 +1677,6 @@
     return ifs;
 }
 
-#if defined(AF_INET6)
-
 /*
  * Enumerates and returns all IPv6 interfaces on Solaris.
  */
@@ -1803,8 +1739,6 @@
     return ifs;
 }
 
-#endif /* AF_INET6 */
-
 /*
  * Try to get the interface index.
  * (Not supported on Solaris 2.6 or 7)
@@ -1976,7 +1910,6 @@
 /** BSD **/
 #if defined(_ALLBSD_SOURCE)
 
-#if defined(AF_INET6)
 /*
  * Opens a socket for further ioctl calls. Tries AF_INET socket first and
  * if it fails return AF_INET6 socket.
@@ -2000,11 +1933,6 @@
 
     return sock;
 }
-#else
-static int openSocketWithFallback(JNIEnv *env, const char *ifname) {
-    return openSocket(env, AF_INET);
-}
-#endif
 
 /*
  * Enumerates and returns all IPv4 interfaces on BSD.
@@ -2050,8 +1978,6 @@
     return ifs;
 }
 
-#if defined(AF_INET6)
-
 /*
  * Enumerates and returns all IPv6 interfaces on BSD.
  */
@@ -2092,8 +2018,6 @@
     return ifs;
 }
 
-#endif /* AF_INET6 */
-
 /*
  * Try to get the interface index.
  */
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,29 +22,23 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 #include <errno.h>
-#include <netinet/in.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <sys/ioctl.h>
 
-#ifdef __solaris__
-#include <fcntl.h>
-#include <unistd.h>
-#include <stropts.h>
+#if defined(__solaris__)
+#include <sys/filio.h>
+#endif
 
-#ifndef BSD_COMP
-#define BSD_COMP
-#endif
-#endif
+#include "net_util.h"
+
+#include "java_net_PlainDatagramSocketImpl.h"
+#include "java_net_InetAddress.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_SocketOptions.h"
+
 #ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#include <sys/utsname.h>
-#include <netinet/ip.h>
-
 #define IPV6_MULTICAST_IF 17
 #ifndef SO_BSDCOMPAT
 #define SO_BSDCOMPAT  14
@@ -58,7 +52,11 @@
 #endif
 #endif  //  __linux__
 
-#include <sys/ioctl.h>
+#ifdef __solaris__
+#ifndef BSD_COMP
+#define BSD_COMP
+#endif
+#endif
 
 #ifndef IPTOS_TOS_MASK
 #define IPTOS_TOS_MASK 0x1e
@@ -67,12 +65,6 @@
 #define IPTOS_PREC_MASK 0xe0
 #endif
 
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_PlainDatagramSocketImpl.h"
-#include "java_net_NetworkInterface.h"
 /************************************************************************
  * PlainDatagramSocketImpl
  */
@@ -151,9 +143,6 @@
 JNIEXPORT void JNICALL
 Java_java_net_PlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
 
-#ifdef __linux__
-    struct utsname sysinfo;
-#endif
     pdsi_fdID = (*env)->GetFieldID(env, cls, "fd",
                                    "Ljava/io/FileDescriptor;");
     CHECK_NULL(pdsi_fdID);
@@ -310,13 +299,10 @@
 
 #if defined(__linux__) || defined(_ALLBSD_SOURCE)
         memset(&addr, 0, sizeof(addr));
-#ifdef AF_INET6
         if (ipv6_available()) {
             addr.sa6.sin6_family = AF_UNSPEC;
             len = sizeof(struct sockaddr_in6);
-        } else
-#endif
-        {
+        } else {
             addr.sa4.sin_family = AF_UNSPEC;
             len = sizeof(struct sockaddr_in);
         }
@@ -330,12 +316,9 @@
         localPort = NET_GetPortFromSockaddr(&addr.sa);
         if (localPort == 0) {
             localPort = (*env)->GetIntField(env, this, pdsi_localPortID);
-#ifdef AF_INET6
             if (addr.sa.sa_family == AF_INET6) {
                 addr.sa6.sin6_port = htons(localPort);
-            } else
-#endif /* AF_INET6 */
-            {
+            } else {
                 addr.sa4.sin_port = htons(localPort);
             }
 
@@ -443,12 +426,9 @@
 
     (*env)->GetByteArrayRegion(env, packetBuffer, packetBufferOffset, packetBufferLen,
                                (jbyte *)fullPacket);
-#ifdef AF_INET6
     if (trafficClass != 0 && ipv6_available()) {
         NET_SetTrafficClass(&rmtaddr.sa, trafficClass);
     }
-#endif /* AF_INET6 */
-
 
     /*
      * Send the datagram.
@@ -549,11 +529,8 @@
     }
 
     iaObj = NET_SockaddrToInetAddress(env, &rmtaddr.sa, &port);
-#ifdef AF_INET6
-    family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
-#else
-    family = AF_INET;
-#endif
+    family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+        AF_INET : AF_INET6;
     if (family == AF_INET) { /* this API can't handle IPV6 addresses */
         int address = getInetAddress_addr(env, iaObj);
         setInetAddress_addr(env, addressObj, address);
@@ -918,11 +895,7 @@
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     int arg, fd, t = 1;
     char tmpbuf[1024];
-#ifdef AF_INET6
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
-#else
-    int domain = AF_INET;
-#endif
 
     if (IS_NULL(fdObj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -936,7 +909,6 @@
         return;
     }
 
-#ifdef AF_INET6
     /* Disable IPV6_V6ONLY to ensure dual-socket support */
     if (domain == AF_INET6) {
         arg = 0;
@@ -947,7 +919,6 @@
             return;
         }
     }
-#endif /* AF_INET6 */
 
 #ifdef __APPLE__
     arg = 65507;
@@ -987,7 +958,7 @@
      }
 #endif
 
-#if defined (__linux__) && defined (AF_INET6)
+#if defined (__linux__)
     /*
      * On Linux for IPv6 sockets we must set the hop limit
      * to 1 to be compatible with default TTL of 1 for IPv4 sockets.
@@ -1071,7 +1042,7 @@
      */
     for (i = 0; i < len; i++) {
         addr = (*env)->GetObjectArrayElement(env, addrArray, i);
-        if (getInetAddress_family(env, addr) == IPv4) {
+        if (getInetAddress_family(env, addr) == java_net_InetAddress_IPv4) {
             in.s_addr = htonl(getInetAddress_addr(env, addr));
             break;
         }
@@ -1088,7 +1059,6 @@
  * Set outgoing multicast interface designated by a NetworkInterface.
  * Throw exception if failed.
  */
-#ifdef AF_INET6
 static void mcast_set_if_by_if_v6(JNIEnv *env, jobject this, int fd, jobject value) {
     static jfieldID ni_indexID;
     int index;
@@ -1113,9 +1083,7 @@
         }
         return;
     }
-
 }
-#endif /* AF_INET6 */
 
 /*
  * Set outgoing multicast interface designated by an InetAddress.
@@ -1137,7 +1105,6 @@
  * Set outgoing multicast interface designated by an InetAddress.
  * Throw exception if failed.
  */
-#ifdef AF_INET6
 static void mcast_set_if_by_addr_v6(JNIEnv *env, jobject this, int fd, jobject value) {
     static jclass ni_class;
     if (ni_class == NULL) {
@@ -1159,7 +1126,6 @@
 
     mcast_set_if_by_if_v6(env, this, fd, value);
 }
-#endif
 
 /*
  * Sets the multicast interface.
@@ -1191,7 +1157,6 @@
         /*
          * value is an InetAddress.
          */
-#ifdef AF_INET6
 #ifdef __linux__
         mcast_set_if_by_addr_v4(env, this, fd, value);
         if (ipv6_available()) {
@@ -1207,16 +1172,12 @@
             mcast_set_if_by_addr_v4(env, this, fd, value);
         }
 #endif  /* __linux__ */
-#else
-        mcast_set_if_by_addr_v4(env, this, fd, value);
-#endif  /* AF_INET6 */
     }
 
     if (opt == java_net_SocketOptions_IP_MULTICAST_IF2) {
         /*
          * value is a NetworkInterface.
          */
-#ifdef AF_INET6
 #ifdef __linux__
         mcast_set_if_by_if_v4(env, this, fd, value);
         if (ipv6_available()) {
@@ -1232,9 +1193,6 @@
             mcast_set_if_by_if_v4(env, this, fd, value);
         }
 #endif  /* __linux__ */
-#else
-        mcast_set_if_by_if_v4(env, this, fd, value);
-#endif  /* AF_INET6 */
     }
 }
 
@@ -1266,7 +1224,6 @@
 /*
  * Enable/disable local loopback of multicast datagrams.
  */
-#ifdef AF_INET6
 static void mcast_set_loop_v6(JNIEnv *env, jobject this, int fd, jobject value) {
     jclass cls;
     jfieldID fid;
@@ -1289,14 +1246,12 @@
     }
 
 }
-#endif  /* AF_INET6 */
 
 /*
  * Sets the multicast loopback mode.
  */
 static void setMulticastLoopbackMode(JNIEnv *env, jobject this, int fd,
                                      jint opt, jobject value) {
-#ifdef AF_INET6
 #ifdef __linux__
     mcast_set_loop_v4(env, this, fd, value);
     if (ipv6_available()) {
@@ -1312,9 +1267,6 @@
         mcast_set_loop_v4(env, this, fd, value);
     }
 #endif  /* __linux__ */
-#else
-    mcast_set_loop_v4(env, this, fd, value);
-#endif  /* AF_INET6 */
 }
 
 /*
@@ -1456,11 +1408,9 @@
 jobject getMulticastInterface(JNIEnv *env, jobject this, int fd, jint opt) {
     jboolean isIPV4 = JNI_TRUE;
 
-#ifdef AF_INET6
     if (ipv6_available()) {
         isIPV4 = JNI_FALSE;
     }
-#endif
 
     /*
      * IPv4 implementation
@@ -1559,7 +1509,6 @@
     }
 
 
-#ifdef AF_INET6
     /*
      * IPv6 implementation
      */
@@ -1677,7 +1626,6 @@
         }
         return ni;
     }
-#endif
     return NULL;
 }
 
@@ -1815,7 +1763,6 @@
 /*
  * Set hops limit for a socket. Throw exception if failed.
  */
-#ifdef AF_INET6
 static void setHopLimit(JNIEnv *env, int fd, jint ttl) {
     int ittl = (int)ttl;
     if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
@@ -1824,7 +1771,6 @@
             (env, JNU_JAVANETPKG "SocketException", "Error setting socket option");
     }
 }
-#endif
 
 /*
  * Class:     java_net_PlainDatagramSocketImpl
@@ -1847,7 +1793,6 @@
         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
     }
     /* setsockopt to be correct TTL */
-#ifdef AF_INET6
 #ifdef __linux__
     setTTL(env, fd, ttl);
     JNU_CHECK_EXCEPTION(env);
@@ -1861,9 +1806,6 @@
         setTTL(env, fd, ttl);
     }
 #endif  /* __linux__ */
-#else
-    setTTL(env, fd, ttl);
-#endif  /* AF_INET6 */
 }
 
 /*
@@ -1896,7 +1838,6 @@
         fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID);
     }
     /* getsockopt of TTL */
-#ifdef AF_INET6
     if (ipv6_available()) {
         int ttl = 0;
         socklen_t len = sizeof(ttl);
@@ -1908,19 +1849,17 @@
             return -1;
         }
         return (jint)ttl;
-    } else
-#endif /* AF_INET6 */
-        {
-            u_char ttl = 0;
-            socklen_t len = sizeof(ttl);
-            if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
-                           (char*)&ttl, &len) < 0) {
-                JNU_ThrowByNameWithMessageAndLastError
-                    (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
-                return -1;
-            }
-            return (jint)ttl;
+    } else {
+        u_char ttl = 0;
+        socklen_t len = sizeof(ttl);
+        if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
+                       (char*)&ttl, &len) < 0) {
+            JNU_ThrowByNameWithMessageAndLastError
+                (env, JNU_JAVANETPKG "SocketException", "Error getting socket option");
+            return -1;
         }
+        return (jint)ttl;
+    }
 }
 
 
@@ -1966,22 +1905,14 @@
     /*
      * Determine if this is an IPv4 or IPv6 join/leave.
      */
-#ifdef AF_INET6
     ipv6_join_leave = ipv6_available();
 
 #ifdef __linux__
-    if (getInetAddress_family(env, iaObj) == IPv4) {
+    if (getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4) {
         ipv6_join_leave = JNI_FALSE;
     }
 #endif
 
-#else
-    /*
-     * IPv6 not compiled in
-     */
-    ipv6_join_leave = JNI_FALSE;
-#endif
-
     /*
      * For IPv4 join use IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP socket option
      *
@@ -2006,7 +1937,7 @@
          *              NetworkInterface
          */
         if (niObj != NULL) {
-#if defined(__linux__) && defined(AF_INET6)
+#if defined(__linux__)
             if (ipv6_available()) {
                 static jfieldID ni_indexID;
 
@@ -2062,7 +1993,7 @@
 
         if (niObj == NULL) {
 
-#if defined(__linux__) && defined(AF_INET6)
+#if defined(__linux__)
             if (ipv6_available()) {
 
                 int index;
@@ -2118,7 +2049,7 @@
              * should return ENOPROTOOPT. We assume this will be fixed in Linux
              * at some stage.
              */
-#if defined(__linux__) && defined(AF_INET6)
+#if defined(__linux__)
             if (errno == ENOPROTOOPT) {
                 if (ipv6_available()) {
                     ipv6_join_leave = JNI_TRUE;
@@ -2155,14 +2086,14 @@
      * IPv6 join. If it's an IPv4 multicast group then we use an IPv4-mapped
      * address.
      */
-#ifdef AF_INET6
     {
         struct ipv6_mreq mname6;
         jbyteArray ipaddress;
         jbyte caddr[16];
         jint family;
         jint address;
-        family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
+        family = getInetAddress_family(env, iaObj) == java_net_InetAddress_IPv4 ?
+            AF_INET : AF_INET6;
         if (family == AF_INET) { /* will convert to IPv4-mapped address */
             memset((char *) caddr, 0, 16);
             address = getInetAddress_addr(env, iaObj);
@@ -2242,7 +2173,6 @@
             }
         }
     }
-#endif
 }
 
 /*
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,32 +22,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <errno.h>
 
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if defined(__linux__)
-#include <sys/poll.h>
-#endif
-#include <netinet/tcp.h>        /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#ifdef __linux__
-#include <netinet/ip.h>
-#endif
-#include <netdb.h>
-#include <stdlib.h>
-
-#ifdef __solaris__
-#include <fcntl.h>
-#endif
-#ifdef __linux__
-#include <unistd.h>
-#include <sys/sysctl.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
 
 #include "java_net_SocketOptions.h"
@@ -186,11 +162,7 @@
     jobject fdObj, ssObj;
     int fd;
     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
-#ifdef AF_INET6
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
-#else
-    int domain = AF_INET;
-#endif
 
     if (socketExceptionCls == NULL) {
         jclass c = (*env)->FindClass(env, "java/net/SocketException");
@@ -214,7 +186,6 @@
         return;
     }
 
-#ifdef AF_INET6
     /* Disable IPV6_V6ONLY to ensure dual-socket support */
     if (domain == AF_INET6) {
         int arg = 0;
@@ -225,7 +196,6 @@
             return;
         }
     }
-#endif /* AF_INET6 */
 
     /*
      * If this is a server socket then enable SO_REUSEADDR
@@ -295,11 +265,10 @@
     }
     setDefaultScopeID(env, &him.sa);
 
-#ifdef AF_INET6
     if (trafficClass != 0 && ipv6_available()) {
         NET_SetTrafficClass(&him.sa, trafficClass);
     }
-#endif /* AF_INET6 */
+
     if (timeout <= 0) {
         connect_rv = NET_Connect(fd, &him.sa, len);
 #ifdef __solaris__
--- a/jdk/src/java.base/unix/native/libnet/SdpSupport.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c	Fri Nov 11 16:44:36 2016 +0100
@@ -56,11 +56,7 @@
     int s;
 
 #if defined(__solaris__)
-  #ifdef AF_INET6
     int domain = ipv6_available() ? AF_INET6 : AF_INET;
-  #else
-    int domain = AF_INET;
-  #endif
     s = socket(domain, SOCK_STREAM, PROTO_SDP);
 #elif defined(__linux__)
     /**
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,20 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <errno.h>
 #include <stdlib.h>
-#include <errno.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
 
-#include "jvm.h"
-#include "jni_util.h"
 #include "net_util.h"
 
 #include "java_net_SocketInputStream.h"
 
-/************************************************************************
+/*
  * SocketInputStream
  */
 
--- a/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/SocketOutputStream.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,15 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <errno.h>
 #include <stdlib.h>
-#include <errno.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
 
-#include "jni_util.h"
-#include "jvm.h"
 #include "net_util.h"
 
 #include "java_net_SocketOutputStream.h"
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,60 +22,42 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
+#include <dlfcn.h>
 #include <errno.h>
+#include <net/if.h>
+#include <netinet/tcp.h> // defines TCP_NODELAY
+#include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h>        /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#include <net/if.h>
-#include <netdb.h>
-#include <stdlib.h>
-#include <dlfcn.h>
+#include <sys/ioctl.h>
 #include <sys/time.h>
 
-#ifndef _ALLBSD_SOURCE
-#include <values.h>
-#else
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/sysctl.h>
-#include <sys/ioctl.h>
-#ifndef MAXINT
-#define MAXINT INT_MAX
-#endif
-#endif
-
-#ifdef __solaris__
-#include <sys/filio.h>
-#include <sys/sockio.h>
-#include <stropts.h>
-#include <inet/nd.h>
-#endif
-
-#ifdef __linux__
-#include <sys/ioctl.h>
+#if defined(__linux__)
 #include <arpa/inet.h>
 #include <net/route.h>
 #include <sys/utsname.h>
+#endif
 
-#ifndef IPV6_FLOWINFO_SEND
+#if defined(__solaris__)
+#include <inet/nd.h>
+#include <limits.h>
+#include <stropts.h>
+#include <sys/filio.h>
+#include <sys/sockio.h>
+#endif
+
+#include "net_util.h"
+
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
+
+#if defined(__linux__) && !defined(IPV6_FLOWINFO_SEND)
 #define IPV6_FLOWINFO_SEND      33
 #endif
 
-#endif
-
-#ifdef _AIX
-#include <sys/ioctl.h>
+#if defined(__solaris__) && !defined(MAXINT)
+#define MAXINT INT_MAX
 #endif
 
-#include "jni_util.h"
-#include "jvm.h"
-#include "net_util.h"
-
-#include "java_net_SocketOptions.h"
-
 /*
  * EXCLBIND socket options only on Solaris
  */
@@ -324,11 +306,6 @@
 
 jint  IPv6_supported()
 {
-#ifndef AF_INET6
-    return JNI_FALSE;
-#endif
-
-#ifdef AF_INET6
     int fd;
     void *ipv6_fn;
     SOCKETADDRESS sa;
@@ -433,7 +410,6 @@
     } else {
         return JNI_TRUE;
     }
-#endif /* AF_INET6 */
 }
 #endif /* DONT_ENABLE_IPV6 */
 
@@ -484,7 +460,7 @@
     }
 }
 
-#if defined(__linux__) && defined(AF_INET6)
+#if defined(__linux__)
 
 /* following code creates a list of addresses from the kernel
  * routing table that are routed via the loopback address.
@@ -804,15 +780,15 @@
                           int *len, jboolean v4MappedAddress) {
     jint family;
     family = getInetAddress_family(env, iaObj);
-#ifdef AF_INET6
     /* needs work. 1. family 2. clean up him6 etc deallocate memory */
-    if (ipv6_available() && !(family == IPv4 && v4MappedAddress == JNI_FALSE)) {
+    if (ipv6_available() && !(family == java_net_InetAddress_IPv4 &&
+                              v4MappedAddress == JNI_FALSE)) {
         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
         jbyte caddr[16];
         jint address;
 
-
-        if (family == IPv4) { /* will convert to IPv4-mapped address */
+        if (family == java_net_InetAddress_IPv4) {
+            // convert to IPv4-mapped address
             memset((char *) caddr, 0, 16);
             address = getInetAddress_addr(env, iaObj);
             if (address == INADDR_ANY) {
@@ -834,9 +810,9 @@
         him6->sin6_port = htons(port);
         memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
         him6->sin6_family = AF_INET6;
-        *len = sizeof(struct sockaddr_in6) ;
+        *len = sizeof(struct sockaddr_in6);
 
-#if defined(_ALLBSD_SOURCE) && defined(_AF_INET6)
+#if defined(_ALLBSD_SOURCE)
 // XXXBSD: should we do something with scope id here ? see below linux comment
 /* MMM: Come back to this! */
 #endif
@@ -880,11 +856,11 @@
                          * try determine the appropriate interface.
                          */
                         if (kernelIsV24()) {
-                            cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
+                            cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
                         } else {
-                            cached_scope_id = getLocalScopeID( (char *)&(him6->sin6_addr) );
+                            cached_scope_id = getLocalScopeID((char *)&(him6->sin6_addr));
                             if (cached_scope_id == 0) {
-                                cached_scope_id = getDefaultIPv6Interface( &(him6->sin6_addr) );
+                                cached_scope_id = getDefaultIPv6Interface(&(him6->sin6_addr));
                             }
                         }
                         (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
@@ -906,52 +882,44 @@
 #else
         /* handle scope_id for solaris */
 
-        if (family != IPv4) {
+        if (family != java_net_InetAddress_IPv4) {
             if (ia6_scopeidID) {
                 him6->sin6_scope_id = getInet6Address_scopeid(env, iaObj);
             }
         }
 #endif
-    } else
-#endif /* AF_INET6 */
-        {
-            struct sockaddr_in *him4 = (struct sockaddr_in*)him;
-            jint address;
-            if (family == IPv6) {
-              JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
-              return -1;
-            }
-            memset((char *) him4, 0, sizeof(struct sockaddr_in));
-            address = getInetAddress_addr(env, iaObj);
-            him4->sin_port = htons((short) port);
-            him4->sin_addr.s_addr = (uint32_t) htonl(address);
-            him4->sin_family = AF_INET;
-            *len = sizeof(struct sockaddr_in);
+    } else {
+        struct sockaddr_in *him4 = (struct sockaddr_in *)him;
+        jint address;
+        if (family == java_net_InetAddress_IPv6) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Protocol family unavailable");
+            return -1;
         }
+        memset((char *)him4, 0, sizeof(struct sockaddr_in));
+        address = getInetAddress_addr(env, iaObj);
+        him4->sin_port = htons((short) port);
+        him4->sin_addr.s_addr = htonl(address);
+        him4->sin_family = AF_INET;
+        *len = sizeof(struct sockaddr_in);
+    }
     return 0;
 }
 
 void
 NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
-#ifdef AF_INET6
     if (him->sa_family == AF_INET6) {
         struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
         him6->sin6_flowinfo = htonl((trafficClass & 0xff) << 20);
     }
-#endif /* AF_INET6 */
 }
 
 JNIEXPORT jint JNICALL
 NET_GetPortFromSockaddr(struct sockaddr *him) {
-#ifdef AF_INET6
     if (him->sa_family == AF_INET6) {
         return ntohs(((struct sockaddr_in6*)him)->sin6_port);
-
-        } else
-#endif /* AF_INET6 */
-            {
-                return ntohs(((struct sockaddr_in*)him)->sin_port);
-            }
+    } else {
+        return ntohs(((struct sockaddr_in*)him)->sin_port);
+    }
 }
 
 int
@@ -1024,7 +992,6 @@
 
     int i;
 
-#ifdef AF_INET6
     if (ipv6_available()) {
         switch (cmd) {
             // Different multicast options if IPv6 is enabled
@@ -1047,7 +1014,6 @@
 #endif
         }
     }
-#endif
 
     /*
      * Map the Java level option to the native level
@@ -1079,7 +1045,7 @@
  *       0 if no matching interface
  *      >1 interface index to use for the link-local address.
  */
-#if defined(__linux__) && defined(AF_INET6)
+#if defined(__linux__)
 int getDefaultIPv6Interface(struct in6_addr *target_addr) {
     FILE *f;
     char srcp[8][5];
@@ -1316,7 +1282,7 @@
     if (level == IPPROTO_IP && opt == IP_TOS) {
         int *iptos;
 
-#if defined(AF_INET6) && defined(__linux__)
+#if defined(__linux__)
         if (ipv6_available()) {
             int optval = 1;
             if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
@@ -1520,7 +1486,7 @@
 int
 NET_Bind(int fd, struct sockaddr *him, int len)
 {
-#if defined(__solaris__) && defined(AF_INET6)
+#if defined(__solaris__)
     int level = -1;
     int exclbind = -1;
 #endif
@@ -1584,7 +1550,7 @@
 
     rv = bind(fd, him, len);
 
-#if defined(__solaris__) && defined(AF_INET6)
+#if defined(__solaris__)
     if (rv < 0) {
         int en = errno;
         /* Restore *_EXCLBIND if the bind fails */
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h	Fri Nov 11 16:44:36 2016 +0100
@@ -26,13 +26,9 @@
 #ifndef NET_UTILS_MD_H
 #define NET_UTILS_MD_H
 
+#include <netdb.h>
+#include <sys/poll.h>
 #include <sys/socket.h>
-#include <sys/types.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#include <sys/poll.h>
 
 int NET_Timeout(int s, long timeout);
 int NET_Timeout0(int s, long timeout, long currentTime);
@@ -88,18 +84,11 @@
 #define MAX_HEAP_BUFFER_LEN 65536
 #endif
 
-#ifdef AF_INET6
 typedef union {
     struct sockaddr     sa;
     struct sockaddr_in  sa4;
     struct sockaddr_in6 sa6;
 } SOCKETADDRESS;
-#else
-typedef union {
-    struct sockaddr     sa;
-    struct sockaddr_in  sa4;
-} SOCKETADDRESS;
-#endif
 
 /************************************************************************
  *  Utilities
@@ -107,10 +96,8 @@
 
 #ifdef __linux__
 int kernelIsV24();
-#ifdef AF_INET6
 int getDefaultIPv6Interface(struct in6_addr *target_addr);
 #endif
-#endif
 
 #ifdef __solaris__
 int net_getParam(char *driver, char *param);
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,10 +22,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
 #include "net_util.h"
+
 #include "java_net_DualStackPlainDatagramSocketImpl.h"
 
 /*
--- a/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,11 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include <windows.h>
-#include <winsock2.h>
-#include "jni.h"
 #include "net_util.h"
+
 #include "java_net_DualStackPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
 
 #define SET_BLOCKING 0
 #define SET_NONBLOCKING 1
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,24 +22,12 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <malloc.h>
 
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
-#include <WinError.h>
+#include "net_util.h"
 
 #include "java_net_InetAddress.h"
 #include "java_net_Inet4AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
 
 /*
  * Returns true if hostname is in dotted IP address format. Note that this
--- a/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/Inet6AddressImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,38 +22,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <malloc.h>
 
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
-#include <process.h>
-#include <iphlpapi.h>
-#include <icmpapi.h>
+#include "net_util.h"
 
 #include "java_net_InetAddress.h"
 #include "java_net_Inet4AddressImpl.h"
 #include "java_net_Inet6AddressImpl.h"
-#include "net_util.h"
-#include "icmp.h"
-
-#ifdef WIN32
-#ifndef _WIN64
-
-/* Retain this code a little longer to support building in
- * old environments.  _MSC_VER is defined as:
- *     1200 for MSVC++ 6.0
- *     1310 for Vc7
- */
-#if defined(_MSC_VER) && _MSC_VER < 1310
-#define sockaddr_in6 SOCKADDR_IN6
-#endif
-#endif
-#define uint32_t UINT32
-#endif
 
 /*
  * Inet6AddressImpl
@@ -300,7 +275,7 @@
         addr |= ((caddr[2] <<8) & 0xff00);
         addr |= (caddr[3] & 0xff);
         memset((char *) &him4, 0, sizeof(him4));
-        him4.sin_addr.s_addr = (uint32_t) htonl(addr);
+        him4.sin_addr.s_addr = htonl(addr);
         him4.sin_family = AF_INET;
         sa = (struct sockaddr *) &him4;
         len = sizeof(him4);
@@ -330,8 +305,6 @@
     return ret;
 }
 
-#ifdef AF_INET6
-
 /**
  * ping implementation using tcp port 7 (echo)
  */
@@ -493,7 +466,6 @@
         return JNI_FALSE;
     }
 }
-#endif /* AF_INET6 */
 
 /*
  * Class:     java_net_Inet6AddressImpl
@@ -507,7 +479,6 @@
                                            jint timeout,
                                            jbyteArray ifArray,
                                            jint ttl, jint if_scope) {
-#ifdef AF_INET6
     jbyte caddr[16];
     jint sz;
     struct sockaddr_in6 him6;
@@ -573,6 +544,5 @@
         return ping6(env, netif, &him6, timeout, hIcmpFile);
     }
 
-#endif /* AF_INET6 */
     return JNI_FALSE;
 }
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,17 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h>           /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
 
 #include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
 
 /*
  * Windows implementation of the java.net.NetworkInterface native methods.
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface.h	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -26,7 +26,6 @@
 #ifndef NETWORK_INTERFACE_H
 #define NETWORK_INTERFACE_H
 
-#include <iphlpapi.h>
 #include "net_util.h"
 
 /*
--- a/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/NetworkInterface_winXP.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,19 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-#include <stdlib.h>
-#include <windows.h>
-#include <winsock2.h>           /* needed for htonl */
-#include <iprtrmib.h>
-#include <assert.h>
-#include <limits.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
 
 #include "java_net_NetworkInterface.h"
-#include "jni_util.h"
-
-#include "NetworkInterface.h"
-#include "net_util.h"
 
 /*
  * Windows implementation of the java.net.NetworkInterface native methods.
--- a/jdk/src/java.base/windows/native/libnet/SocketInputStream.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/SocketInputStream.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,24 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <malloc.h>
 
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
 
 #include "java_net_SocketInputStream.h"
 
-#include "net_util.h"
-#include "jni_util.h"
-
 /*************************************************************************
  * SocketInputStream
  */
-
 static jfieldID IO_fd_fdID;
 
 /*
--- a/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/SocketOutputStream.c	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, 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
@@ -22,20 +22,12 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <malloc.h>
 
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
 
 #include "java_net_SocketOutputStream.h"
 
-#include "net_util.h"
-#include "jni_util.h"
-
 /************************************************************************
  * SocketOutputStream
  */
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,15 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include <malloc.h>
 
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <malloc.h>
-#include <sys/types.h>
+#include "net_util.h"
+#include "NetworkInterface.h"
+
+#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_NetworkInterface.h"
+#include "java_net_InetAddress.h"
 
 #ifndef IPTOS_TOS_MASK
 #define IPTOS_TOS_MASK 0x1e
@@ -39,14 +39,6 @@
 #define IPTOS_PREC_MASK 0xe0
 #endif
 
-#include "java_net_TwoStacksPlainDatagramSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_NetworkInterface.h"
-
-#include "NetworkInterface.h"
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
 
 #define IN_CLASSD(i)    (((long)(i) & 0xf0000000) == 0xe0000000)
 #define IN_MULTICAST(i) IN_CLASSD(i)
@@ -439,7 +431,7 @@
     memset((char *)&lcladdr, 0, sizeof(lcladdr));
 
     family = getInetAddress_family(env, addressObj);
-    if (family == IPv6 && !ipv6_supported) {
+    if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Protocol family not supported");
         return;
@@ -561,13 +553,13 @@
     addr = getInetAddress_addr(env, address);
 
     family = getInetAddress_family(env, address);
-    if (family == IPv6 && !ipv6_supported) {
+    if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Protocol family not supported");
         return;
     }
 
-    fdc = family == IPv4? fd: fd1;
+    fdc = family == java_net_InetAddress_IPv4 ? fd : fd1;
 
     if (xp_or_later) {
         /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
@@ -605,12 +597,12 @@
     jint fd, len;
     SOCKETADDRESS addr;
 
-    if (family == IPv4) {
+    if (family == java_net_InetAddress_IPv4) {
         fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
-        len = sizeof (struct sockaddr_in);
+        len = sizeof(struct sockaddr_in);
     } else {
         fdObj = (*env)->GetObjectField(env, this, pdsi_fd1ID);
-        len = sizeof (struct SOCKADDR_IN6);
+        len = sizeof(struct sockaddr_in6);
     }
 
     if (IS_NULL(fdObj)) {
@@ -678,7 +670,7 @@
     }
 
     family = getInetAddress_family(env, iaObj);
-    if (family == IPv4) {
+    if (family == java_net_InetAddress_IPv4) {
         fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
     } else {
         if (!ipv6_available()) {
@@ -906,7 +898,7 @@
         return 0;
     }
     setInetAddress_addr(env, addressObj, ntohl(remote_addr.sa4.sin_addr.s_addr));
-    setInetAddress_family(env, addressObj, IPv4);
+    setInetAddress_family(env, addressObj, java_net_InetAddress_IPv4);
 
     /* return port */
     return ntohs(remote_addr.sa4.sin_port);
@@ -1610,7 +1602,7 @@
 {
     jobject addr;
 
-    int ret = getInetAddrFromIf (env, IPv4, nif, &addr);
+    int ret = getInetAddrFromIf(env, java_net_InetAddress_IPv4, nif, &addr);
     if (ret == -1) {
         return -1;
     }
@@ -2285,9 +2277,9 @@
     len = sizeof(struct sockaddr_in);
 
     /* family==-1 when socket is not connected */
-    if ((family == IPv6) || (family == -1 && fd == -1)) {
+    if ((family == java_net_InetAddress_IPv6) || (family == -1 && fd == -1)) {
         fd = fd1; /* must be IPv6 only */
-        len = sizeof (struct SOCKADDR_IN6);
+        len = sizeof(struct sockaddr_in6);
     }
 
     if (fd == -1) {
--- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,23 +22,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
-#include <windows.h>
-#include <winsock2.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <malloc.h>
-#include <sys/types.h>
-
-#include "java_net_SocketOptions.h"
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_InetAddress.h"
-#include "java_io_FileDescriptor.h"
-#include "java_lang_Integer.h"
 
 #include "net_util.h"
-#include "jni_util.h"
+
+#include "java_net_TwoStacksPlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
+#include "java_net_InetAddress.h"
 
 /************************************************************************
  * TwoStacksPlainSocketImpl
@@ -413,7 +403,7 @@
 
     family = getInetAddress_family(env, iaObj);
 
-    if (family == IPv6 && !ipv6_supported) {
+    if (family == java_net_InetAddress_IPv6 && !ipv6_supported) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Protocol family not supported");
         return;
@@ -655,18 +645,18 @@
             return;
         }
         if (fd2 == fd) { /* v4 */
-            len = sizeof (struct sockaddr_in);
+            len = sizeof(struct sockaddr_in);
         } else {
-            len = sizeof (struct SOCKADDR_IN6);
+            len = sizeof(struct sockaddr_in6);
         }
         fd = fd2;
     } else {
         int ret;
         if (fd1 != -1) {
             fd = fd1;
-            len = sizeof (struct SOCKADDR_IN6);
+            len = sizeof(struct sockaddr_in6);
         } else {
-            len = sizeof (struct sockaddr_in);
+            len = sizeof(struct sockaddr_in);
         }
         if (timeout) {
             ret = NET_Timeout(fd, timeout);
@@ -728,7 +718,7 @@
         }
 
         setInetAddress_addr(env, socketAddressObj, ntohl(him.sa4.sin_addr.s_addr));
-        setInetAddress_family(env, socketAddressObj, IPv4);
+        setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv4);
         (*env)->SetObjectField(env, socket, psi_addressID, socketAddressObj);
     } else {
         /* AF_INET6 -> Inet6Address */
@@ -754,7 +744,7 @@
             return;
         }
         setInet6Address_ipaddress(env, socketAddressObj, (char *)&him.sa6.sin6_addr);
-        setInetAddress_family(env, socketAddressObj, IPv6);
+        setInetAddress_family(env, socketAddressObj, java_net_InetAddress_IPv6);
         setInet6Address_scopeid(env, socketAddressObj, him.sa6.sin6_scope_id);
 
     }
--- a/jdk/src/java.base/windows/native/libnet/icmp.h	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef ICMP_H
-#define ICMP_H
-
-/*
- * Structure of an internet header, naked of options.
- *
- * We declare ip_len and ip_off to be short, rather than ushort_t
- * pragmatically since otherwise unsigned comparisons can result
- * against negative integers quite easily, and fail in subtle ways.
- */
-struct ip {
-        unsigned char   ip_hl:4,        /* header length */
-                        ip_v:4;         /* version */
-        unsigned char   ip_tos;                 /* type of service */
-        short   ip_len;                 /* total length */
-        unsigned short ip_id;                   /* identification */
-        short   ip_off;                 /* fragment offset field */
-#define IP_DF 0x4000                    /* don't fragment flag */
-#define IP_MF 0x2000                    /* more fragments flag */
-        unsigned char   ip_ttl;                 /* time to live */
-        unsigned char   ip_p;                   /* protocol */
-        unsigned short ip_sum;          /* checksum */
-        struct  in_addr ip_src, ip_dst; /* source and dest address */
-};
-
-/*
- * Structure of an icmp header.
- */
-struct icmp {
-        unsigned char   icmp_type;              /* type of message, see below */
-        unsigned char   icmp_code;              /* type sub code */
-        unsigned short icmp_cksum;              /* ones complement cksum of struct */
-        union {
-                unsigned char ih_pptr;          /* ICMP_PARAMPROB */
-                struct in_addr ih_gwaddr;       /* ICMP_REDIRECT */
-                struct ih_idseq {
-                        unsigned short icd_id;
-                        unsigned short icd_seq;
-                } ih_idseq;
-                int ih_void;
-
-                /* ICMP_UNREACH_NEEDFRAG -- Path MTU Discovery (RFC1191) */
-                struct ih_pmtu {
-                        unsigned short ipm_void;
-                        unsigned short ipm_nextmtu;
-                } ih_pmtu;
-
-                struct ih_rtradv {
-                        unsigned char irt_num_addrs;
-                        unsigned char irt_wpa;
-                        unsigned short irt_lifetime;
-                } ih_rtradv;
-        } icmp_hun;
-#define icmp_pptr       icmp_hun.ih_pptr
-#define icmp_gwaddr     icmp_hun.ih_gwaddr
-#define icmp_id         icmp_hun.ih_idseq.icd_id
-#define icmp_seq        icmp_hun.ih_idseq.icd_seq
-#define icmp_void       icmp_hun.ih_void
-#define icmp_pmvoid     icmp_hun.ih_pmtu.ipm_void
-#define icmp_nextmtu    icmp_hun.ih_pmtu.ipm_nextmtu
-        union {
-                struct id_ts {
-                        unsigned int its_otime;
-                        unsigned int its_rtime;
-                        unsigned int its_ttime;
-                } id_ts;
-                struct id_ip  {
-                        struct ip idi_ip;
-                        /* options and then 64 bits of data */
-                } id_ip;
-                unsigned int id_mask;
-                char    id_data[1];
-        } icmp_dun;
-#define icmp_otime      icmp_dun.id_ts.its_otime
-#define icmp_rtime      icmp_dun.id_ts.its_rtime
-#define icmp_ttime      icmp_dun.id_ts.its_ttime
-#define icmp_ip         icmp_dun.id_ip.idi_ip
-#define icmp_mask       icmp_dun.id_mask
-#define icmp_data       icmp_dun.id_data
-};
-
-#define ICMP_ECHOREPLY          0               /* echo reply */
-#define ICMP_ECHO               8               /* echo service */
-
-/*
- * ICMPv6 structures & constants
- */
-
-typedef struct icmp6_hdr {
-        u_char   icmp6_type;    /* type field */
-        u_char   icmp6_code;    /* code field */
-        u_short  icmp6_cksum;   /* checksum field */
-        union {
-                u_int icmp6_un_data32[1];       /* type-specific field */
-                u_short icmp6_un_data16[2];     /* type-specific field */
-                u_char  icmp6_un_data8[4];      /* type-specific field */
-        } icmp6_dataun;
-} icmp6_t;
-
-#define icmp6_data32    icmp6_dataun.icmp6_un_data32
-#define icmp6_data16    icmp6_dataun.icmp6_un_data16
-#define icmp6_data8     icmp6_dataun.icmp6_un_data8
-#define icmp6_pptr      icmp6_data32[0] /* parameter prob */
-#define icmp6_mtu       icmp6_data32[0] /* packet too big */
-#define icmp6_id        icmp6_data16[0] /* echo request/reply */
-#define icmp6_seq       icmp6_data16[1] /* echo request/reply */
-#define icmp6_maxdelay  icmp6_data16[0] /* mcast group membership */
-
-struct ip6_pseudo_hdr  /* for calculate the ICMPv6 checksum */
-{
-  struct in6_addr ip6_src;
-  struct in6_addr ip6_dst;
-  u_int       ip6_plen;
-  u_int       ip6_nxt;
-};
-
-#define ICMP6_ECHO_REQUEST      128
-#define ICMP6_ECHO_REPLY        129
-#define IPPROTO_ICMPV6          58
-#define IPV6_UNICAST_HOPS       4  /* Set/get IP unicast hop limit */
-
-
-#endif
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c	Fri Nov 11 16:44:36 2016 +0100
@@ -22,12 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include "net_util.h"
 
-#include <winsock2.h>
-#include <ws2tcpip.h>
-
-#include "net_util.h"
-#include "jni.h"
+#include "java_net_InetAddress.h"
+#include "java_net_SocketOptions.h"
 
 // Taken from mstcpip.h in Windows SDK 8.0 or newer.
 #define SIO_LOOPBACK_FAST_PATH              _WSAIOW(IOC_VENDOR,16)
@@ -593,7 +591,7 @@
 
 
 void dumpAddr (char *str, void *addr) {
-    struct SOCKADDR_IN6 *a = (struct SOCKADDR_IN6 *)addr;
+    struct sockaddr_in6 *a = (struct sockaddr_in6 *)addr;
     int family = a->sin6_family;
     printf ("%s\n", str);
     if (family == AF_INET) {
@@ -812,7 +810,7 @@
  *      0 if error
  *      > 0 interface index to use
  */
-jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
+jint getDefaultIPv6Interface(JNIEnv *env, struct sockaddr_in6 *target_addr)
 {
     int ret;
     DWORD b;
@@ -866,9 +864,9 @@
                           int *len, jboolean v4MappedAddress) {
     jint family, iafam;
     iafam = getInetAddress_family(env, iaObj);
-    family = (iafam == IPv4)? AF_INET : AF_INET6;
+    family = (iafam == java_net_InetAddress_IPv4)? AF_INET : AF_INET6;
     if (ipv6_available() && !(family == AF_INET && v4MappedAddress == JNI_FALSE)) {
-        struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+        struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
         jbyte caddr[16];
         jint address, scopeid = 0;
         jint cached_scope_id = 0;
@@ -894,7 +892,7 @@
             cached_scope_id = (jint)(*env)->GetIntField(env, iaObj, ia6_cachedscopeidID);
         }
 
-        memset((char *)him6, 0, sizeof(struct SOCKADDR_IN6));
+        memset((char *)him6, 0, sizeof(struct sockaddr_in6));
         him6->sin6_port = (u_short) htons((u_short)port);
         memcpy((void *)&(him6->sin6_addr), caddr, sizeof(struct in6_addr) );
         him6->sin6_family = AF_INET6;
@@ -904,7 +902,7 @@
             (*env)->SetIntField(env, iaObj, ia6_cachedscopeidID, cached_scope_id);
         }
         him6->sin6_scope_id = scopeid != 0 ? scopeid : cached_scope_id;
-        *len = sizeof(struct SOCKADDR_IN6) ;
+        *len = sizeof(struct sockaddr_in6) ;
     } else {
         struct sockaddr_in *him4 = (struct sockaddr_in *)him;
         jint address;
@@ -964,12 +962,12 @@
 }
 
 int getScopeID(struct sockaddr *him) {
-    struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
     return him6->sin6_scope_id;
 }
 
 int cmpScopeID(unsigned int scope, struct sockaddr *him) {
-    struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
+    struct sockaddr_in6 *him6 = (struct sockaddr_in6 *)him;
     return him6->sin6_scope_id == scope;
 }
 
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h	Fri Nov 11 16:44:36 2016 +0100
@@ -22,195 +22,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 #include <winsock2.h>
 #include <WS2tcpip.h>
-
-/* typedefs that were defined correctly for the first time
- * in Nov. 2001 SDK, which we need to include here.
- * Specifically, in6_addr and sockaddr_in6 (which is defined but
- * not correctly). When moving to a later SDK remove following
- * code between START and END
- */
-
-/* --- START --- */
-
-/* WIN64 already uses newer SDK */
-#ifdef _WIN64
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-#ifdef _MSC_VER
-#define WS2TCPIP_INLINE __inline
-#else
-#define WS2TCPIP_INLINE extern inline /* GNU style */
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1310
-
-#define SOCKADDR_IN6 sockaddr_in6
-
-#else
-
-/*SO_REUSEPORT is not supported on Windows, define it to 0*/
-#define SO_REUSEPORT 0
-
-/* Retain this code a little longer to support building in
- * old environments.  _MSC_VER is defined as:
- *     1200 for MSVC++ 6.0
- *     1310 for Vc7
- */
-
-#define IPPROTO_IPV6    41
-#define IPV6_MULTICAST_IF 9
-
-struct in6_addr {
-    union {
-        u_char Byte[16];
-        u_short Word[8];
-    } u;
-};
-
-/*
-** Defines to match RFC 2553.
-*/
-#define _S6_un     u
-#define _S6_u8     Byte
-#define s6_addr    _S6_un._S6_u8
-
-/*
-** Defines for our implementation.
-*/
-#define s6_bytes   u.Byte
-#define s6_words   u.Word
-
-/* IPv6 socket address structure, RFC 2553 */
-
-struct SOCKADDR_IN6 {
-        short   sin6_family;    /* AF_INET6 */
-        u_short sin6_port;      /* Transport level port number */
-        u_long  sin6_flowinfo;  /* IPv6 flow information */
-        struct in6_addr sin6_addr; /* IPv6 address */
-        u_long sin6_scope_id;  /* set of interfaces for a scope */
-};
-
-
-/* Error codes from getaddrinfo() */
-
-#define EAI_AGAIN       WSATRY_AGAIN
-#define EAI_BADFLAGS    WSAEINVAL
-#define EAI_FAIL        WSANO_RECOVERY
-#define EAI_FAMILY      WSAEAFNOSUPPORT
-#define EAI_MEMORY      WSA_NOT_ENOUGH_MEMORY
-//#define EAI_NODATA      WSANO_DATA
-#define EAI_NONAME      WSAHOST_NOT_FOUND
-#define EAI_SERVICE     WSATYPE_NOT_FOUND
-#define EAI_SOCKTYPE    WSAESOCKTNOSUPPORT
-
-#define EAI_NODATA      EAI_NONAME
-
-/* Structure used in getaddrinfo() call */
-
-typedef struct addrinfo {
-    int ai_flags;              /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
-    int ai_family;             /* PF_xxx */
-    int ai_socktype;           /* SOCK_xxx */
-    int ai_protocol;           /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-    size_t ai_addrlen;         /* Length of ai_addr */
-    char *ai_canonname;        /* Canonical name for nodename */
-    struct sockaddr *ai_addr;  /* Binary address */
-    struct addrinfo *ai_next;  /* Next structure in linked list */
-} ADDRINFO, FAR * LPADDRINFO;
-
-/* Flags used in "hints" argument to getaddrinfo() */
-
-#define AI_PASSIVE     0x1  /* Socket address will be used in bind() call */
-#define AI_CANONNAME   0x2  /* Return canonical name in first ai_canonname */
-#define AI_NUMERICHOST 0x4  /* Nodename must be a numeric address string */
-
-/* IPv6 Multicasting definitions */
-
-/* Argument structure for IPV6_JOIN_GROUP and IPV6_LEAVE_GROUP */
-
-typedef struct ipv6_mreq {
-    struct in6_addr ipv6mr_multiaddr;  /* IPv6 multicast address */
-    unsigned int    ipv6mr_interface;  /* Interface index */
-} IPV6_MREQ;
-
-#define IPV6_ADD_MEMBERSHIP     12 /* Add an IP group membership */
-#define IPV6_DROP_MEMBERSHIP    13 /* Drop an IP group membership */
-#define IPV6_MULTICAST_LOOP     11 /* Set/get IP multicast loopback */
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_MULTICAST(const struct in6_addr *a)
-{
-    return (a->s6_bytes[0] == 0xff);
-}
-
-WS2TCPIP_INLINE int
-IN6_IS_ADDR_LINKLOCAL(const struct in6_addr *a)
-{
-    return (a->s6_bytes[0] == 0xfe
-            && a->s6_bytes[1] == 0x80);
-}
-
-#define NI_MAXHOST  1025  /* Max size of a fully-qualified domain name */
-#define NI_MAXSERV    32  /* Max size of a service name */
-
-#define INET_ADDRSTRLEN  16 /* Max size of numeric form of IPv4 address */
-#define INET6_ADDRSTRLEN 46 /* Max size of numeric form of IPv6 address */
-
-/* Flags for getnameinfo() */
-
-#define NI_NOFQDN       0x01  /* Only return nodename portion for local hosts */
-#define NI_NUMERICHOST  0x02  /* Return numeric form of the host's address */
-#define NI_NAMEREQD     0x04  /* Error if the host's name not in DNS */
-#define NI_NUMERICSERV  0x08  /* Return numeric form of the service (port #) */
-#define NI_DGRAM        0x10  /* Service is a datagram service */
-
-
-#define IN6_IS_ADDR_V4MAPPED(a) \
-    (((a)->s6_words[0] == 0) && ((a)->s6_words[1] == 0) &&      \
-    ((a)->s6_words[2] == 0) && ((a)->s6_words[3] == 0) &&       \
-    ((a)->s6_words[4] == 0) && ((a)->s6_words[5] == 0xffff))
-
-
-/* --- END --- */
-#endif /* end 'else older build environment' */
-
-#endif
-
-#if !INCL_WINSOCK_API_TYPEDEFS
-
-typedef
-int
-(WSAAPI * LPFN_GETADDRINFO)(
-    IN const char FAR * nodename,
-    IN const char FAR * servname,
-    IN const struct addrinfo FAR * hints,
-    OUT struct addrinfo FAR * FAR * res
-    );
-
-typedef
-void
-(WSAAPI * LPFN_FREEADDRINFO)(
-    IN struct addrinfo FAR * ai
-    );
-
-typedef
-int
-(WSAAPI * LPFN_GETNAMEINFO)(
-    IN  const struct sockaddr FAR * sa,
-    IN  int             salen,
-    OUT char FAR *      host,
-    IN  DWORD           hostlen,
-    OUT char FAR *      serv,
-    IN  DWORD           servlen,
-    IN  int             flags
-    );
-#endif
+#include <iphlpapi.h>
+#include <icmpapi.h>
 
 /* used to disable connection reset messages on Windows XP */
 #ifndef SIO_UDP_CONNRESET
@@ -229,13 +44,9 @@
 #define IPV6_V6ONLY     27 /* Treat wildcard bind as AF_INET6-only. */
 #endif
 
-#include "java_io_FileDescriptor.h"
-#include "java_net_SocketOptions.h"
-
 #define MAX_BUFFER_LEN          2048
 #define MAX_HEAP_BUFFER_LEN     65536
 
-
 /* true if SO_RCVTIMEO is supported by underlying provider */
 extern jboolean isRcvTimeoutSupported;
 
@@ -249,7 +60,7 @@
 typedef union {
     struct sockaddr     sa;
     struct sockaddr_in  sa4;
-    struct SOCKADDR_IN6 sa6;
+    struct sockaddr_in6 sa6;
 } SOCKETADDRESS;
 
 /*
@@ -264,7 +75,7 @@
 
 #define SOCKETADDRESS_COPY(DST,SRC) {                           \
     if ((SRC)->sa_family == AF_INET6) {                         \
-        memcpy ((DST), (SRC), sizeof (struct SOCKADDR_IN6));    \
+        memcpy ((DST), (SRC), sizeof (struct sockaddr_in6));    \
     } else {                                                    \
         memcpy ((DST), (SRC), sizeof (struct sockaddr_in));     \
     }                                                           \
--- a/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/java2d/OSXSurfaceData.java	Fri Nov 11 16:44:36 2016 +0100
@@ -74,8 +74,13 @@
         this.fGraphicsStatesInt = this.fGraphicsStates.asIntBuffer();
         this.fGraphicsStatesFloat = this.fGraphicsStates.asFloatBuffer();
         this.fGraphicsStatesLong = this.fGraphicsStates.asLongBuffer();
-        this.fGraphicsStatesObject = new Object[6]; // clip coordinates + clip types + texture paint image + stroke dash
-                                                    // array + font + font paint
+        this.fGraphicsStatesObject = new Object[8]; // clip coordinates +
+                                                    // clip types +
+                                                    // texture paint image +
+                                                    // stroke dash array +
+                                                    // font + font paint +
+                                                    // linear/radial gradient color +
+                                                    // linear/radial gradient fractions
 
         // NOTE: All access to the DrawingQueue comes through this OSXSurfaceData instance. Therefore
         // every instance method of OSXSurfaceData that accesses the fDrawingQueue is synchronized.
@@ -292,10 +297,10 @@
     @Native static final int kHintsFractionalMetricsIndex = 46;
     @Native static final int kHintsRenderingIndex = 47;
     @Native static final int kHintsInterpolationIndex = 48;
-    // live resizing info
-    @Native static final int kCanDrawDuringLiveResizeIndex = 49;
+    //gradient info
+    @Native static final int kRadiusIndex = 49;
 
-    @Native static final int kSizeOfParameters = kCanDrawDuringLiveResizeIndex + 1;
+    @Native static final int kSizeOfParameters = kRadiusIndex + 1;
 
     // for objectParameters
     @Native static final int kClipCoordinatesIndex = 0;
@@ -304,6 +309,8 @@
     @Native static final int kStrokeDashArrayIndex = 3;
     @Native static final int kFontIndex = 4;
     @Native static final int kFontPaintIndex = 5;
+    @Native static final int kColorArrayIndex = 6;
+    @Native static final int kFractionsArrayIndex = 7;
 
     // possible state changes
     @Native static final int kBoundsChangedBit = 1 << 0;
@@ -329,6 +336,8 @@
     @Native static final int kColorSystem = 1;
     @Native static final int kColorGradient = 2;
     @Native static final int kColorTexture = 3;
+    @Native static final int kColorLinearGradient = 4;
+    @Native static final int kColorRadialGradient = 5;
 
     // possible gradient color states
     @Native static final int kColorNonCyclic = 0;
@@ -522,6 +531,28 @@
     int lastPaintIndex = 0;
     BufferedImage texturePaintImage = null;
 
+    void setGradientViaRasterPath(SunGraphics2D sg2d) {
+        if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
+            PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
+            WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
+            ColorModel cm = context.getColorModel();
+            texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
+
+            this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
+            this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
+            this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
+            this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
+            this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
+            this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
+            this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
+            this.fGraphicsStatesObject[kTextureImageIndex] = OSXOffScreenSurfaceData.createNewSurface(texturePaintImage);
+
+            this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+        } else {
+            this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+        }
+    }
+
     void setupPaint(SunGraphics2D sg2d, int x, int y, int w, int h) {
         if (sg2d.paint instanceof SystemColor) {
             SystemColor color = (SystemColor) sg2d.paint;
@@ -567,6 +598,75 @@
             } else {
                 this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
             }
+        } else if (sg2d.paint instanceof LinearGradientPaint) {
+            LinearGradientPaint color = (LinearGradientPaint) sg2d.paint;
+            if (color.getCycleMethod() == LinearGradientPaint.CycleMethod.NO_CYCLE) {
+                if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorLinearGradient) || (lastPaint != sg2d.paint)) {
+
+                    this.fGraphicsStatesInt.put(kColorStateIndex, kColorLinearGradient);
+                    int numColor = color.getColors().length;
+                    int colorArray[] = new int[numColor];
+                    for (int i = 0; i < numColor; i++) {
+                        colorArray[i] = color.getColors()[i].getRGB();
+                    }
+                    this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
+
+                    int numFractions = color.getFractions().length;
+                    float fractionArray[] = new float[numFractions];
+                    for (int i = 0; i < numFractions; i++) {
+                        fractionArray[i] = color.getFractions()[i];
+                    }
+                    this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
+
+                    Point2D p = color.getStartPoint();
+                    this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
+                    p = color.getEndPoint();
+                    this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
+
+                    this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+                } else {
+                    this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+                }
+            } else {
+                setGradientViaRasterPath(sg2d);
+            }
+        } else if (sg2d.paint instanceof RadialGradientPaint) {
+            RadialGradientPaint color = (RadialGradientPaint) sg2d.paint;
+            if (color.getCycleMethod() == RadialGradientPaint.CycleMethod.NO_CYCLE) {
+                if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorRadialGradient) || (lastPaint != sg2d.paint)) {
+
+                    this.fGraphicsStatesInt.put(kColorStateIndex, kColorRadialGradient);
+                    int numColor = color.getColors().length;
+                    int colorArray[] = new int[numColor];
+                    for (int i = 0; i < numColor; i++) {
+                        colorArray[i] = color.getColors()[i].getRGB();
+                    }
+                    this.fGraphicsStatesObject[kColorArrayIndex] = colorArray;
+
+                    int numStops = color.getFractions().length;
+                    float stopsArray[] = new float[numStops];
+                    for (int i = 0; i < numStops; i++) {
+                        stopsArray[i] = color.getFractions()[i];
+                    }
+                    this.fGraphicsStatesObject[kFractionsArrayIndex] = color.getFractions();
+
+                    Point2D p = color.getFocusPoint();
+                    this.fGraphicsStatesFloat.put(kColorx1Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory1Index, (float) p.getY());
+                    p = color.getCenterPoint();
+                    this.fGraphicsStatesFloat.put(kColorx2Index, (float) p.getX());
+                    this.fGraphicsStatesFloat.put(kColory2Index, (float) p.getY());
+                    this.fGraphicsStatesFloat.put(kRadiusIndex,     color.getRadius());
+
+                    this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
+                } else {
+                    this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
+                }
+            } else {
+                setGradientViaRasterPath(sg2d);
+            }
         } else if (sg2d.paint instanceof TexturePaint) {
             if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint)) {
                 TexturePaint color = (TexturePaint) sg2d.paint;
@@ -587,27 +687,7 @@
                 this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
             }
         } else {
-            if ((this.fGraphicsStatesInt.get(kColorStateIndex) != kColorTexture) || (lastPaint != sg2d.paint) || ((this.fChangeFlag & kBoundsChangedBit) != 0)) {
-                PaintContext context = sg2d.paint.createContext(sg2d.getDeviceColorModel(), userBounds, userBounds, sIdentityMatrix, sg2d.getRenderingHints());
-                WritableRaster raster = (WritableRaster) (context.getRaster(userBounds.x, userBounds.y, userBounds.width, userBounds.height));
-                ColorModel cm = context.getColorModel();
-                texturePaintImage = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
-
-                this.fGraphicsStatesInt.put(kColorStateIndex, kColorTexture);
-                this.fGraphicsStatesInt.put(kColorWidthIndex, texturePaintImage.getWidth());
-                this.fGraphicsStatesInt.put(kColorHeightIndex, texturePaintImage.getHeight());
-                this.fGraphicsStatesFloat.put(kColortxIndex, (float) userBounds.getX());
-                this.fGraphicsStatesFloat.put(kColortyIndex, (float) userBounds.getY());
-                this.fGraphicsStatesFloat.put(kColorsxIndex, 1.0f);
-                this.fGraphicsStatesFloat.put(kColorsyIndex, 1.0f);
-                this.fGraphicsStatesObject[kTextureImageIndex] = sun.awt.image.BufImgSurfaceData.createData(texturePaintImage);
-
-                context.dispose();
-
-                this.fChangeFlag = (this.fChangeFlag | kColorChangedBit);
-            } else {
-                this.fChangeFlag = (this.fChangeFlag & kColorNotChangedBit);
-            }
+            setGradientViaRasterPath(sg2d);
         }
         lastPaint = sg2d.paint;
     }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessibility.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,11 +29,9 @@
 
 import java.awt.*;
 import java.beans.*;
-import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 import java.util.concurrent.Callable;
-import sun.awt.AWTAccessor;
 
 import javax.accessibility.*;
 import javax.swing.*;
@@ -73,8 +71,20 @@
     }
 
     public void propertyChange(final PropertyChangeEvent evt) {
-        if (evt.getNewValue() == null) return;
-        focusChanged();
+        Object newValue = evt.getNewValue();
+        if (newValue == null) return;
+        // Don't post focus on things that don't matter, i.e. alert, colorchooser,
+        // desktoppane, dialog, directorypane, filechooser, filler, fontchoose,
+        // frame, glasspane, layeredpane, optionpane, panel, rootpane, separator,
+        // tooltip, viewport, window.
+        // List taken from initializeRoles() in JavaComponentUtilities.m.
+        if (newValue instanceof Accessible) {
+            AccessibleContext nvAC = ((Accessible) newValue).getAccessibleContext();
+            AccessibleRole nvRole = nvAC.getAccessibleRole();
+            if (!ignoredRoles.contains(roleKey(nvRole))) {
+                focusChanged();
+            }
+        }
     }
 
     private native void focusChanged();
@@ -683,9 +693,15 @@
             if (context == null) continue;
 
             if (whichChildren == JAVA_AX_VISIBLE_CHILDREN) {
-                if (!context.getAccessibleComponent().isVisible()) continue;
+                AccessibleComponent acomp = context.getAccessibleComponent();
+                if (acomp == null || !acomp.isVisible()) {
+                    continue;
+                }
             } else if (whichChildren == JAVA_AX_SELECTED_CHILDREN) {
-                if (!ac.getAccessibleSelection().isAccessibleChildSelected(i)) continue;
+                AccessibleSelection sel = ac.getAccessibleSelection();
+                if (sel == null || !sel.isAccessibleChildSelected(i)) {
+                    continue;
+                }
             }
 
             if (!allowIgnored) {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Fri Nov 11 16:44:36 2016 +0100
@@ -39,7 +39,10 @@
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_CARET_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_SELECTION_PROPERTY;
+import static javax.accessibility.AccessibleContext.ACCESSIBLE_STATE_PROPERTY;
 import static javax.accessibility.AccessibleContext.ACCESSIBLE_TEXT_PROPERTY;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
 import sun.awt.AWTAccessor;
 
 
@@ -63,6 +66,9 @@
     private static native void valueChanged(long ptr);
     private static native void selectedTextChanged(long ptr);
     private static native void selectionChanged(long ptr);
+    private static native void menuOpened(long ptr);
+    private static native void menuClosed(long ptr);
+    private static native void menuItemSelected(long ptr);
 
     private Accessible accessible;
 
@@ -111,16 +117,45 @@
         public void propertyChange(PropertyChangeEvent e) {
             String name = e.getPropertyName();
             if ( ptr != 0 ) {
+                Object newValue = e.getNewValue();
+                Object oldValue = e.getOldValue();
                 if (name.compareTo(ACCESSIBLE_CARET_PROPERTY) == 0) {
                     selectedTextChanged(ptr);
                 } else if (name.compareTo(ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
                     valueChanged(ptr);
                 } else if (name.compareTo(ACCESSIBLE_SELECTION_PROPERTY) == 0 ) {
                     selectionChanged(ptr);
-                }  else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
-                    Object nv = e.getNewValue();
-                    if (nv instanceof AccessibleContext) {
-                        activeDescendant = (AccessibleContext)nv;
+                } else if (name.compareTo(ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY) == 0 ) {
+                    if (newValue instanceof AccessibleContext) {
+                        activeDescendant = (AccessibleContext)newValue;
+                    }
+                } else if (name.compareTo(ACCESSIBLE_STATE_PROPERTY) == 0) {
+                    AccessibleContext thisAC = accessible.getAccessibleContext();
+                    AccessibleRole thisRole = thisAC.getAccessibleRole();
+                    Accessible parentAccessible = thisAC.getAccessibleParent();
+                    AccessibleRole parentRole = null;
+                    if (parentAccessible != null) {
+                        parentRole = parentAccessible.getAccessibleContext().getAccessibleRole();
+                    }
+                    // At least for now don't handle combo box menu state changes.
+                    // This may change when later fixing issues which currently
+                    // exist for combo boxes, but for now the following is only
+                    // for JPopupMenus, not for combobox menus.
+                    if (parentRole != AccessibleRole.COMBO_BOX) {
+                        if (thisRole == AccessibleRole.POPUP_MENU) {
+                            if ( newValue != null &&
+                                 ((AccessibleState)newValue) == AccessibleState.VISIBLE ) {
+                                    menuOpened(ptr);
+                            } else if ( oldValue != null &&
+                                        ((AccessibleState)oldValue) == AccessibleState.VISIBLE ) {
+                                menuClosed(ptr);
+                            }
+                        } else if (thisRole == AccessibleRole.MENU_ITEM) {
+                            if ( newValue != null &&
+                                 ((AccessibleState)newValue) == AccessibleState.FOCUSED ) {
+                                menuItemSelected(ptr);
+                            }
+                        }
                     }
                 }
             }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java	Fri Nov 11 16:44:36 2016 +0100
@@ -97,7 +97,7 @@
         int absY = locationOnScreen.y + y;
 
         responder.handleScrollEvent(x, y, absX, absY, modifierFlags, deltaX,
-                                    deltaY);
+                                    deltaY, NSEvent.SCROLL_PHASE_UNSUPPORTED);
     }
 
     public void handleKeyEvent(int eventType, int modifierFlags, String characters,
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformResponder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -44,6 +44,8 @@
     private final PlatformEventNotifier eventNotifier;
     private final boolean isNpapiCallback;
     private int lastKeyPressCode = KeyEvent.VK_UNDEFINED;
+    private final DeltaAccumulator deltaAccumulatorX = new DeltaAccumulator();
+    private final DeltaAccumulator deltaAccumulatorY = new DeltaAccumulator();
 
     CPlatformResponder(final PlatformEventNotifier eventNotifier,
                        final boolean isNpapiCallback) {
@@ -89,37 +91,37 @@
      */
     void handleScrollEvent(final int x, final int y, final int absX,
                            final int absY, final int modifierFlags,
-                           final double deltaX, final double deltaY) {
+                           final double deltaX, final double deltaY,
+                           final int scrollPhase) {
         int jmodifiers = NSEvent.nsToJavaModifiers(modifierFlags);
         final boolean isShift = (jmodifiers & InputEvent.SHIFT_DOWN_MASK) != 0;
 
+        int roundDeltaX = deltaAccumulatorX.getRoundedDelta(deltaX, scrollPhase);
+        int roundDeltaY = deltaAccumulatorY.getRoundedDelta(deltaY, scrollPhase);
+
         // Vertical scroll.
-        if (!isShift && deltaY != 0.0) {
-            dispatchScrollEvent(x, y, absX, absY, jmodifiers, deltaY);
+        if (!isShift && (deltaY != 0.0 || roundDeltaY != 0)) {
+            dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDeltaY, deltaY);
         }
         // Horizontal scroll or shirt+vertical scroll.
         final double delta = isShift && deltaY != 0.0 ? deltaY : deltaX;
-        if (delta != 0.0) {
+        final int roundDelta = isShift && roundDeltaY != 0 ? roundDeltaY : roundDeltaX;
+        if (delta != 0.0 || roundDelta != 0) {
             jmodifiers |= InputEvent.SHIFT_DOWN_MASK;
-            dispatchScrollEvent(x, y, absX, absY, jmodifiers, delta);
+            dispatchScrollEvent(x, y, absX, absY, jmodifiers, roundDelta, delta);
         }
     }
 
     private void dispatchScrollEvent(final int x, final int y, final int absX,
                                      final int absY, final int modifiers,
-                                     final double delta) {
+                                     final int roundDelta, final double delta) {
         final long when = System.currentTimeMillis();
         final int scrollType = MouseWheelEvent.WHEEL_UNIT_SCROLL;
         final int scrollAmount = 1;
-        int wheelRotation = (int) delta;
-        int signum = (int) Math.signum(delta);
-        if (signum * delta < 1) {
-            wheelRotation = signum;
-        }
         // invert the wheelRotation for the peer
         eventNotifier.notifyMouseWheelEvent(when, x, y, absX, absY, modifiers,
                                             scrollType, scrollAmount,
-                                            -wheelRotation, -delta, null);
+                                            -roundDelta, -delta, null);
     }
 
     /**
@@ -260,4 +262,46 @@
     void handleWindowFocusEvent(boolean gained, LWWindowPeer opposite) {
         eventNotifier.notifyActivation(gained, opposite);
     }
+
+    static class DeltaAccumulator {
+
+        static final double MIN_THRESHOLD = 0.1;
+        static final double MAX_THRESHOLD = 0.5;
+        double accumulatedDelta;
+
+        int getRoundedDelta(double delta, int scrollPhase) {
+
+            int roundDelta = (int) Math.round(delta);
+
+            if (scrollPhase == NSEvent.SCROLL_PHASE_UNSUPPORTED) { // mouse wheel
+                if (roundDelta == 0 && delta != 0) {
+                    roundDelta = delta > 0 ? 1 : -1;
+                }
+            } else { // trackpad
+                boolean begin = scrollPhase == NSEvent.SCROLL_PHASE_BEGAN;
+                boolean end = scrollPhase == NSEvent.SCROLL_MASK_PHASE_ENDED
+                        || scrollPhase == NSEvent.SCROLL_MASK_PHASE_CANCELLED;
+
+                if (begin) {
+                    accumulatedDelta = 0;
+                }
+
+                accumulatedDelta += delta;
+
+                double absAccumulatedDelta = Math.abs(accumulatedDelta);
+                if (absAccumulatedDelta > MAX_THRESHOLD) {
+                    roundDelta = (int) Math.round(accumulatedDelta);
+                    accumulatedDelta -= roundDelta;
+                }
+
+                if (end) {
+                    if (roundDelta == 0 && absAccumulatedDelta > MIN_THRESHOLD) {
+                        roundDelta = accumulatedDelta > 0 ? 1 : -1;
+                    }
+                }
+            }
+
+            return roundDelta;
+        }
+    }
 }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformView.java	Fri Nov 11 16:44:36 2016 +0100
@@ -194,7 +194,8 @@
 
         if (event.getType() == CocoaConstants.NSScrollWheel) {
             responder.handleScrollEvent(x, y, absX, absY, event.getModifierFlags(),
-                                        event.getScrollDeltaX(), event.getScrollDeltaY());
+                                        event.getScrollDeltaX(), event.getScrollDeltaY(),
+                                        event.getScrollPhase());
         } else {
             responder.handleMouseEvent(event.getType(), event.getModifierFlags(), event.getButtonNumber(),
                                        event.getClickCount(), x, y,
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java	Fri Nov 11 16:44:36 2016 +0100
@@ -178,12 +178,6 @@
             return;
         }
 
-        // See if this has an NSPrintInfo in it.
-        NSPrintInfo nsPrintInfo = (NSPrintInfo)attributes.get(NSPrintInfo.class);
-        if (nsPrintInfo != null) {
-            fNSPrintInfo = nsPrintInfo.getValue();
-        }
-
         PageRanges pageRangesAttr =  (PageRanges)attributes.get(PageRanges.class);
         if (isSupportedValue(pageRangesAttr, attributes)) {
             SunPageSelection rangeSelect = (SunPageSelection)attributes.get(SunPageSelection.class);
@@ -563,8 +557,11 @@
 
     @Override
     protected void finalize() {
-        if (fNSPrintInfo != -1) {
-            dispose(fNSPrintInfo);
+        synchronized (fNSPrintInfoLock) {
+            if (fNSPrintInfo != -1) {
+                dispose(fNSPrintInfo);
+            }
+            fNSPrintInfo = -1;
         }
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSEvent.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,6 +32,13 @@
  * JDK functionality.
  */
 final class NSEvent {
+
+    static final int SCROLL_PHASE_UNSUPPORTED = 1;
+    static final int SCROLL_PHASE_BEGAN = 2;
+    static final int SCROLL_PHASE_CONTINUED = 3;
+    static final int SCROLL_MASK_PHASE_CANCELLED = 4;
+    static final int SCROLL_MASK_PHASE_ENDED = 5;
+
     private int type;
     private int modifierFlags;
 
@@ -42,6 +49,7 @@
     private int y;
     private double scrollDeltaY;
     private double scrollDeltaX;
+    private int scrollPhase;
     private int absX;
     private int absY;
 
@@ -62,7 +70,7 @@
     // Called from native
     NSEvent(int type, int modifierFlags, int clickCount, int buttonNumber,
                    int x, int y, int absX, int absY,
-                   double scrollDeltaY, double scrollDeltaX) {
+                   double scrollDeltaY, double scrollDeltaX, int scrollPhase) {
         this.type = type;
         this.modifierFlags = modifierFlags;
         this.clickCount = clickCount;
@@ -73,6 +81,7 @@
         this.absY = absY;
         this.scrollDeltaY = scrollDeltaY;
         this.scrollDeltaX = scrollDeltaX;
+        this.scrollPhase = scrollPhase;
     }
 
     int getType() {
@@ -107,6 +116,10 @@
         return scrollDeltaX;
     }
 
+    int getScrollPhase() {
+        return scrollPhase;
+    }
+
     int getAbsX() {
         return absX;
     }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * 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 sun.lwawt.macosx;
-
-
-import java.io.*;
-import javax.print.attribute.*;
-
-@SuppressWarnings("serial") // JDK implementation class
-public final class NSPrintInfo implements PrintJobAttribute, PrintRequestAttribute, Serializable, Cloneable {
-
-    private long fNSPrintInfo;
-
-    public NSPrintInfo(long nsPrintInfo) {
-        fNSPrintInfo = nsPrintInfo;
-    }
-
-    public long getValue() {
-        return fNSPrintInfo;
-    }
-
-    public boolean equals(Object object) {
-        return (object != null && object instanceof NSPrintInfo && fNSPrintInfo == ((NSPrintInfo)object).fNSPrintInfo);
-    }
-
-    public int hashCode() {
-        return (int)fNSPrintInfo;
-    }
-
-    public String toString() {
-        return "" + fNSPrintInfo;
-    }
-
-    public Class<? extends Attribute> getCategory() {
-        return NSPrintInfo.class;
-    }
-
-    public String getName() {
-        return "nsPrintInfo";
-    }
-}
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m	Fri Nov 11 16:44:36 2016 +0100
@@ -383,7 +383,7 @@
     }
     
     static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
-    static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+    static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
     jobject jEvent = JNFNewObject(env, jctor_NSEvent,
                                   [event type],
                                   [event modifierFlags],
@@ -392,7 +392,8 @@
                                   (jint)localPoint.x, (jint)localPoint.y,
                                   (jint)absP.x, (jint)absP.y,
                                   [event deltaY],
-                                  [event deltaX]);
+                                  [event deltaX],
+                                  [AWTToolkit scrollStateWithEvent: event]);
     CHECK_NULL(jEvent);
     
     static JNF_CLASS_CACHE(jc_PlatformView, "sun/lwawt/macosx/CPlatformView");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m	Fri Nov 11 16:44:36 2016 +0100
@@ -317,7 +317,7 @@
     [self setPropertiesForStyleBits:styleBits mask:MASK(_METHOD_PROP_BITMASK)];
 
     if (IS(self.styleBits, IS_POPUP)) {
-        [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/]; 
+        [self.nsWindow setCollectionBehavior:(1 << 8) /*NSWindowCollectionBehaviorFullScreenAuxiliary*/];
     }
 
     return self;
@@ -330,7 +330,7 @@
 // returns id for the topmost window under mouse
 + (NSInteger) getTopmostWindowUnderMouseID {
     NSInteger result = -1;
-    
+
     NSRect screenRect = [[NSScreen mainScreen] frame];
     NSPoint nsMouseLocation = [NSEvent mouseLocation];
     CGPoint cgMouseLocation = CGPointMake(nsMouseLocation.x, screenRect.size.height - nsMouseLocation.y);
@@ -433,18 +433,18 @@
 // Tests wheather the corresponding Java paltform window is visible or not
 + (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window {
     BOOL isVisible = NO;
-    
+
     if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) {
         AWTWindow *awtWindow = (AWTWindow *)[window delegate];
         [AWTToolkit eventCountPlusPlus];
-        
+
         JNIEnv *env = [ThreadUtilities getJNIEnv];
         jobject platformWindow = [awtWindow.javaPlatformWindow jObjectWithEnv:env];
         if (platformWindow != NULL) {
             static JNF_MEMBER_CACHE(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z");
             isVisible = JNFCallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO;
             (*env)->DeleteLocalRef(env, platformWindow);
-            
+
         }
     }
     return isVisible;
@@ -577,7 +577,9 @@
 - (NSRect)windowWillUseStandardFrame:(NSWindow *)window
                         defaultFrame:(NSRect)newFrame {
 
-    return [self standardFrame];
+    return NSEqualSizes(NSZeroSize, [self standardFrame].size)
+                ? newFrame
+                : [self standardFrame];
 }
 
 // Hides/shows window's childs during iconify/de-iconify operation
@@ -1085,17 +1087,17 @@
      jdouble width, jdouble height)
 {
     JNF_COCOA_ENTER(env);
-    
+
     NSRect jrect = NSMakeRect(originX, originY, width, height);
-    
+
     NSWindow *nsWindow = OBJC(windowPtr);
     [ThreadUtilities performOnMainThreadWaiting:NO block:^(){
-        
+
         NSRect rect = ConvertNSScreenRect(NULL, jrect);
         AWTWindow *window = (AWTWindow*)[nsWindow delegate];
         window.standardFrame = rect;
     }];
-    
+
     JNF_COCOA_EXIT(env);
 }
 
@@ -1366,7 +1368,7 @@
     } else {
         [JNFException raise:env as:kIllegalArgumentException reason:"unknown event type"];
     }
-    
+
 JNF_COCOA_EXIT(env);
 }
 
@@ -1476,7 +1478,7 @@
 
         if (CGDisplayRelease(aID) == kCGErrorSuccess) {
             NSUInteger styleMask = [AWTWindow styleMaskForStyleBits:window.styleBits];
-            [nsWindow setStyleMask:styleMask]; 
+            [nsWindow setStyleMask:styleMask];
             [nsWindow setLevel: window.preFullScreenLevel];
 
             // GraphicsDevice takes care of restoring pre full screen bounds
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobotKeyCode.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CRobotKeyCode.m	Fri Nov 11 16:44:36 2016 +0100
@@ -45,7 +45,7 @@
     self = [super init];
 
     if (nil != self) {
-        javaToMacKeyMap = [NSDictionary dictionaryWithObjectsAndKeys :
+        self.javaToMacKeyMap = [NSDictionary dictionaryWithObjectsAndKeys :
             [NSNumber numberWithInt : OSX_Delete], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_BACK_SPACE],
             [NSNumber numberWithInt : OSX_kVK_Tab], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_TAB],
             [NSNumber numberWithInt : OSX_kVK_Return], [NSNumber numberWithInt : java_awt_event_KeyEvent_VK_ENTER],
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CTrayIcon.m	Fri Nov 11 16:44:36 2016 +0100
@@ -139,9 +139,9 @@
     jint clickCount;
 
     clickCount = [event clickCount];
-
+        
     static JNF_CLASS_CACHE(jc_NSEvent, "sun/lwawt/macosx/NSEvent");
-    static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDD)V");
+    static JNF_CTOR_CACHE(jctor_NSEvent, jc_NSEvent, "(IIIIIIIIDDI)V");
     jobject jEvent = JNFNewObject(env, jctor_NSEvent,
                                   [event type],
                                   [event modifierFlags],
@@ -150,7 +150,8 @@
                                   (jint)localPoint.x, (jint)localPoint.y,
                                   (jint)absP.x, (jint)absP.y,
                                   [event deltaY],
-                                  [event deltaX]);
+                                  [event deltaX],
+                                  [AWTToolkit scrollStateWithEvent: event]);
     CHECK_NULL(jEvent);
 
     static JNF_CLASS_CACHE(jc_TrayIcon, "sun/lwawt/macosx/CTrayIcon");
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/JavaComponentAccessibility.m	Fri Nov 11 16:44:36 2016 +0100
@@ -66,7 +66,6 @@
 static JNF_MEMBER_CACHE(jf_ptr, sjc_CAccessible, "ptr", "J");
 static JNF_STATIC_MEMBER_CACHE(sjm_getCAccessible, sjc_CAccessible, "getCAccessible", "(Ljavax/accessibility/Accessible;)Lsun/lwawt/macosx/CAccessible;");
 
-
 static jobject sAccessibilityClass = NULL;
 
 // sAttributeNamesForRoleCache holds the names of the attributes to which each java
@@ -213,6 +212,24 @@
     NSAccessibilityPostNotification(self, NSAccessibilitySelectedChildrenChangedNotification);
 }
 
+- (void)postMenuOpened
+{
+    AWT_ASSERT_APPKIT_THREAD;
+    NSAccessibilityPostNotification(self, (NSString *)kAXMenuOpenedNotification);
+}
+
+- (void)postMenuClosed
+{
+    AWT_ASSERT_APPKIT_THREAD;
+    NSAccessibilityPostNotification(self, (NSString *)kAXMenuClosedNotification);
+}
+
+- (void)postMenuItemSelected
+{
+    AWT_ASSERT_APPKIT_THREAD;
+    NSAccessibilityPostNotification(self, (NSString *)kAXMenuItemSelectedNotification);
+}
+
 - (BOOL)isEqual:(id)anObject
 {
     if (![anObject isKindOfClass:[self class]]) return NO;
@@ -278,8 +295,7 @@
 + (jobject) getCAccessible:(jobject)jaccessible withEnv:(JNIEnv *)env {
     if (JNFIsInstanceOf(env, jaccessible, &sjc_CAccessible)) {
         return jaccessible;
-    }
-    else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {
+    } else if (JNFIsInstanceOf(env, jaccessible, &sjc_Accessible)) {
         return JNFCallStaticObjectMethod(env, sjm_getCAccessible, jaccessible);
     }
     return NULL;
@@ -368,6 +384,14 @@
     // must init freshly -alloc'd object
     [newChild initWithParent:parent withEnv:env withAccessible:jCAX withIndex:index withView:view withJavaRole:javaRole]; // must init new instance
 
+    // If creating a JPopupMenu (not a combobox popup list) need to fire menuOpened.
+    // This is the only way to know if the menu is opening; visible state change
+    // can't be caught because the listeners are not set up in time.
+    if ( [javaRole isEqualToString:@"popupmenu"] &&
+         ![[parent javaRole] isEqualToString:@"combobox"] ) {
+        [newChild postMenuOpened];
+    }
+
     // must hard retain pointer poked into Java object
     [newChild retain];
     JNFSetLongField(env, jCAX, jf_ptr, ptr_to_jlong(newChild));
@@ -634,6 +658,15 @@
                 return moreNames;
             }
         }
+        // popupmenu's return values not selected children
+        if ( [javaRole isEqualToString:@"popupmenu"] &&
+             ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
+            NSMutableArray *moreNames =
+                [[NSMutableArray alloc] initWithCapacity: [names count] + 1];
+            [moreNames addObjectsFromArray: names];
+            [moreNames addObject:NSAccessibilityValueAttribute];
+            return moreNames;
+        }
         return names;
 
     }  // end @synchronized
@@ -707,6 +740,7 @@
 
     return value;
 }
+
 - (BOOL)accessibilityIsChildrenAttributeSettable
 {
     return NO;
@@ -939,6 +973,13 @@
     if (fNSRole == nil) {
         NSString *javaRole = [self javaRole];
         fNSRole = [sRoles objectForKey:javaRole];
+        // The sRoles NSMutableDictionary maps popupmenu to Mac's popup button.
+        // JComboBox behavior currently relies on this.  However this is not the
+        // proper mapping for a JPopupMenu so fix that.
+        if ( [javaRole isEqualToString:@"popupmenu"] &&
+             ![[[self parent] javaRole] isEqualToString:@"combobox"] ) {
+             fNSRole = NSAccessibilityMenuRole;
+        }
         if (fNSRole == nil) {
             // this component has assigned itself a custom AccessibleRole not in the sRoles array
             fNSRole = javaRole;
@@ -947,6 +988,7 @@
     }
     return fNSRole;
 }
+
 - (BOOL)accessibilityIsRoleAttributeSettable
 {
     return NO;
@@ -1046,8 +1088,7 @@
 - (NSString *)accessibilitySubroleAttribute
 {
     NSString *value = nil;
-    if ([[self javaRole] isEqualToString:@"passwordtext"])
-    {
+    if ([[self javaRole] isEqualToString:@"passwordtext"]) {
         value = NSAccessibilitySecureTextFieldSubrole;
     }
     /*
@@ -1123,6 +1164,45 @@
 
     JNIEnv* env = [ThreadUtilities getJNIEnv];
 
+    // Need to handle popupmenus differently.
+    //
+    // At least for now don't handle combo box menus.
+    // This may change when later fixing issues which currently 
+    // exist for combo boxes, but for now the following is only
+    // for JPopupMenus, not for combobox menus.
+    id parent = [self parent];
+    if ( [[self javaRole] isEqualToString:@"popupmenu"] &&
+         ![[parent javaRole] isEqualToString:@"combobox"] ) {
+        NSArray *children =
+            [JavaComponentAccessibility childrenOfParent:self
+                                        withEnv:env
+                                        withChildrenCode:JAVA_AX_ALL_CHILDREN
+                                        allowIgnored:YES];
+        if ([children count] > 0) {
+            // handle case of AXMenuItem
+            // need to ask menu what is selected
+            NSArray *selectedChildrenOfMenu =
+            	[self accessibilitySelectedChildrenAttribute];
+            JavaComponentAccessibility *selectedMenuItem =
+            	[selectedChildrenOfMenu objectAtIndex:0];
+            if (selectedMenuItem != nil) {
+                jobject itemValue =
+                	JNFCallStaticObjectMethod( env,
+                                                   sjm_getAccessibleName,
+                                                   selectedMenuItem->fAccessible,
+                                                   selectedMenuItem->fComponent ); // AWT_THREADING Safe (AWTRunLoop)
+                if (itemValue == NULL) {
+                    return nil;
+                }
+                NSString* itemString = JNFJavaToNSString(env, itemValue);
+                (*env)->DeleteLocalRef(env, itemValue);
+                return itemString;
+            } else {
+            	return nil;
+            }
+        }
+    }
+
     // ask Java for the component's accessibleValue. In java, the "accessibleValue" just means a numerical value
     // a text value is taken care of in JavaTextAccessibility
 
@@ -1345,6 +1425,54 @@
 
 /*
  * Class:     sun_lwawt_macosx_CAccessible
+ * Method:    menuOpened
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuOpened
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+    [ThreadUtilities performOnMainThread:@selector(postMenuOpened)
+                     on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+                     withObject:nil
+                     waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CAccessible
+ * Method:    menuClosed
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuClosed
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+    [ThreadUtilities performOnMainThread:@selector(postMenuClosed)
+                     on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+                     withObject:nil
+                     waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CAccessible
+ * Method:    menuItemSelected
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CAccessible_menuItemSelected
+(JNIEnv *env, jclass jklass, jlong element)
+{
+JNF_COCOA_ENTER(env);
+    [ThreadUtilities performOnMainThread:@selector(postMenuItemSelected)
+                     on:(JavaComponentAccessibility *)jlong_to_ptr(element)
+                     withObject:nil
+                     waitUntilDone:NO];
+JNF_COCOA_EXIT(env);
+}
+
+/*
+ * Class:     sun_lwawt_macosx_CAccessible
  * Method:    unregisterFromCocoaAXSystem
  * Signature: (I)V
  */
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.h	Fri Nov 11 16:44:36 2016 +0100
@@ -41,6 +41,7 @@
 @interface AWTToolkit : NSObject { }
 + (long) getEventCount;
 + (void) eventCountPlusPlus;
++ (jint) scrollStateWithEvent: (NSEvent*) event;
 @end
 
 /*
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m	Fri Nov 11 16:44:36 2016 +0100
@@ -43,6 +43,13 @@
 
 #import <JavaRuntimeSupport/JavaRuntimeSupport.h>
 
+// SCROLL PHASE STATE
+#define SCROLL_PHASE_UNSUPPORTED 1
+#define SCROLL_PHASE_BEGAN 2
+#define SCROLL_PHASE_CONTINUED 3
+#define SCROLL_PHASE_CANCELLED 4
+#define SCROLL_PHASE_ENDED 5
+
 int gNumberOfButtons;
 jint* gButtonDownMasks;
 
@@ -72,6 +79,23 @@
     eventCount++;
 }
 
++ (jint) scrollStateWithEvent: (NSEvent*) event {
+
+    if ([event type] != NSScrollWheel) {
+        return 0;
+    }
+    
+    NSEventPhase phase = [event phase];
+    NSEventPhase momentumPhase = [event momentumPhase];
+    
+    if (!phase && !momentumPhase) return SCROLL_PHASE_UNSUPPORTED;
+    switch (phase) {
+        case NSEventPhaseBegan: return SCROLL_PHASE_BEGAN;
+        case NSEventPhaseCancelled: return SCROLL_PHASE_CANCELLED;
+        case NSEventPhaseEnded: return SCROLL_PHASE_ENDED;
+        default: return SCROLL_PHASE_CONTINUED;
+    }
+}
 @end
 
 
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.h	Fri Nov 11 16:44:36 2016 +0100
@@ -44,6 +44,8 @@
     SD_Fill,
     SD_EOFill,
     SD_Shade,
+    SD_LinearGradient,
+    SD_RadialGradient,
     SD_Pattern,
     SD_Image,
     SD_Text,
@@ -65,6 +67,17 @@
 };
 typedef struct _stateShadingInfo StateShadingInfo;
 
+struct _stateGradientInfo
+{
+    CGPoint    start;
+    CGPoint    end;
+    CGFloat  radius;
+    CGFloat* colordata;
+    CGFloat* fractionsdata;
+    jint     fractionsLength;
+};
+typedef struct _stateGradientInfo StateGradientInfo;
+
 struct _statePatternInfo
 {
     CGFloat    tx;
@@ -122,6 +135,7 @@
                                                 // its callees.
 
     StateShadingInfo*        shadingInfo;        // tracks shading and its parameters
+    StateGradientInfo*       gradientInfo;       // tracks gradient and its parameters
     StatePatternInfo*        patternInfo;        // tracks pattern and its parameters
     StateGraphicsInfo        graphicsStateInfo;    // tracks other graphics state
 
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/QuartzSurfaceData.m	Fri Nov 11 16:44:36 2016 +0100
@@ -268,9 +268,105 @@
     free(info);
 }
 
+static inline void contextQuartzLinearGradientPath(QuartzSDOps* qsdo)
+{
+
+PRINT("    contextQuartzLinearGradientPath");
+
+    CGContextRef cgRef = qsdo->cgRef;
+    StateGradientInfo *gradientInfo = qsdo->gradientInfo;
+   
+    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    size_t num_locations = gradientInfo->fractionsLength;
+    CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations);
+    int i = 0;
+    size_t component_size = num_locations * 4;
+    CGFloat components[component_size];
+    CGGradientRef gradient = NULL;
+
+    for (int i = 0; i < num_locations; i++) {
+        locations[i] = gradientInfo->fractionsdata[i];
+//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
+    }
+    for (i = 0; i < component_size; i++) {
+        components[i] = gradientInfo->colordata[i];
+//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
+//                  i, components[i], i, gradientInfo->colordata[i]);
+    } 
+    CGContextSaveGState(cgRef);
+    gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
+//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", 
+//                 gradientInfo->start.x, gradientInfo->start.y);
+//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", 
+//                 gradientInfo->end.x, gradientInfo->end.y);
+    if (qsdo->isEvenOddFill) {
+        CGContextEOClip(cgRef);
+    } else {
+        CGContextClip(cgRef);
+    }
+    CGContextDrawLinearGradient(cgRef, gradient, gradientInfo->start, gradientInfo->end, kCGGradientDrawsAfterEndLocation);    
+    
+    CGContextRestoreGState(cgRef);
+    CGColorSpaceRelease(colorspace);
+    CGGradientRelease(gradient);
+    free(locations);
+    free(gradientInfo->colordata);
+    free(gradientInfo->fractionsdata);
+}
+
+static inline void contextQuartzRadialGradientPath(QuartzSDOps* qsdo)
+{
+
+PRINT("    contextQuartzRadialGradientPath");
+
+    CGContextRef cgRef = qsdo->cgRef;
+    StateGradientInfo *gradientInfo = qsdo->gradientInfo;
+   
+    CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+    size_t num_locations = gradientInfo->fractionsLength;
+    CGFloat *locations = (CGFloat *) malloc(sizeof(CGFloat) * num_locations);
+    int i = 0;
+    size_t component_size = num_locations * 4;
+    CGFloat components[component_size];
+    CGGradientRef gradient = NULL;
+    CGFloat startRadius = gradientInfo->radius;
+    CGFloat endRadius = gradientInfo->radius;
+
+    for (int i = 0; i < num_locations; i++) {
+        locations[i] = gradientInfo->fractionsdata[i];
+//fprintf(stderr, "locations[%d] %f\n", i, locations[i]);
+    }
+    for (i = 0; i < component_size; i++) {
+        components[i] = gradientInfo->colordata[i];
+//fprintf(stderr, "components[%d] %f, gradientInfo->colordata[%d] %f\n",
+//                  i, components[i], i, gradientInfo->colordata[i]);
+    } 
+    CGContextSaveGState(cgRef);
+    gradient = CGGradientCreateWithColorComponents(colorspace, components, locations, num_locations);
+//fprintf(stderr, "gradientInfo->start.x %f, gradientInfo->start.y %f\n", 
+//                 gradientInfo->start.x, gradientInfo->start.y);
+//fprintf(stderr, "gradientInfo->end.x %f, gradientInfo->end.y %f\n", 
+//                 gradientInfo->end.x, gradientInfo->end.y);
+    if (qsdo->isEvenOddFill) {
+        CGContextEOClip(cgRef);
+    } else {
+        CGContextClip(cgRef);
+    }
+//fprintf(stderr, "gradientInfo->startRadius %f, gradientInfo->endRadius %f\n",startRadius,endRadius);
+    CGContextDrawRadialGradient(cgRef, gradient, gradientInfo->start, 0, gradientInfo->end, endRadius, kCGGradientDrawsAfterEndLocation);    
+    
+    CGContextRestoreGState(cgRef);
+    CGColorSpaceRelease(colorspace);
+    CGGradientRelease(gradient);
+    free(locations);
+    free(gradientInfo->colordata);
+    free(gradientInfo->fractionsdata);
+}
+
 static inline void contextGradientPath(QuartzSDOps* qsdo)
 {
 PRINT("    ContextGradientPath")
+ 
     CGContextRef cgRef = qsdo->cgRef;
     StateShadingInfo* shadingInfo = qsdo->shadingInfo;
 
@@ -827,6 +923,81 @@
     qsdo->renderType = renderType;
 }
 
+void setupGradient(JNIEnv *env, QuartzSDOps* qsdo, jfloat* javaFloatGraphicsStates)
+{
+    static const CGFloat kColorConversionMultiplier = 1.0f/255.0f;
+    qsdo->gradientInfo = (StateGradientInfo*)malloc(sizeof(StateGradientInfo));
+    if (qsdo->gradientInfo == NULL)
+    {
+        [JNFException raise:env as:kOutOfMemoryError reason:"Failed to malloc memory for gradient paint"];
+    }
+
+    qsdo->graphicsStateInfo.simpleStroke = NO;
+    qsdo->graphicsStateInfo.simpleColor = NO;
+
+    qsdo->gradientInfo->start.x    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx1Index];
+    qsdo->gradientInfo->start.y    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory1Index];
+    qsdo->gradientInfo->end.x    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColorx2Index];
+    qsdo->gradientInfo->end.y    = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kColory2Index];
+
+    jobject colorArray  = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kColorArrayIndex)); 
+    if (colorArray != NULL)
+    {
+        jint length = (*env)->GetArrayLength(env, colorArray);
+//fprintf(stderr, "length %d\n", length);
+
+        jint* jcolorData = (jint*)(*env)->GetPrimitiveArrayCritical(env, colorArray, NULL);
+        CGFloat* colors= (CGFloat*)calloc(0, sizeof(CGFloat)*length);
+        if (jcolorData != NULL)
+        {
+            jint i;
+            for (i=0; i<length; i++)
+            {
+                colors[i] = (CGFloat)jcolorData[i];
+            }
+        }
+        (*env)->ReleasePrimitiveArrayCritical(env, colorArray, jcolorData, 0);
+        qsdo->gradientInfo->colordata = (CGFloat*)calloc(0, sizeof(CGFloat)*4*length);
+        for (int i = 0; i < length; i++) 
+        {
+            jint c1 = colors[i];
+//fprintf(stderr, "c1 %x\n", c1);
+            qsdo->gradientInfo->colordata[i*4] = ((c1>>16)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4, qsdo->gradientInfo->colordata[i*4]);
+
+            qsdo->gradientInfo->colordata[i*4+1] = ((c1>>8)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+1, qsdo->gradientInfo->colordata[i*4+1]);
+
+            qsdo->gradientInfo->colordata[i*4+2] = ((c1>>0)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+2, qsdo->gradientInfo->colordata[i*4+2]);
+
+            qsdo->gradientInfo->colordata[i*4+3] = ((c1>>24)&0xff)*kColorConversionMultiplier;
+//fprintf(stderr, "qsdo->gradientInfo->colordata[%d] %f\n", i*4+3, qsdo->gradientInfo->colordata[i*4+3]);
+        }
+        free(colors);
+    }
+    jobject fractionsArray  = ((*env)->GetObjectArrayElement(env, qsdo->javaGraphicsStatesObjects, sun_java2d_OSXSurfaceData_kFractionsArrayIndex)); 
+    if (fractionsArray != NULL)
+    {
+        jint length = (*env)->GetArrayLength(env, fractionsArray);
+//fprintf(stderr, "fractions length %d\n", length);
+        qsdo->gradientInfo->fractionsLength = length;
+
+        jfloat* jfractionsData = (jfloat*)(*env)->GetPrimitiveArrayCritical(env, fractionsArray, NULL);
+        if (jfractionsData != NULL)
+        {
+            qsdo->gradientInfo->fractionsdata = (CGFloat *)malloc(sizeof(CGFloat) *length);
+            jint i;
+            for (i=0; i<length; i++)
+            {
+                qsdo->gradientInfo->fractionsdata[i] = jfractionsData[i];
+//fprintf(stderr, "jfrationsData[%d] %f, qsdo->gradientInfo->fractionsdata[%d] = %f\n", i, jfractionsData[i], i, qsdo->gradientInfo->fractionsdata[i]);
+            }
+            (*env)->ReleasePrimitiveArrayCritical(env, fractionsArray, jfractionsData, 0);
+        }
+    }    
+}
+
 SDRenderType SetUpPaint(JNIEnv *env, QuartzSDOps *qsdo, SDRenderType renderType)
 {
     CGContextRef cgRef = qsdo->cgRef;
@@ -898,6 +1069,21 @@
 
             break;
         }
+        case sun_java2d_OSXSurfaceData_kColorLinearGradient:
+        {
+            renderType = SD_LinearGradient;
+            setupGradient(env, qsdo, javaFloatGraphicsStates);
+            break;
+        }
+
+        case sun_java2d_OSXSurfaceData_kColorRadialGradient:
+        {
+            renderType = SD_RadialGradient;
+            setupGradient(env, qsdo, javaFloatGraphicsStates);
+            qsdo->gradientInfo->radius = javaFloatGraphicsStates[sun_java2d_OSXSurfaceData_kRadiusIndex];
+            break;
+        }
+
         case sun_java2d_OSXSurfaceData_kColorTexture:
         {
             qsdo->patternInfo = (StatePatternInfo*)malloc(sizeof(StatePatternInfo));
@@ -1076,11 +1262,24 @@
             }
             break;
 
+        case SD_LinearGradient:
+            if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
+            {
+                contextQuartzLinearGradientPath(qsdo);
+            }
+            break;
+
+        case SD_RadialGradient:
+            if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
+            {
+                contextQuartzRadialGradientPath(qsdo);
+            }
+            break;
+
         case SD_Pattern:
             if (CGContextIsPathEmpty(qsdo->cgRef) == 0)
             {
-                //TODO:BG
-                //contextTexturePath(env, qsdo);
+                contextTexturePath(env, qsdo);
             }
             break;
 
@@ -1111,4 +1310,8 @@
         gradientPaintReleaseFunction(qsdo->shadingInfo);
         qsdo->shadingInfo = NULL;
     }
+    if (qsdo->gradientInfo != NULL) {
+        gradientPaintReleaseFunction(qsdo->gradientInfo);
+        qsdo->gradientInfo = NULL;
+    }
 }
--- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/font/AWTFont.m	Fri Nov 11 16:44:36 2016 +0100
@@ -193,6 +193,44 @@
     return [sFontFamilyTable objectForKey:fontname];
 }
 
+static void addFont(CTFontUIFontType uiType, 
+                    NSMutableArray *allFonts,
+                    NSMutableDictionary* fontFamilyTable) {
+
+        CTFontRef font = CTFontCreateUIFontForLanguage(uiType, 0.0, NULL);
+        if (font == NULL) {
+            return;
+        }
+        CTFontDescriptorRef desc = CTFontCopyFontDescriptor(font);
+        if (desc == NULL) {
+            CFRelease(font);
+            return;
+        }
+        CFStringRef family = CTFontDescriptorCopyAttribute(desc, kCTFontFamilyNameAttribute);
+        if (family == NULL) {
+            CFRelease(desc);
+            CFRelease(font);
+            return;
+        }
+        CFStringRef name = CTFontDescriptorCopyAttribute(desc, kCTFontNameAttribute);
+        if (name == NULL) {
+            CFRelease(family);
+            CFRelease(desc);
+            CFRelease(font);
+            return;
+        }
+        [allFonts addObject:name];
+        [fontFamilyTable setObject:family forKey:name];
+#ifdef DEBUG
+        NSLog(@"name is : %@", (NSString*)name);
+        NSLog(@"family is : %@", (NSString*)family);
+#endif
+        CFRelease(family);
+        CFRelease(name);
+        CFRelease(desc);
+        CFRelease(font);
+}
+ 
 static NSArray*
 GetFilteredFonts()
 {
@@ -227,6 +265,16 @@
             }
         }
 
+        /*
+         * JavaFX registers these fonts and so JDK needs to do so as well.
+         * If this isn't done we will have mis-matched rendering, since
+         * although these may include fonts that are enumerated normally
+         * they also demonstrably includes fonts that are not.
+         */
+        addFont(kCTFontUIFontSystem, allFonts, fontFamilyTable);
+        addFont(kCTFontUIFontEmphasizedSystem, allFonts, fontFamilyTable);
+        addFont(kCTFontUIFontUserFixedPitch, allFonts, fontFamilyTable);
+
         sFilteredFonts = allFonts;
         sFontFamilyTable = fontFamilyTable;
     }
--- a/jdk/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/macosx/native/libsplashscreen/splashscreen_sys.m	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, 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
@@ -47,6 +47,10 @@
 #include <sizecalc.h>
 #import "ThreadUtilities.h"
 
+NSString* findScaledImageName(NSString *fileName,
+                              NSUInteger dotIndex,
+                              NSString *strToAppend);
+
 static NSScreen* SplashNSScreen()
 {
     return [[NSScreen screens] objectAtIndex: 0];
@@ -134,8 +138,8 @@
 }
 
 jboolean SplashGetScaledImageName(const char* jar, const char* file,
-                                    float *scaleFactor, char *scaledFile,
-                                    const size_t scaledImageLength) {
+                                  float *scaleFactor, char *scaledFile,
+                                  const size_t scaledImageLength) {
     *scaleFactor = 1;
 
     if(isSWTRunning()){
@@ -158,18 +162,14 @@
                                         options:NSBackwardsSearch];
         NSUInteger dotIndex = range.location;
         NSString *fileName2x = nil;
-        
-        if (dotIndex == NSNotFound) {
-            fileName2x = [fileName stringByAppendingString: @"@2x"];
-        } else {
-            fileName2x = [fileName substringToIndex: dotIndex];
-            fileName2x = [fileName2x stringByAppendingString: @"@2x"];
-            fileName2x = [fileName2x stringByAppendingString:
-                          [fileName substringFromIndex: dotIndex]];
+
+        fileName2x = findScaledImageName(fileName, dotIndex, @"@2x");
+        if(![[NSFileManager defaultManager]
+                fileExistsAtPath: fileName2x]) {
+            fileName2x = findScaledImageName(fileName, dotIndex, @"@200pct");
         }
-        
-        if ((fileName2x != nil) && (jar || [[NSFileManager defaultManager]
-                    fileExistsAtPath: fileName2x])){
+        if (jar || [[NSFileManager defaultManager]
+                fileExistsAtPath: fileName2x]){
             if (strlen([fileName2x UTF8String]) > scaledImageLength) {
                 [pool drain];
                 return JNI_FALSE;
@@ -458,3 +458,16 @@
     sendctl(splash, SPLASHCTL_RECONFIGURE);
 }
 
+NSString* findScaledImageName(NSString *fileName, NSUInteger dotIndex, NSString *strToAppend) {
+    NSString *fileName2x = nil;
+    if (dotIndex == NSNotFound) {
+        fileName2x = [fileName stringByAppendingString: strToAppend];
+    } else {
+        fileName2x = [fileName substringToIndex: dotIndex];
+        fileName2x = [fileName2x stringByAppendingString: strToAppend];
+        fileName2x = [fileName2x stringByAppendingString:
+                      [fileName substringFromIndex: dotIndex]];
+    }
+    return fileName2x;
+}
+
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/gif/GIFImageWriter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1314,7 +1314,7 @@
         super(locale);
         this.canWriteCompressed = true;
         this.canWriteProgressive = true;
-        this.compressionTypes = new String[] {"LZW", "lzw"};
+        this.compressionTypes = new String[] {"LZW"};
         this.compressionType = compressionTypes[0];
     }
 
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifComboBoxUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -298,31 +298,24 @@
         public void paintIcon(Component c, Graphics g, int xo, int yo) {
             int w = getIconWidth();
             int h = getIconHeight();
-
-            g.setColor(lightShadow);
-            g.drawLine(xo, yo, xo+w-1, yo);
-            g.drawLine(xo, yo+1, xo+w-3, yo+1);
-            g.setColor(darkShadow);
-            g.drawLine(xo+w-2, yo+1, xo+w-1, yo+1);
+            int x1 = xo + w - 1;
+            int y1 = yo;
+            int x2 = xo + w / 2;
+            int y2 = yo + h - 1;
 
-            for ( int x = xo+1, y = yo+2, dx = w-6; y+1 < yo+h; y += 2 ) {
-                g.setColor(lightShadow);
-                g.drawLine(x, y,   x+1, y);
-                g.drawLine(x, y+1, x+1, y+1);
-                if ( dx > 0 ) {
-                    g.setColor(fill);
-                    g.drawLine(x+2, y,   x+1+dx, y);
-                    g.drawLine(x+2, y+1, x+1+dx, y+1);
-                }
-                g.setColor(darkShadow);
-                g.drawLine(x+dx+2, y,   x+dx+3, y);
-                g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
-                x += 1;
-                dx -= 2;
-            }
+            g.setColor(fill);
+            g.fillPolygon(new int[]{xo, x1, x2}, new int[]{yo, y1, y2}, 3);
+            g.setColor(lightShadow);
+            g.drawLine(xo, yo, x1, y1);
 
+            g.drawLine(xo, yo + 1, x2, y2);
+            g.drawLine(xo, yo + 1, x1, y1 + 1);
+            g.drawLine(xo + 1, yo + 1, x2, y2 - 1);
             g.setColor(darkShadow);
-            g.drawLine(xo+(w/2), yo+h-1, xo+(w/2), yo+h-1);
+            g.drawLine(x1, y1 + 1, x2, y2);
+            g.drawLine(x1 - 1, y1 + 1, x2, y2 - 1);
+            g.drawLine(x1 - 1, y1 + 1, x1, y1 + 1); // corner
+            g.drawLine(x2, y2, x2, y2); // corner
 
         }
 
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifIconFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifIconFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -249,17 +249,11 @@
                 if (check) {
                     // draw check
                     g.setColor(foreground);
-                    g.drawLine(csize-2,1,csize-2,2);
-                    g.drawLine(csize-3,2,csize-3,3);
-                    g.drawLine(csize-4,3,csize-4,4);
-                    g.drawLine(csize-5,4,csize-5,6);
-                    g.drawLine(csize-6,5,csize-6,8);
-                    g.drawLine(csize-7,6,csize-7,10);
-                    g.drawLine(csize-8,7,csize-8,10);
-                    g.drawLine(csize-9,6,csize-9,9);
-                    g.drawLine(csize-10,5,csize-10,8);
-                    g.drawLine(csize-11,5,csize-11,7);
-                    g.drawLine(csize-12,6,csize-12,6);
+                    int[] xa = {csize - 12, csize - 8, csize - 7, csize - 4,
+                                csize - 2, csize - 2, csize - 8, csize - 10,
+                                csize - 11};
+                    int[] ya = new int[]{6, 10, 10, 4, 2, 1, 7, 5, 5};
+                    g.fillPolygon(xa, ya, 9);
                 }
                 g.translate(-x, -y);
                 g.setColor(oldColor);
@@ -301,50 +295,18 @@
 
             if (checkIn){
                 g.setColor(shadow);
-                g.drawLine(x+5,y+0,x+8,y+0);
-                g.drawLine(x+3,y+1,x+4,y+1);
-                g.drawLine(x+9,y+1,x+9,y+1);
-                g.drawLine(x+2,y+2,x+2,y+2);
-                g.drawLine(x+1,y+3,x+1,y+3);
-                g.drawLine(x,y+4,x,y+9);
-                g.drawLine(x+1,y+10,x+1,y+10);
-                g.drawLine(x+2,y+11,x+2,y+11);
+                g.drawArc(x, y, w - 1, h - 1, 45, 180);
                 g.setColor(highlight);
-                g.drawLine(x+3,y+12,x+4,y+12);
-                g.drawLine(x+5,y+13,x+8,y+13);
-                g.drawLine(x+9,y+12,x+10,y+12);
-                g.drawLine(x+11,y+11,x+11,y+11);
-                g.drawLine(x+12,y+10,x+12,y+10);
-                g.drawLine(x+13,y+9,x+13,y+4);
-                g.drawLine(x+12,y+3,x+12,y+3);
-                g.drawLine(x+11,y+2,x+11,y+2);
-                g.drawLine(x+10,y+1,x+10,y+1);
+                g.drawArc(x, y, w - 1, h - 1, 45, -180);
                 g.setColor(dot);
-                g.fillRect(x+4,y+5,6,4);
-                g.drawLine(x+5,y+4,x+8,y+4);
-                g.drawLine(x+5,y+9,x+8,y+9);
+                g.fillOval(x + 3, y + 3, 7, 7);
             }
             else {
                 g.setColor(highlight);
-                g.drawLine(x+5,y+0,x+8,y+0);
-                g.drawLine(x+3,y+1,x+4,y+1);
-                g.drawLine(x+9,y+1,x+9,y+1);
-                g.drawLine(x+2,y+2,x+2,y+2);
-                g.drawLine(x+1,y+3,x+1,y+3);
-                g.drawLine(x,y+4,x,y+9);
-                g.drawLine(x+1,y+10,x+1,y+10);
-                g.drawLine(x+2,y+11,x+2,y+11);
+                g.drawArc(x, y, w - 1, h - 1, 45, 180);
 
                 g.setColor(shadow);
-                g.drawLine(x+3,y+12,x+4,y+12);
-                g.drawLine(x+5,y+13,x+8,y+13);
-                g.drawLine(x+9,y+12,x+10,y+12);
-                g.drawLine(x+11,y+11,x+11,y+11);
-                g.drawLine(x+12,y+10,x+12,y+10);
-                g.drawLine(x+13,y+9,x+13,y+4);
-                g.drawLine(x+12,y+3,x+12,y+3);
-                g.drawLine(x+11,y+2,x+11,y+2);
-                g.drawLine(x+10,y+1,x+10,y+1);
+                g.drawArc(x, y, w - 1, h - 1, 45, -180);
 
             }
         }
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarButton.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifScrollBarButton.java	Fri Nov 11 16:44:36 2016 +0100
@@ -117,95 +117,57 @@
 
         switch (direction) {
         case NORTH:
+            g.setColor(fill);
+            g.fillPolygon(new int[]{cx, 0, s - 1}, new int[]{0, s - 1, s - 1}, 3);
+            g.setColor(trail);
+            g.drawLine(cx, 0, s - 1, s - 2);
+            g.drawLine(0, s - 1, s - 1, s - 1);
+            g.drawLine(s - 1, s - 2, s - 1, s - 1); // corner
             g.setColor(lead);
-            g.drawLine(cx, 0, cx, 0);
-            for (int x = cx - 1, y = 1, dx = 1; y <= s - 2; y += 2) {
-                g.setColor(lead);
-                g.drawLine(x, y, x, y);
-                if (y >= (s - 2)) {
-                    g.drawLine(x, y + 1, x, y + 1);
-                }
-                g.setColor(fill);
-                g.drawLine(x + 1, y, x + dx, y);
-                if (y < (s - 2)) {
-                    g.drawLine(x, y + 1, x + dx + 1, y + 1);
-                }
-                g.setColor(trail);
-                g.drawLine(x + dx + 1, y, x + dx + 1, y);
-                if (y >= (s - 2)) {
-                    g.drawLine(x + 1, y + 1, x + dx + 1, y + 1);
-                }
-                dx += 2;
-                x -= 1;
-            }
+            g.drawLine(cx, 0, 0, s - 2);
+            g.drawLine(cx, 0, cx, 0); // corner
+            g.drawLine(0, s - 1, 0, s - 1); // corner
             break;
 
         case SOUTH:
+            g.setColor(fill);
+            g.fillPolygon(new int[]{0, s - 1, cx}, new int[]{1, 1, s}, 3);
             g.setColor(trail);
-            g.drawLine(cx, s, cx, s);
-            for (int x = cx - 1, y = s - 1, dx = 1; y >= 1; y -= 2) {
-                g.setColor(lead);
-                g.drawLine(x, y, x, y);
-                if (y <= 2) {
-                    g.drawLine(x, y - 1, x + dx + 1, y - 1);
-                }
-                g.setColor(fill);
-                g.drawLine(x + 1, y, x + dx, y);
-                if (y > 2) {
-                    g.drawLine(x, y - 1, x + dx + 1, y - 1);
-                }
-                g.setColor(trail);
-                g.drawLine(x + dx + 1, y, x + dx + 1, y);
-
-                dx += 2;
-                x -= 1;
-            }
+            g.drawLine(s - 1, 2, cx, s);
+            g.drawLine(s - 1, 2, s - 1, 2); // corner
+            g.setColor(lead);
+            g.drawLine(0, 2, cx, s);
+            g.drawLine(0, 1, s - 1, 1);
+            g.drawLine(0, 1, 0, 2);
+            g.setColor(trail);
+            g.drawLine(cx, s, cx, s); // corner
             break;
 
         case EAST:
+            g.setColor(fill);
+            g.fillPolygon(new int[]{1, s, 1}, new int[]{0, cy, s}, 3);
+            g.setColor(trail);
+            g.drawLine(1, s, s, cy);
+            g.drawLine(2, s, 2, s); // corner
             g.setColor(lead);
+            g.drawLine(1, 0, 1, s);
+            g.drawLine(2, 0, s, cy);
+            g.drawLine(2, 0, 2, 0); // corner
             g.drawLine(s, cy, s, cy);
-            for (int y = cy - 1, x = s - 1, dy = 1; x >= 1; x -= 2) {
-                g.setColor(lead);
-                g.drawLine(x, y, x, y);
-                if (x <= 2) {
-                    g.drawLine(x - 1, y, x - 1, y + dy + 1);
-                }
-                g.setColor(fill);
-                g.drawLine(x, y + 1, x, y + dy);
-                if (x > 2) {
-                    g.drawLine(x - 1, y, x - 1, y + dy + 1);
-                }
-                g.setColor(trail);
-                g.drawLine(x, y + dy + 1, x, y + dy + 1);
-
-                dy += 2;
-                y -= 1;
-            }
             break;
 
         case WEST:
+            g.setColor(fill);
+            g.fillPolygon(new int[]{0, s - 1, s - 1}, new int[]{cy, 0, s}, 3);
+            g.drawLine(s - 1, 0, s - 1, s);
             g.setColor(trail);
-            g.drawLine(0, cy, 0, cy);
-            for (int y = cy - 1, x = 1, dy = 1; x <= s - 2; x += 2) {
-                g.setColor(lead);
-                g.drawLine(x, y, x, y);
-                if (x >= (s - 2)) {
-                    g.drawLine(x + 1, y, x + 1, y);
-                }
-                g.setColor(fill);
-                g.drawLine(x, y + 1, x, y + dy);
-                if (x < (s - 2)) {
-                    g.drawLine(x + 1, y, x + 1, y + dy + 1);
-                }
-                g.setColor(trail);
-                g.drawLine(x, y + dy + 1, x, y + dy + 1);
-                if (x >= (s - 2)) {
-                    g.drawLine(x + 1, y + 1, x + 1, y + dy + 1);
-                }
-                dy += 2;
-                y -= 1;
-            }
+            g.drawLine(0, cy, s - 1, s);
+            g.drawLine(s - 1, 0, s - 1, s);
+            g.setColor(lead);
+            g.drawLine(0, cy, s - 2, 0);
+            g.drawLine(s - 2, 0, s - 1, 0); // corner
+            g.setColor(trail);
+            g.drawLine(0, cy, 0, cy); // corner
             break;
         }
     }
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AlawCodec.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -30,25 +30,26 @@
 import java.util.Vector;
 
 import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
 
 /**
  * A-law encodes linear data, and decodes a-law data to linear data.
  *
  * @author Kara Kytle
  */
-public final class AlawCodec extends SunCodec {
+public final class AlawCodec extends FormatConversionProvider {
 
     /* Tables used for A-law decoding */
 
     private static final byte[] ALAW_TABH = new byte[256];
     private static final byte[] ALAW_TABL = new byte[256];
 
-    private static final AudioFormat.Encoding[] alawEncodings = { AudioFormat.Encoding.ALAW, AudioFormat.Encoding.PCM_SIGNED };
-
-    private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
-                                             0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+    private static final short seg_end[] = {
+            0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
+    };
 
     /**
      * Initializes the decode tables.
@@ -73,13 +74,14 @@
         }
     }
 
+    @Override
+    public AudioFormat.Encoding[] getSourceEncodings() {
+        return new Encoding[]{Encoding.ALAW, Encoding.PCM_SIGNED};
+    }
 
-    /**
-     * Constructs a new ALAW codec object.
-     */
-    public AlawCodec() {
-
-        super(alawEncodings, alawEncodings);
+    @Override
+    public AudioFormat.Encoding[] getTargetEncodings() {
+        return getSourceEncodings();
     }
 
     @Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AudioFloatFormatConverter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -562,8 +562,7 @@
 
     @Override
     public Encoding[] getTargetEncodings() {
-        return new Encoding[] { Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED,
-                Encoding.PCM_FLOAT };
+        return getSourceEncodings();
     }
 
     @Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/DirectAudioDevice.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -1034,6 +1034,7 @@
 
             // $$fb part of fix for 4679187: Clip.open() throws unexpected Exceptions
             Toolkit.isFullySpecifiedAudioFormat(format);
+            Toolkit.validateBuffer(format.getFrameSize(), bufferSize);
 
             byte[] newData = new byte[bufferSize];
             System.arraycopy(data, offset, newData, 0, bufferSize);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/PCMtoPCMCodec.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -30,32 +30,26 @@
 import java.util.Vector;
 
 import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
 
 /**
  * Converts among signed/unsigned and little/big endianness of sampled.
  *
  * @author Jan Borgersen
  */
-public final class PCMtoPCMCodec extends SunCodec {
-
-    private static final AudioFormat.Encoding[] inputEncodings = {
-        AudioFormat.Encoding.PCM_SIGNED,
-        AudioFormat.Encoding.PCM_UNSIGNED,
-    };
+public final class PCMtoPCMCodec extends FormatConversionProvider {
 
-    private static final AudioFormat.Encoding[] outputEncodings = {
-        AudioFormat.Encoding.PCM_SIGNED,
-        AudioFormat.Encoding.PCM_UNSIGNED,
-    };
+    @Override
+    public AudioFormat.Encoding[] getSourceEncodings() {
+        return new Encoding[]{Encoding.PCM_SIGNED, Encoding.PCM_UNSIGNED};
+    }
 
-    /**
-     * Constructs a new PCMtoPCM codec object.
-     */
-    public PCMtoPCMCodec() {
-
-        super( inputEncodings, outputEncodings);
+    @Override
+    public AudioFormat.Encoding[] getTargetEncodings() {
+        return getSourceEncodings();
     }
 
     @Override
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingClip.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMixingClip.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -363,9 +363,7 @@
             if (AudioFloatConverter.getConverter(format) == null)
                 throw new IllegalArgumentException("Invalid format : "
                         + format.toString());
-            if (bufferSize % format.getFrameSize() != 0)
-                throw new IllegalArgumentException(
-                        "Buffer size does not represent an integral number of sample frames!");
+            Toolkit.validateBuffer(format.getFrameSize(), bufferSize);
 
             if (data != null) {
                 this.data = Arrays.copyOf(data, data.length);
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SunCodec.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.media.sound;
-
-import javax.sound.sampled.AudioFormat;
-import javax.sound.sampled.spi.FormatConversionProvider;
-
-/**
- * A codec can encode and/or decode audio data.  It provides an
- * AudioInputStream from which processed data may be read.
- * <p>
- * Its input format represents the format of the incoming
- * audio data, or the format of the data in the underlying stream.
- * <p>
- * Its output format represents the format of the processed, outgoing
- * audio data.  This is the format of the data which may be read from
- * the filtered stream.
- *
- * @author Kara Kytle
- */
-abstract class SunCodec extends FormatConversionProvider {
-
-    private final AudioFormat.Encoding[] inputEncodings;
-    private final AudioFormat.Encoding[] outputEncodings;
-
-    /**
-     * Constructs a new codec object.
-     */
-    SunCodec(final AudioFormat.Encoding[] inputEncodings,
-             final AudioFormat.Encoding[] outputEncodings) {
-        this.inputEncodings = inputEncodings;
-        this.outputEncodings = outputEncodings;
-    }
-
-    @Override
-    public final AudioFormat.Encoding[] getSourceEncodings() {
-        AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[inputEncodings.length];
-        System.arraycopy(inputEncodings, 0, encodings, 0, inputEncodings.length);
-        return encodings;
-    }
-
-    @Override
-    public final AudioFormat.Encoding[] getTargetEncodings() {
-        AudioFormat.Encoding[] encodings = new AudioFormat.Encoding[outputEncodings.length];
-        System.arraycopy(outputEncodings, 0, encodings, 0, outputEncodings.length);
-        return encodings;
-    }
-}
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/Toolkit.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/Toolkit.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -149,6 +149,20 @@
         return (long) (((double) frames) / format.getFrameRate() * 1000000.0d);
     }
 
+    /**
+     * Throws an exception if the buffer size does not represent an integral
+     * number of sample frames.
+     */
+    static void validateBuffer(final int frameSize, final int bufferSize) {
+        if (bufferSize % frameSize == 0) {
+            return;
+        }
+        throw new IllegalArgumentException(String.format(
+                "Buffer size (%d) does not represent an integral number of "
+                        + "sample frames (%d)", bufferSize, frameSize));
+    }
+
+
     static void isFullySpecifiedAudioFormat(AudioFormat format) {
         if (!format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
             && !format.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)
--- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/UlawCodec.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -30,26 +30,26 @@
 import java.util.Vector;
 
 import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
 import javax.sound.sampled.AudioInputStream;
 import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.spi.FormatConversionProvider;
 
 /**
  * U-law encodes linear data, and decodes u-law data to linear data.
  *
  * @author Kara Kytle
  */
-public final class UlawCodec extends SunCodec {
+public final class UlawCodec extends FormatConversionProvider {
 
     /* Tables used for U-law decoding */
 
     private static final byte[] ULAW_TABH = new byte[256];
     private static final byte[] ULAW_TABL = new byte[256];
 
-    private static final AudioFormat.Encoding[] ulawEncodings = {AudioFormat.Encoding.ULAW,
-                                                                 AudioFormat.Encoding.PCM_SIGNED};
-
-    private static final short seg_end [] = {0xFF, 0x1FF, 0x3FF,
-                                             0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
+    private static final short seg_end[] = {
+            0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF
+    };
 
     /**
      * Initializes the decode tables.
@@ -69,11 +69,14 @@
         }
     }
 
-    /**
-     * Constructs a new ULAW codec object.
-     */
-    public UlawCodec() {
-        super(ulawEncodings, ulawEncodings);
+    @Override
+    public AudioFormat.Encoding[] getSourceEncodings() {
+        return new Encoding[]{Encoding.ULAW, Encoding.PCM_SIGNED};
+    }
+
+    @Override
+    public AudioFormat.Encoding[] getTargetEncodings() {
+        return getSourceEncodings();
     }
 
     @Override
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java	Fri Nov 11 16:44:36 2016 +0100
@@ -851,8 +851,8 @@
             {
                 comp.setGraphicsConfiguration(gc);
             }
-            public boolean requestFocus(Component comp, FocusEvent.Cause cause) {
-                return comp.requestFocus(cause);
+            public void requestFocus(Component comp, FocusEvent.Cause cause) {
+                comp.requestFocus(cause);
             }
             public boolean canBeFocusOwner(Component comp) {
                 return comp.canBeFocusOwner();
@@ -7511,8 +7511,51 @@
         requestFocusHelper(false, true);
     }
 
-    boolean requestFocus(FocusEvent.Cause cause) {
-        return requestFocusHelper(false, true, cause);
+
+    /**
+     * Requests by the reason of {@code cause} that this Component get the input
+     * focus, and that this Component's top-level ancestor become the
+     * focused Window. This component must be displayable, focusable, visible
+     * and all of its ancestors (with the exception of the top-level Window)
+     * must be visible for the request to be granted. Every effort will be
+     * made to honor the request; however, in some cases it may be
+     * impossible to do so. Developers must never assume that this
+     * Component is the focus owner until this Component receives a
+     * FOCUS_GAINED event.
+     * <p>
+     * The focus request effect may also depend on the provided
+     * cause value. If this request is succeed the {@code FocusEvent}
+     * generated in the result will receive the cause value specified as the
+     * argument of method. If this request is denied because this Component's
+     * top-level Window cannot become the focused Window, the request will be
+     * remembered and will be granted when the Window is later focused by the
+     * user.
+     * <p>
+     * This method cannot be used to set the focus owner to no Component at
+     * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()}
+     * instead.
+     * <p>
+     * Because the focus behavior of this method is platform-dependent,
+     * developers are strongly encouraged to use
+     * {@code requestFocusInWindow(FocusEvent.Cause)} when possible.
+     *
+     * <p>Note: Not all focus transfers result from invoking this method. As
+     * such, a component may receive focus without this or any of the other
+     * {@code requestFocus} methods of {@code Component} being invoked.
+     *
+     * @param  cause the cause why the focus is requested
+     * @see FocusEvent
+     * @see FocusEvent.Cause
+     * @see #requestFocusInWindow(FocusEvent.Cause)
+     * @see java.awt.event.FocusEvent
+     * @see #addFocusListener
+     * @see #isFocusable
+     * @see #isDisplayable
+     * @see KeyboardFocusManager#clearGlobalFocusOwner
+     * @since 9
+     */
+    public void requestFocus(FocusEvent.Cause cause) {
+        requestFocusHelper(false, true, cause);
     }
 
     /**
@@ -7578,9 +7621,77 @@
         return requestFocusHelper(temporary, true);
     }
 
-    boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
+    /**
+     * Requests by the reason of {@code cause} that this {@code Component} get
+     * the input focus, and that this {@code Component}'s top-level ancestor
+     * become the focused {@code Window}. This component must be
+     * displayable, focusable, visible and all of its ancestors (with
+     * the exception of the top-level Window) must be visible for the
+     * request to be granted. Every effort will be made to honor the
+     * request; however, in some cases it may be impossible to do
+     * so. Developers must never assume that this component is the
+     * focus owner until this component receives a FOCUS_GAINED
+     * event. If this request is denied because this component's
+     * top-level window cannot become the focused window, the request
+     * will be remembered and will be granted when the window is later
+     * focused by the user.
+     * <p>
+     * This method returns a boolean value. If {@code false} is returned,
+     * the request is <b>guaranteed to fail</b>. If {@code true} is
+     * returned, the request will succeed <b>unless</b> it is vetoed, or an
+     * extraordinary event, such as disposal of the component's peer, occurs
+     * before the request can be granted by the native windowing system. Again,
+     * while a return value of {@code true} indicates that the request is
+     * likely to succeed, developers must never assume that this component is
+     * the focus owner until this component receives a FOCUS_GAINED event.
+     * <p>
+     * The focus request effect may also depend on the provided
+     * cause value. If this request is succeed the {FocusEvent}
+     * generated in the result will receive the cause value specified as the
+     * argument of the method.
+     * <p>
+     * This method cannot be used to set the focus owner to no component at
+     * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner}
+     * instead.
+     * <p>
+     * Because the focus behavior of this method is platform-dependent,
+     * developers are strongly encouraged to use
+     * {@code requestFocusInWindow} when possible.
+     * <p>
+     * Every effort will be made to ensure that {@code FocusEvent}s
+     * generated as a
+     * result of this request will have the specified temporary value. However,
+     * because specifying an arbitrary temporary state may not be implementable
+     * on all native windowing systems, correct behavior for this method can be
+     * guaranteed only for lightweight {@code Component}s.
+     * This method is not intended
+     * for general use, but exists instead as a hook for lightweight component
+     * libraries, such as Swing.
+     * <p>
+     * Note: Not all focus transfers result from invoking this method. As
+     * such, a component may receive focus without this or any of the other
+     * {@code requestFocus} methods of {@code Component} being invoked.
+     *
+     * @param temporary true if the focus change is temporary,
+     *        such as when the window loses the focus; for
+     *        more information on temporary focus changes see the
+     *<a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
+     *
+     * @param  cause the cause why the focus is requested
+     * @return {@code false} if the focus change request is guaranteed to
+     *         fail; {@code true} if it is likely to succeed
+     * @see FocusEvent
+     * @see FocusEvent.Cause
+     * @see #addFocusListener
+     * @see #isFocusable
+     * @see #isDisplayable
+     * @see KeyboardFocusManager#clearGlobalFocusOwner
+     * @since 9
+     */
+    protected boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
         return requestFocusHelper(temporary, true, cause);
     }
+
     /**
      * Requests that this Component get the input focus, if this
      * Component's top-level ancestor is already the focused
@@ -7629,7 +7740,59 @@
         return requestFocusHelper(false, false);
     }
 
-    boolean requestFocusInWindow(FocusEvent.Cause cause) {
+    /**
+     * Requests by the reason of {@code cause} that this Component get the input
+     * focus, if this Component's top-level ancestor is already the focused
+     * Window. This component must be displayable, focusable, visible
+     * and all of its ancestors (with the exception of the top-level
+     * Window) must be visible for the request to be granted. Every
+     * effort will be made to honor the request; however, in some
+     * cases it may be impossible to do so. Developers must never
+     * assume that this Component is the focus owner until this
+     * Component receives a FOCUS_GAINED event.
+     * <p>
+     * This method returns a boolean value. If {@code false} is returned,
+     * the request is <b>guaranteed to fail</b>. If {@code true} is
+     * returned, the request will succeed <b>unless</b> it is vetoed, or an
+     * extraordinary event, such as disposal of the Component's peer, occurs
+     * before the request can be granted by the native windowing system. Again,
+     * while a return value of {@code true} indicates that the request is
+     * likely to succeed, developers must never assume that this Component is
+     * the focus owner until this Component receives a FOCUS_GAINED event.
+     * <p>
+     * The focus request effect may also depend on the provided
+     * cause value. If this request is succeed the {@code FocusEvent}
+     * generated in the result will receive the cause value specified as the
+     * argument of the method.
+     * <p>
+     * This method cannot be used to set the focus owner to no Component at
+     * all. Use {@code KeyboardFocusManager.clearGlobalFocusOwner()}
+     * instead.
+     * <p>
+     * The focus behavior of this method can be implemented uniformly across
+     * platforms, and thus developers are strongly encouraged to use this
+     * method over {@code requestFocus(FocusEvent.Cause)} when possible.
+     * Code which relies on {@code requestFocus(FocusEvent.Cause)} may exhibit
+     * different focus behavior on different platforms.
+     *
+     * <p>Note: Not all focus transfers result from invoking this method. As
+     * such, a component may receive focus without this or any of the other
+     * {@code requestFocus} methods of {@code Component} being invoked.
+     *
+     * @param  cause the cause why the focus is requested
+     * @return {@code false} if the focus change request is guaranteed to
+     *         fail; {@code true} if it is likely to succeed
+     * @see #requestFocus(FocusEvent.Cause)
+     * @see FocusEvent
+     * @see FocusEvent.Cause
+     * @see java.awt.event.FocusEvent
+     * @see #addFocusListener
+     * @see #isFocusable
+     * @see #isDisplayable
+     * @see KeyboardFocusManager#clearGlobalFocusOwner
+     * @since 9
+     */
+    public boolean requestFocusInWindow(FocusEvent.Cause cause) {
         return requestFocusHelper(false, false, cause);
     }
 
--- a/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/java/awt/DisplayMode.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -142,6 +142,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean equals(Object dm) {
         if (dm instanceof DisplayMode) {
             return equals((DisplayMode)dm);
@@ -153,9 +154,20 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int hashCode() {
         return getWidth() + getHeight() + getBitDepth() * 7
             + getRefreshRate() * 13;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString() {
+        return getWidth() + "x" + getHeight() + "x" +
+               (getBitDepth() > 0 ? getBitDepth() + "bpp": "[Multi depth]")
+               + "@" + (getRefreshRate() > 0 ? getRefreshRate() + "Hz" :
+               "[Unknown refresh rate]");
+    }
 }
--- a/jdk/src/java.desktop/share/classes/java/awt/Font.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/java/awt/Font.java	Fri Nov 11 16:44:36 2016 +0100
@@ -154,6 +154,10 @@
  * associated with a font face, each differing in size, style, transform
  * and font features.
  * <p>
+ * Glyphs may not always be rendered with the requested properties (e.g, font
+ * and style) due to platform limitations such as the absence of suitable
+ * platform fonts to implement a logical font.
+ * <p>
  * The {@link GraphicsEnvironment#getAllFonts() getAllFonts} method
  * of the {@code GraphicsEnvironment} class returns an
  * array of all font faces available in the system. These font faces are
--- a/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/java/awt/SplashScreen.java	Fri Nov 11 16:44:36 2016 +0100
@@ -65,6 +65,16 @@
  * <PRE>
  * java -splash:filename.gif Test
  * </PRE>
+ * HiDPI scaled image is also supported.
+ * Unscaled image name i.e. filename.gif should be passed in
+ * {@code manifest.mf}/{@code -splash:} option for all image types irrespective of
+ * HiDPI and Non-HiDPI.
+ * Following is the naming convention for scaled images.
+ * Screen scale 1.25: filename@125pct.gif
+ * Screen scale 1.50: filename@150pct.gif
+ * Screen scale 2:    filename@200pct.gif and filename@2x.gif both are supported
+ * Screen scale 2.50: filename@250pct.gif
+ * Screen scale 3:    filename@300pct.gif and filename@3x.gif both are supported
  * The command line interface has higher precedence over the manifest
  * setting.
  * <p>
--- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java	Fri Nov 11 16:44:36 2016 +0100
@@ -122,7 +122,7 @@
     }
 
     public Node item(int index) {
-        if (index < 0 || index > nodes.size()) {
+        if (index < 0 || index >= nodes.size()) {
             return null;
         }
         return nodes.get(index);
@@ -882,7 +882,7 @@
     }
 
     private void getElementsByTagName(String name, List<Node> l) {
-        if (nodeName.equals(name)) {
+        if (nodeName.equals(name) || "*".equals(name)) {
             l.add(this);
         }
 
--- a/jdk/src/java.desktop/share/classes/javax/imageio/package.html	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/package.html	Fri Nov 11 16:44:36 2016 +0100
@@ -2,7 +2,7 @@
 <html>
 <head>
 <!--
-Copyright (c) 2000, 2007, 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
@@ -58,6 +58,25 @@
     <th>&nbsp;</th> <th>Reading</th> <th>Writing</th>
     <th>Notes</th> <th>Metadata</th>
 </tr>
+<!-- BMP plugin -->
+<tr>
+    <td><a href="https://msdn.microsoft.com/en-us/library/dd183391.aspx">BMP</a></td>
+    <td align='center'>yes</td>
+    <td align='center'>yes</td>
+    <td align='center'>none</td>
+    <td align='center'><a href='metadata/doc-files/bmp_metadata.html'>
+    BMP metadata format</a></td>
+</tr>
+<!-- GIF plugin -->
+<tr>
+    <td><a href="http://www.w3.org/Graphics/GIF/spec-gif89a.txt">GIF</a></td>
+    <td align='center'>yes</td>
+    <td align='center'>yes</td>
+    <td align='center'><a href="#gif_plugin_notes">
+    GIF plug-in notes</a></td>
+    <td align='center'><a href='metadata/doc-files/gif_metadata.html'>
+    GIF metadata format</a></td>
+</tr>
 <!-- JPEG plugin -->
 <tr>
     <td> <a href="http://www.jpeg.org">JPEG</a></td>
@@ -76,14 +95,15 @@
     <td align='center'><a href='metadata/doc-files/png_metadata.html'>
     PNG metadata format</a></td>
 </tr>
-<!-- BMP plugin -->
+<!-- TIFF plugin -->
 <tr>
-    <td>BMP</td>
+    <td><a href="https://partners.adobe.com/public/developer/en/tiff/TIFF6.pdf">TIFF</a></td>
     <td align='center'>yes</td>
     <td align='center'>yes</td>
-    <td align='center'>none</td>
-    <td align='center'><a href='metadata/doc-files/bmp_metadata.html'>
-    BMP metadata format</a></td>
+    <td align='center'><a href='metadata/doc-files/tiff_metadata.html#Reading'>
+    TIFF plug-in notes</td>
+    <td align='center'><a href='metadata/doc-files/tiff_metadata.html#StreamMetadata'>
+    TIFF metadata format</a></td>
 </tr>
 <!-- WBMP plugin -->
 <tr>
@@ -94,16 +114,6 @@
     <td align='center'><a href='metadata/doc-files/wbmp_metadata.html'>
     WBMP metadata format</a></td>
 </tr>
-<!-- GIF plugin -->
-<tr>
-    <td><a href="http://www.w3.org/Graphics/GIF/spec-gif89a.txt">GIF</a></td>
-    <td align='center'>yes</td>
-    <td align='center'>yes</td>
-    <td align='center'><a href="#gif_plugin_notes">
-    GIF plug-in notes</a></td>
-    <td align='center'><a href='metadata/doc-files/gif_metadata.html'>
-    GIF metadata format</a></td>
-</tr>
 </table>
 </div>
 <BR>
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java	Fri Nov 11 16:44:36 2016 +0100
@@ -55,9 +55,7 @@
      *
      * @see #TAG_GPS_VERSION_ID
      */
-    public static final String GPS_VERSION_2_2 =
-        new String(new byte[] { '2', '2', '0', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String GPS_VERSION_2_2 = "2200";
 
     /**
      * A tag indicating the North or South latitude (type ASCII, count = 2).
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java	Fri Nov 11 16:44:36 2016 +0100
@@ -71,9 +71,7 @@
      *
      * @see #TAG_EXIF_VERSION
      */
-    public static final String EXIF_VERSION_2_1 =
-        new String(new byte[] { '0', '2', '1', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String EXIF_VERSION_2_1 = "0210";
 
     /**
      * A value to be used with the "ExifVersion" tag to indicate Exif version
@@ -82,9 +80,7 @@
      *
      * @see #TAG_EXIF_VERSION
      */
-    public static final String EXIF_VERSION_2_2 =
-        new String(new byte[] { '0', '2', '2', '0' },
-        StandardCharsets.US_ASCII);
+    public static final String EXIF_VERSION_2_2 = "0220";
 
     /**
      * A tag indicating the FlashPix version number (type UNDEFINED,
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java	Fri Nov 11 16:44:36 2016 +0100
@@ -261,7 +261,7 @@
  * @see   TIFFDirectory
  * @see   TIFFTag
  */
-public class TIFFField implements Cloneable {
+public final class TIFFField implements Cloneable {
 
     private static final String[] typeNames = {
         null,
--- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java	Fri Nov 11 16:44:36 2016 +0100
@@ -48,7 +48,7 @@
  *
  * @since 9
  */
-public class TIFFImageReadParam extends ImageReadParam {
+public final class TIFFImageReadParam extends ImageReadParam {
 
     private List<TIFFTagSet> allowedTagSets = new ArrayList<TIFFTagSet>(4);
 
--- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/FormatConversionProvider.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/FormatConversionProvider.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,7 +25,7 @@
 
 package javax.sound.sampled.spi;
 
-import java.util.Objects;
+import java.util.stream.Stream;
 
 import javax.sound.sampled.AudioFormat;
 import javax.sound.sampled.AudioInputStream;
@@ -81,16 +81,8 @@
      *         {@code false}
      * @throws NullPointerException if {@code sourceEncoding} is {@code null}
      */
-    public boolean isSourceEncodingSupported(Encoding sourceEncoding) {
-        Objects.requireNonNull(sourceEncoding);
-        Encoding sourceEncodings[] = getSourceEncodings();
-
-        for(int i=0; i<sourceEncodings.length; i++) {
-            if( sourceEncoding.equals( sourceEncodings[i]) ) {
-                return true;
-            }
-        }
-        return false;
+    public boolean isSourceEncodingSupported(final Encoding sourceEncoding) {
+        return Stream.of(getSourceEncodings()).anyMatch(sourceEncoding::equals);
     }
 
     /**
@@ -103,16 +95,8 @@
      *         {@code false}
      * @throws NullPointerException if {@code targetEncoding} is {@code null}
      */
-    public boolean isTargetEncodingSupported(Encoding targetEncoding) {
-        Objects.requireNonNull(targetEncoding);
-        Encoding targetEncodings[] = getTargetEncodings();
-
-        for(int i=0; i<targetEncodings.length; i++) {
-            if( targetEncoding.equals( targetEncodings[i]) ) {
-                return true;
-            }
-        }
-        return false;
+    public boolean isTargetEncodingSupported(final Encoding targetEncoding) {
+        return Stream.of(getTargetEncodings()).anyMatch(targetEncoding::equals);
     }
 
     /**
@@ -137,17 +121,10 @@
      * @throws NullPointerException if {@code targetEncoding} or
      *         {@code sourceFormat} are {@code null}
      */
-    public boolean isConversionSupported(Encoding targetEncoding,
-                                         AudioFormat sourceFormat) {
-        Objects.requireNonNull(targetEncoding);
-        Encoding targetEncodings[] = getTargetEncodings(sourceFormat);
-
-        for(int i=0; i<targetEncodings.length; i++) {
-            if( targetEncoding.equals( targetEncodings[i]) ) {
-                return true;
-            }
-        }
-        return false;
+    public boolean isConversionSupported(final Encoding targetEncoding,
+                                         final AudioFormat sourceFormat) {
+        return Stream.of(getTargetEncodings(sourceFormat))
+                     .anyMatch(targetEncoding::equals);
     }
 
     /**
@@ -175,17 +152,11 @@
      * @throws NullPointerException if {@code targetFormat} or
      *         {@code sourceFormat} are {@code null}
      */
-    public boolean isConversionSupported(AudioFormat targetFormat,
-                                         AudioFormat sourceFormat) {
-
-        AudioFormat targetFormats[] = getTargetFormats( targetFormat.getEncoding(), sourceFormat );
-
-        for(int i=0; i<targetFormats.length; i++) {
-            if( targetFormat.matches( targetFormats[i] ) ) {
-                return true;
-            }
-        }
-        return false;
+    public boolean isConversionSupported(final AudioFormat targetFormat,
+                                         final AudioFormat sourceFormat) {
+        final Encoding targetEncoding = targetFormat.getEncoding();
+        return Stream.of(getTargetFormats(targetEncoding, sourceFormat))
+                     .anyMatch(targetFormat::matches);
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JRootPane.java	Fri Nov 11 16:44:36 2016 +0100
@@ -320,28 +320,6 @@
      * a UI-specific action like pressing the <b>Enter</b> key occurs.
      */
     protected JButton defaultButton;
-    /**
-     * As of Java 2 platform v1.3 this unusable field is no longer used.
-     * To override the default button you should replace the <code>Action</code>
-     * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
-     * the key bindings specification for further details.
-     *
-     * @deprecated As of Java 2 platform v1.3.
-     *  @see #defaultButton
-     */
-    @Deprecated
-    protected DefaultAction defaultPressAction;
-    /**
-     * As of Java 2 platform v1.3 this unusable field is no longer used.
-     * To override the default button you should replace the <code>Action</code>
-     * in the <code>JRootPane</code>'s <code>ActionMap</code>. Please refer to
-     * the key bindings specification for further details.
-     *
-     * @deprecated As of Java 2 platform v1.3.
-     *  @see #defaultButton
-     */
-    @Deprecated
-    protected DefaultAction defaultReleaseAction;
 
     /**
      * Whether or not true double buffering should be used.  This is typically
@@ -829,35 +807,6 @@
         }
     }
 
-    @SuppressWarnings("serial")
-    static class DefaultAction extends AbstractAction {
-        JButton owner;
-        JRootPane root;
-        boolean press;
-        DefaultAction(JRootPane root, boolean press) {
-            this.root = root;
-            this.press = press;
-        }
-        public void setOwner(JButton owner) {
-            this.owner = owner;
-        }
-        public void actionPerformed(ActionEvent e) {
-            if (owner != null && SwingUtilities.getRootPane(owner) == root) {
-                ButtonModel model = owner.getModel();
-                if (press) {
-                    model.setArmed(true);
-                    model.setPressed(true);
-                } else {
-                    model.setPressed(false);
-                }
-            }
-        }
-        public boolean isEnabled() {
-            return owner.getModel().isEnabled();
-        }
-    }
-
-
     /**
      * Overridden to enforce the position of the glass component as
      * the zero child.
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -46,7 +46,11 @@
      * @return the coordinates as a {@code Rectangle}
      * @exception BadLocationException  if the given position does not
      *   represent a valid location in the associated document
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
+    @Deprecated(since = "9")
     public abstract Rectangle modelToView(JTextComponent t, int pos) throws BadLocationException;
 
     /**
@@ -59,7 +63,11 @@
      * @return the coordinates as a {@code Rectangle}
      * @exception BadLocationException  if the given position does not
      *   represent a valid location in the associated document
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
+    @Deprecated(since = "9")
     public abstract Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) throws BadLocationException;
 
     /**
@@ -92,7 +100,11 @@
      *   should be in the same coordinate system as the mouse
      *   events.
      * @return the offset from the start of the document &gt;= 0
+     *
+     * @deprecated replaced by
+     *     {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
      */
+    @Deprecated(since = "9")
     public abstract int viewToModel(JTextComponent t, Point pt);
 
     /**
@@ -110,7 +122,11 @@
      *
      * @return the location within the model that best represents the
      *         given point in the view &gt;= 0
+     *
+     * @deprecated replaced by
+     *     {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
      */
+    @Deprecated(since = "9")
     public abstract int viewToModel(JTextComponent t, Point pt,
                                     Position.Bias[] biasReturn);
 
@@ -222,7 +238,11 @@
      * @return a {@code String} containing the tooltip
      * @see javax.swing.text.JTextComponent#getToolTipText
      * @since 1.4
+     *
+     * @deprecated replaced by
+     *     {@link #getToolTipText2D(JTextComponent, Point2D)}
      */
+    @Deprecated(since = "9")
     public String getToolTipText(JTextComponent t, Point pt) {
         return null;
     }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,8 @@
 import java.awt.*;
 import java.awt.event.*;
 import java.awt.datatransfer.*;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 import java.awt.im.InputContext;
 import java.beans.*;
 import java.io.*;
@@ -1047,7 +1049,12 @@
      * @exception BadLocationException  if the given position does not
      *   represent a valid location in the associated document
      * @see TextUI#modelToView
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
+    @Deprecated(since = "9")
+    @Override
     public Rectangle modelToView(JTextComponent tc, int pos) throws BadLocationException {
         return modelToView(tc, pos, Position.Bias.Forward);
     }
@@ -1064,8 +1071,30 @@
      * @exception BadLocationException  if the given position does not
      *   represent a valid location in the associated document
      * @see TextUI#modelToView
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
-    public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias bias) throws BadLocationException {
+    @Deprecated(since = "9")
+    @Override
+    public Rectangle modelToView(JTextComponent tc, int pos, Position.Bias bias)
+            throws BadLocationException
+    {
+        return (Rectangle) modelToView(tc, pos, bias, false);
+    }
+
+    @Override
+    public Rectangle2D modelToView2D(JTextComponent tc, int pos,
+                                     Position.Bias bias)
+            throws BadLocationException
+    {
+        return modelToView(tc, pos, bias, true);
+    }
+
+    private Rectangle2D modelToView(JTextComponent tc, int pos,
+                                    Position.Bias bias, boolean useFPAPI)
+            throws BadLocationException
+    {
         Document doc = editor.getDocument();
         if (doc instanceof AbstractDocument) {
             ((AbstractDocument)doc).readLock();
@@ -1076,7 +1105,7 @@
                 rootView.setSize(alloc.width, alloc.height);
                 Shape s = rootView.modelToView(pos, alloc, bias);
                 if (s != null) {
-                  return s.getBounds();
+                    return useFPAPI ? s.getBounds2D() : s.getBounds();
                 }
             }
         } finally {
@@ -1099,7 +1128,12 @@
      * @return the offset from the start of the document &gt;= 0,
      *   -1 if not painted
      * @see TextUI#viewToModel
+     *
+     * @deprecated replaced by
+     *     {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
      */
+    @Deprecated(since = "9")
+    @Override
     public int viewToModel(JTextComponent tc, Point pt) {
         return viewToModel(tc, pt, discardBias);
     }
@@ -1116,9 +1150,25 @@
      * @return the offset from the start of the document &gt;= 0,
      *   -1 if the component doesn't yet have a positive size.
      * @see TextUI#viewToModel
+     *
+     * @deprecated replaced by
+     *     {@link #viewToModel2D(JTextComponent, Point2D, Position.Bias[])}
      */
+    @Deprecated(since = "9")
+    @Override
     public int viewToModel(JTextComponent tc, Point pt,
                            Position.Bias[] biasReturn) {
+        return viewToModel(tc, pt.x, pt.y, biasReturn);
+    }
+
+    @Override
+    public int viewToModel2D(JTextComponent tc, Point2D pt,
+                             Position.Bias[] biasReturn) {
+        return viewToModel(tc, (float) pt.getX(), (float) pt.getY(), biasReturn);
+    }
+
+    private int viewToModel(JTextComponent tc, float x, float y,
+                            Position.Bias[] biasReturn) {
         int offs = -1;
         Document doc = editor.getDocument();
         if (doc instanceof AbstractDocument) {
@@ -1128,7 +1178,7 @@
             Rectangle alloc = getVisibleEditorRect();
             if (alloc != null) {
                 rootView.setSize(alloc.width, alloc.height);
-                offs = rootView.viewToModel(pt.x, pt.y, alloc, biasReturn);
+                offs = rootView.viewToModel(x, y, alloc, biasReturn);
             }
         } finally {
             if (doc instanceof AbstractDocument) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalBorders.java	Fri Nov 11 16:44:36 2016 +0100
@@ -739,7 +739,7 @@
         /**
          * The instance of {@code MetalBumps}.
          */
-        protected MetalBumps bumps = new MetalBumps( 10, 10,
+        private MetalBumps bumps = new MetalBumps( 10, 10,
                                       MetalLookAndFeel.getControlHighlight(),
                                       MetalLookAndFeel.getControlDarkShadow(),
                                      UIManager.getColor("ToolBar.background"));
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalFileChooserUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -923,7 +923,7 @@
      * @param fc a {@code JFileChooser}
      * @return a new instance of {@code DirectoryComboBoxRenderer}
      */
-    protected DirectoryComboBoxRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
+    private DefaultListCellRenderer createDirectoryComboBoxRenderer(JFileChooser fc) {
         return new DirectoryComboBoxRenderer();
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/MetalScrollBarUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -62,7 +62,7 @@
     /**
      * The metal bumps.
      */
-    protected MetalBumps bumps;
+    private MetalBumps bumps;
 
     /**
      * The increase button.
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiTextUI.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/multi/MultiTextUI.java	Fri Nov 11 16:44:36 2016 +0100
@@ -38,6 +38,8 @@
 import javax.swing.JComponent;
 import java.awt.Graphics;
 import java.awt.Dimension;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 import javax.accessibility.Accessible;
 
 /**
@@ -97,7 +99,11 @@
      *
      * @return the value obtained from the first UI, which is
      * the UI obtained from the default <code>LookAndFeel</code>
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
+    @Deprecated(since = "9")
     public Rectangle modelToView(JTextComponent a, int b)
             throws BadLocationException {
         Rectangle returnValue =
@@ -113,7 +119,12 @@
      *
      * @return the value obtained from the first UI, which is
      * the UI obtained from the default <code>LookAndFeel</code>
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(JTextComponent, int, Position.Bias)}
      */
+    @Deprecated(since = "9")
+    @Override
     public Rectangle modelToView(JTextComponent a, int b, Position.Bias c)
             throws BadLocationException {
         Rectangle returnValue =
@@ -124,12 +135,24 @@
         return returnValue;
     }
 
+    @Override
+    public Rectangle2D modelToView2D(JTextComponent a, int b, Position.Bias c) throws BadLocationException {
+        Rectangle2D returnValue =
+            ((TextUI) (uis.elementAt(0))).modelToView2D(a,b,c);
+        for (int i = 1; i < uis.size(); i++) {
+            ((TextUI) (uis.elementAt(i))).modelToView2D(a,b,c);
+        }
+        return returnValue;
+    }
+
     /**
      * Invokes the <code>viewToModel</code> method on each UI handled by this object.
      *
      * @return the value obtained from the first UI, which is
      * the UI obtained from the default <code>LookAndFeel</code>
      */
+    @Deprecated(since = "9")
+    @Override
     public int viewToModel(JTextComponent a, Point b) {
         int returnValue =
             ((TextUI) (uis.elementAt(0))).viewToModel(a,b);
@@ -145,6 +168,8 @@
      * @return the value obtained from the first UI, which is
      * the UI obtained from the default <code>LookAndFeel</code>
      */
+    @Deprecated(since = "9")
+    @Override
     public int viewToModel(JTextComponent a, Point b, Position.Bias[] c) {
         int returnValue =
             ((TextUI) (uis.elementAt(0))).viewToModel(a,b,c);
@@ -154,6 +179,16 @@
         return returnValue;
     }
 
+    @Override
+    public int viewToModel2D(JTextComponent a, Point2D b, Position.Bias[] c) {
+        int returnValue =
+            ((TextUI) (uis.elementAt(0))).viewToModel2D(a,b,c);
+        for (int i = 1; i < uis.size(); i++) {
+            ((TextUI) (uis.elementAt(i))).viewToModel2D(a,b,c);
+        }
+        return returnValue;
+    }
+
     /**
      * Invokes the <code>getNextVisualPositionFrom</code> method on each UI handled by this object.
      *
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter1.java	Fri Nov 11 16:44:36 2016 +0100
@@ -98,26 +98,27 @@
         Rectangle alloc = (a instanceof Rectangle) ? (Rectangle)a : a.getBounds();
 
         // determine the x coordinate to render the glyphs
-        int x = alloc.x;
+        float x = alloc.x;
         int p = v.getStartOffset();
         int[] justificationData = getJustificationData(v);
         if (p != p0) {
             text = v.getText(p, p0);
-            int width = Utilities.getTabbedTextWidth(v, text, metrics, x, expander, p,
-                                                     justificationData);
+            float width = Utilities.getTabbedTextWidth(v, text, metrics, x,
+                                                       expander, p,
+                                                       justificationData);
             x += width;
             SegmentCache.releaseSharedSegment(text);
         }
 
         // determine the y coordinate to render the glyphs
-        int y = alloc.y + metrics.getHeight() - metrics.getDescent();
+        float y = alloc.y + metrics.getHeight() - metrics.getDescent();
 
         // render the glyphs
         text = v.getText(p0, p1);
         g.setFont(metrics.getFont());
 
         Utilities.drawTabbedText(v, text, x, y, g, expander,p0,
-                                 justificationData);
+                                 justificationData, true);
         SegmentCache.releaseSharedSegment(text);
     }
 
@@ -210,9 +211,9 @@
         TabExpander expander = v.getTabExpander();
         Segment s = v.getText(p0, v.getEndOffset());
         int[] justificationData = getJustificationData(v);
-        int index = Utilities.getTabbedTextOffset(v, s, metrics, (int)x, (int)(x+len),
+        int index = Utilities.getTabbedTextOffset(v, s, metrics, x, (x+len),
                                                   expander, p0, false,
-                                                  justificationData);
+                                                  justificationData, true);
         SegmentCache.releaseSharedSegment(s);
         int p1 = p0 + index;
         return p1;
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphPainter2.java	Fri Nov 11 16:44:36 2016 +0100
@@ -145,8 +145,9 @@
 
         // vertical at the baseline, should use slope and check if glyphs
         // are being rendered vertically.
-        alloc.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight());
-        return alloc;
+        Rectangle2D rect = new Rectangle2D.Float();
+        rect.setRect(alloc.getX() + locs[0], alloc.getY(), 1, alloc.getHeight());
+        return rect;
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java	Fri Nov 11 16:44:36 2016 +0100
@@ -49,6 +49,8 @@
 import java.awt.im.InputMethodRequests;
 import java.awt.font.TextHitInfo;
 import java.awt.font.TextAttribute;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
 
 import java.awt.print.Printable;
 import java.awt.print.PrinterException;
@@ -1370,12 +1372,38 @@
      * @exception BadLocationException if the given position does not
      *   represent a valid location in the associated document
      * @see TextUI#modelToView
+     *
+     * @deprecated replaced by
+     *     {@link #modelToView2D(int)}
      */
+    @Deprecated(since = "9")
     public Rectangle modelToView(int pos) throws BadLocationException {
         return getUI().modelToView(this, pos);
     }
 
     /**
+     * Converts the given location in the model to a place in
+     * the view coordinate system.
+     * The component must have a positive size for
+     * this translation to be computed (i.e. layout cannot
+     * be computed until the component has been sized).  The
+     * component does not have to be visible or painted.
+     *
+     * @param pos the position {@code >= 0}
+     * @return the coordinates as a rectangle, with (r.x, r.y) as the location
+     *   in the coordinate system, or null if the component does
+     *   not yet have a positive size.
+     * @exception BadLocationException if the given position does not
+     *   represent a valid location in the associated document
+     * @see TextUI#modelToView2D
+     *
+     * @since 9
+     */
+    public Rectangle2D modelToView2D(int pos) throws BadLocationException {
+        return getUI().modelToView2D(this, pos, Position.Bias.Forward);
+    }
+
+    /**
      * Converts the given place in the view coordinate system
      * to the nearest representative location in the model.
      * The component must have a positive size for
@@ -1388,12 +1416,36 @@
      *   or -1 if the component does not yet have a positive
      *   size.
      * @see TextUI#viewToModel
+     *
+     * @deprecated replaced by
+     *     {@link #viewToModel2D(Point2D)}
      */
+    @Deprecated(since = "9")
     public int viewToModel(Point pt) {
         return getUI().viewToModel(this, pt);
     }
 
     /**
+     * Converts the given place in the view coordinate system
+     * to the nearest representative location in the model.
+     * The component must have a positive size for
+     * this translation to be computed (i.e. layout cannot
+     * be computed until the component has been sized).  The
+     * component does not have to be visible or painted.
+     *
+     * @param pt the location in the view to translate
+     * @return the offset {@code >= 0} from the start of the document,
+     *   or {@code -1} if the component does not yet have a positive
+     *   size.
+     * @see TextUI#viewToModel2D
+     *
+     * @since 9
+     */
+    public int viewToModel2D(Point2D pt) {
+        return getUI().viewToModel2D(this, pt, new Position.Bias[1]);
+    }
+
+    /**
      * Transfers the currently selected range in the associated
      * text model to the system clipboard, removing the contents
      * from the model.  The current selection is reset.  Does nothing
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/ParagraphView.java	Fri Nov 11 16:44:36 2016 +0100
@@ -27,6 +27,7 @@
 import java.util.Arrays;
 import java.awt.*;
 import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
 import javax.swing.event.*;
 import javax.swing.SizeRequirements;
 
@@ -888,10 +889,9 @@
             int height = r.height;
             int y = r.y;
             Shape loc = super.modelToView(pos, a, b);
-            r = loc.getBounds();
-            r.height = height;
-            r.y = y;
-            return r;
+            Rectangle2D bounds = loc.getBounds2D();
+            bounds.setRect(bounds.getX(), y, bounds.getWidth(), height);
+            return bounds;
         }
 
         /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PasswordView.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,7 +26,11 @@
 
 import sun.swing.SwingUtilities2;
 import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import javax.swing.JPasswordField;
+import static javax.swing.text.PlainView.isFPMethodOverriden;
 
 /**
  * Implements a View suitable for use in JPasswordField
@@ -61,15 +65,40 @@
      * @param p1 the ending offset in the model &gt;= p0
      * @return the X location of the end of the range &gt;= 0
      * @exception BadLocationException if p0 or p1 are out of range
+     *
+     * @deprecated replaced by
+     *     {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
      */
+    @Deprecated(since = "9")
+    @Override
     protected int drawUnselectedText(Graphics g, int x, int y,
                                      int p0, int p1) throws BadLocationException {
+        return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+    }
 
+    @Override
+    protected float drawUnselectedText(Graphics2D g, float x, float y,
+                                       int p0, int p1)
+            throws BadLocationException
+    {
+        return drawUnselectedTextImpl(g, x, y, p0, p1, true);
+    }
+
+    private float drawUnselectedTextImpl(Graphics g, float x, float y,
+                                         int p0, int p1,
+                                         boolean useFPAPI)
+            throws BadLocationException
+    {
         Container c = getContainer();
         if (c instanceof JPasswordField) {
             JPasswordField f = (JPasswordField) c;
-            if (! f.echoCharIsSet()) {
-                return super.drawUnselectedText(g, x, y, p0, p1);
+            if (!f.echoCharIsSet()) {
+                boolean useDrawUnselectedFPAPI = useFPAPI
+                        && drawUnselectedTextOverridden
+                        && g instanceof Graphics2D;
+                return (useDrawUnselectedFPAPI )
+                        ? super.drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+                        : super.drawUnselectedText(g, (int) x, (int) y, p0, p1);
             }
             if (f.isEnabled()) {
                 g.setColor(f.getForeground());
@@ -79,8 +108,13 @@
             }
             char echoChar = f.getEchoChar();
             int n = p1 - p0;
+            boolean useEchoCharFPAPI = useFPAPI
+                    && drawEchoCharacterOverridden
+                    && g instanceof Graphics2D;
             for (int i = 0; i < n; i++) {
-                x = drawEchoCharacter(g, x, y, echoChar);
+                x = (useEchoCharFPAPI)
+                        ? drawEchoCharacter((Graphics2D) g, x, y, echoChar)
+                        : drawEchoCharacter(g, (int) x, (int) y, echoChar);
             }
         }
         return x;
@@ -100,20 +134,50 @@
      * @param p1 the ending offset in the model &gt;= p0
      * @return the X location of the end of the range &gt;= 0
      * @exception BadLocationException if p0 or p1 are out of range
+     *
+     * @deprecated replaced by
+     *     {@link #drawSelectedText(Graphics2D, float, float, int, int)}
      */
+    @Deprecated(since = "9")
+    @Override
     protected int drawSelectedText(Graphics g, int x,
                                    int y, int p0, int p1) throws BadLocationException {
+        return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+    }
+
+    @Override
+    protected float drawSelectedText(Graphics2D g, float x, float y,
+                                     int p0, int p1) throws BadLocationException
+    {
+        return drawSelectedTextImpl(g, x, y, p0, p1, true);
+    }
+
+    private float drawSelectedTextImpl(Graphics g, float x, float y,
+                                       int p0, int p1,
+                                       boolean useFPAPI)
+            throws BadLocationException {
         g.setColor(selected);
         Container c = getContainer();
         if (c instanceof JPasswordField) {
             JPasswordField f = (JPasswordField) c;
-            if (! f.echoCharIsSet()) {
-                return super.drawSelectedText(g, x, y, p0, p1);
+            if (!f.echoCharIsSet()) {
+                boolean useDrawUnselectedFPAPI = useFPAPI
+                        && drawSelectedTextOverridden
+                        && g instanceof Graphics2D;
+                return (useFPAPI)
+                        ? super.drawSelectedText((Graphics2D) g, x, y, p0, p1)
+                        : super.drawSelectedText(g, (int) x, (int) y, p0, p1);
             }
             char echoChar = f.getEchoChar();
             int n = p1 - p0;
+            boolean useEchoCharFPAPI = useFPAPI
+                    && drawEchoCharacterOverridden
+                    && g instanceof Graphics2D;
             for (int i = 0; i < n; i++) {
-                x = drawEchoCharacter(g, x, y, echoChar);
+                x = (useEchoCharFPAPI)
+                        ? drawEchoCharacter((Graphics2D) g, x, y, echoChar)
+                        : drawEchoCharacter(g, (int) x, (int) y, echoChar);
+
             }
         }
         return x;
@@ -130,12 +194,13 @@
      * @param y the starting Y coordinate &gt;= 0
      * @param c the echo character
      * @return the updated X position &gt;= 0
+     *
+     * @deprecated replaced by
+     *     {@link #drawEchoCharacter(Graphics2D, float, float, char)}
      */
+    @Deprecated(since = "9")
     protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
-        ONE[0] = c;
-        SwingUtilities2.drawChars(Utilities.getJComponent(this),
-                                  g, ONE, 0, 1, x, y);
-        return x + g.getFontMetrics().charWidth(c);
+        return (int) drawEchoCharacterImpl(g, x, y, c, false);
     }
 
     /**
@@ -144,18 +209,29 @@
      * object is set to the appropriate foreground color for selected
      * or unselected text.
      *
-     * @implSpec This implementation calls
-     * {@link #drawEchoCharacter(Graphics, int, int, char)
-     *      drawEchoCharacter((Graphics) g, (int) x, (int) y, c)}.
-     *
      * @param g the graphics context
      * @param x the starting X coordinate {@code >= 0}
      * @param y the starting Y coordinate {@code >= 0}
      * @param c the echo character
      * @return the updated X position {@code >= 0}
+     *
+     * @since 9
      */
     protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
-        return drawEchoCharacter((Graphics) g, (int) x, (int) y, c);
+        return drawEchoCharacterImpl(g, x, y, c, true);
+    }
+
+    private float drawEchoCharacterImpl(Graphics g, float x, float y,
+                                        char c, boolean useFPAPI) {
+        ONE[0] = c;
+        SwingUtilities2.drawChars(Utilities.getJComponent(this),
+                                  g, ONE, 0, 1, x, y);
+        if (useFPAPI) {
+            return x + g.getFontMetrics().charWidth(c);
+        } else {
+            FontRenderContext frc = g.getFontMetrics().getFontRenderContext();
+            return x + (float) g.getFont().getStringBounds(ONE, 0, 1, frc).getWidth();
+        }
     }
 
     /**
@@ -253,4 +329,23 @@
     }
 
     static char[] ONE = new char[1];
+
+    private final boolean drawEchoCharacterOverridden;
+
+    {
+        final Class<?> CLS = getClass();
+        final Class<?> INT = Integer.TYPE;
+        final Class<?> FP = Float.TYPE;
+        final Class<?> CHAR = Character.TYPE;
+
+        drawEchoCharacterOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {Graphics.class, INT, INT, CHAR};
+                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, CHAR};
+                return isFPMethodOverriden("drawEchoCharacter", CLS, intTypes, fpTypes);
+            }
+        });
+    }
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/PlainView.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,11 +24,14 @@
  */
 package javax.swing.text;
 
-import java.util.Vector;
-import java.util.Properties;
 import java.awt.*;
+import java.awt.font.FontRenderContext;
+import java.awt.geom.Rectangle2D;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Objects;
 import javax.swing.event.*;
+import java.lang.reflect.Module;
 
 /**
  * Implements View interface for a simple multi-line text view
@@ -61,17 +64,6 @@
     }
 
     /**
-     * Returns the tab size set for the document, defaulting to 8.
-     *
-     * @implSpec This implementation calls {@link #getTabSize() getTabSize()}.
-     *
-     * @return the tab size
-     */
-    protected float getFractionalTabSize() {
-        return getTabSize();
-    }
-
-    /**
      * Renders a line of text, suppressing whitespace at the end
      * and expanding any tabs.  This is implemented to make calls
      * to the methods <code>drawUnselectedText</code> and
@@ -84,8 +76,16 @@
      * @param y the starting Y position &gt;= 0
      * @see #drawUnselectedText
      * @see #drawSelectedText
+     *
+     * @deprecated replaced by
+     *     {@link #drawLine(int, Graphics2D, float, float)}
      */
+    @Deprecated(since = "9")
     protected void drawLine(int lineIndex, Graphics g, int x, int y) {
+        drawLineImpl(lineIndex, g, x, y);
+    }
+
+    private void drawLineImpl(int lineIndex, Graphics g, float x, float y) {
         Element line = getElement().getElement(lineIndex);
         Element elem;
 
@@ -112,22 +112,23 @@
      * {@code drawSelectedText} so that the way selected and
      * unselected text are rendered can be customized.
      *
-     * @implSpec This implementation calls
-     * {@link #drawLine(int, Graphics, int, int)
-     * drawLine(lineIndex, (Graphics)g, (int) x, (int) y)}.
-     *
      * @param lineIndex the line to draw {@code >= 0}
      * @param g the {@code Graphics} context
      * @param x the starting X position {@code >= 0}
      * @param y the starting Y position {@code >= 0}
      * @see #drawUnselectedText
      * @see #drawSelectedText
+     *
+     * @since 9
      */
     protected void drawLine(int lineIndex, Graphics2D g, float x, float y) {
-        drawLine(lineIndex, (Graphics)g, (int) x, (int) y);
+        drawLineImpl(lineIndex, g, x, y);
     }
 
-    private int drawElement(int lineIndex, Element elem, Graphics g, int x, int y) throws BadLocationException {
+    private float drawElement(int lineIndex, Element elem, Graphics g,
+                              float x, float y)
+                              throws BadLocationException
+    {
         int p0 = elem.getStartOffset();
         int p1 = elem.getEndOffset();
         p1 = Math.min(getDocument().getLength(), p1);
@@ -144,23 +145,23 @@
         } else {
             if (sel0 == sel1 || selected == unselected) {
                 // no selection, or it is invisible
-                x = drawUnselectedText(g, x, y, p0, p1);
+                x = callDrawUnselectedText(g, x, y, p0, p1);
             } else if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) {
-                x = drawSelectedText(g, x, y, p0, p1);
+                x = callDrawSelectedText(g, x, y, p0, p1);
             } else if (sel0 >= p0 && sel0 <= p1) {
                 if (sel1 >= p0 && sel1 <= p1) {
-                    x = drawUnselectedText(g, x, y, p0, sel0);
-                    x = drawSelectedText(g, x, y, sel0, sel1);
-                    x = drawUnselectedText(g, x, y, sel1, p1);
+                    x = callDrawUnselectedText(g, x, y, p0, sel0);
+                    x = callDrawSelectedText(g, x, y, sel0, sel1);
+                    x = callDrawUnselectedText(g, x, y, sel1, p1);
                 } else {
-                    x = drawUnselectedText(g, x, y, p0, sel0);
-                    x = drawSelectedText(g, x, y, sel0, p1);
+                    x = callDrawUnselectedText(g, x, y, p0, sel0);
+                    x = callDrawSelectedText(g, x, y, sel0, p1);
                 }
             } else if (sel1 >= p0 && sel1 <= p1) {
-                x = drawSelectedText(g, x, y, p0, sel1);
-                x = drawUnselectedText(g, x, y, sel1, p1);
+                x = callDrawSelectedText(g, x, y, p0, sel1);
+                x = callDrawUnselectedText(g, x, y, sel1, p1);
             } else {
-                x = drawUnselectedText(g, x, y, p0, p1);
+                x = callDrawUnselectedText(g, x, y, p0, p1);
             }
         }
 
@@ -178,14 +179,36 @@
      * @param p1 the ending position in the model &gt;= 0
      * @return the X location of the end of the range &gt;= 0
      * @exception BadLocationException if the range is invalid
+     *
+     * @deprecated replaced by
+     *     {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
      */
+    @Deprecated(since = "9")
     protected int drawUnselectedText(Graphics g, int x, int y,
                                      int p0, int p1) throws BadLocationException {
+        return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+    }
+
+    private float callDrawUnselectedText(Graphics g, float x, float y,
+                                         int p0, int p1)
+                                         throws BadLocationException
+    {
+        return drawUnselectedTextOverridden && (g instanceof Graphics2D)
+                ? drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+                : drawUnselectedText(g, (int) x, (int) y, p0, p1);
+    }
+
+    private float drawUnselectedTextImpl(Graphics g, float x, float y,
+                                         int p0, int p1,
+                                         boolean useFPAPI)
+            throws BadLocationException
+    {
         g.setColor(unselected);
         Document doc = getDocument();
         Segment s = SegmentCache.getSharedSegment();
         doc.getText(p0, p1 - p0, s);
-        int ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0);
+        float ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0, null,
+                                             useFPAPI);
         SegmentCache.releaseSharedSegment(s);
         return ret;
     }
@@ -194,10 +217,6 @@
      * Renders the given range in the model as normal unselected
      * text.  Uses the foreground or disabled color to render the text.
      *
-     * @implSpec This implementation calls
-     * {@link #drawUnselectedText(Graphics, int, int, int, int)
-     * drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
-     *
      * @param g the graphics context
      * @param x the starting X coordinate {@code >= 0}
      * @param y the starting Y coordinate {@code >= 0}
@@ -205,10 +224,12 @@
      * @param p1 the ending position in the model {@code >= 0}
      * @return the X location of the end of the range {@code >= 0}
      * @exception BadLocationException if the range is invalid
+     *
+     * @since 9
      */
     protected float drawUnselectedText(Graphics2D g, float x, float y,
                                        int p0, int p1) throws BadLocationException {
-        return drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1);
+        return drawUnselectedTextImpl(g, x, y, p0, p1, true);
     }
 
     /**
@@ -224,14 +245,38 @@
      * @param p1 the ending position in the model &gt;= 0
      * @return the location of the end of the range
      * @exception BadLocationException if the range is invalid
+     *
+     * @deprecated replaced by
+     *     {@link #drawSelectedText(Graphics2D, float, float, int, int)}
      */
+    @Deprecated(since = "9")
     protected int drawSelectedText(Graphics g, int x,
-                                   int y, int p0, int p1) throws BadLocationException {
+                                   int y, int p0, int p1)
+                                   throws BadLocationException
+    {
+        return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+    }
+
+    float callDrawSelectedText(Graphics g, float x, float y,
+                               int p0, int p1)
+                               throws BadLocationException
+    {
+        return drawSelectedTextOverridden && g instanceof Graphics2D
+                ? drawSelectedText((Graphics2D) g, x, y, p0, p1)
+                : drawSelectedText(g, (int) x, (int) y, p0, p1);
+    }
+
+    private float drawSelectedTextImpl(Graphics g, float x, float y,
+                                       int p0, int p1,
+                                       boolean useFPAPI)
+            throws BadLocationException
+    {
         g.setColor(selected);
         Document doc = getDocument();
         Segment s = SegmentCache.getSharedSegment();
         doc.getText(p0, p1 - p0, s);
-        int ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0);
+        float ret = Utilities.drawTabbedText(this, s, x, y, g, this, p0, null,
+                                             useFPAPI);
         SegmentCache.releaseSharedSegment(s);
         return ret;
     }
@@ -242,10 +287,6 @@
      * the hosting component.  It assumes the highlighter will render
      * the selected background.
      *
-     * @implSpec This implementation calls
-     * {@link #drawSelectedText(Graphics, int, int, int, int)
-     * drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
-     *
      * @param g the graphics context
      * @param x the starting X coordinate {@code >= 0}
      * @param y the starting Y coordinate {@code >= 0}
@@ -253,11 +294,12 @@
      * @param p1 the ending position in the model {@code >= 0}
      * @return the location of the end of the range
      * @exception BadLocationException if the range is invalid
+     *
+     * @since 9
      */
-
     protected float drawSelectedText(Graphics2D g, float x,
                                      float y, int p0, int p1) throws BadLocationException {
-        return drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1);
+        return drawSelectedTextImpl(g, x, y, p0, p1, true);
     }
 
     /**
@@ -287,7 +329,13 @@
             // The font changed, we need to recalculate the
             // longest line.
             calculateLongestLine();
-            tabSize = getTabSize() * metrics.charWidth('m');
+            if (useFloatingPointAPI) {
+                FontRenderContext frc = metrics.getFontRenderContext();
+                float tabWidth = (float) font.getStringBounds("m", frc).getWidth();
+                tabSize = getTabSize() * tabWidth;
+            } else {
+                tabSize = getTabSize() * metrics.charWidth('m');
+            }
         }
     }
 
@@ -388,7 +436,11 @@
                                               originalA, host, this);
                 }
             }
-            drawLine(line, g, x, y);
+            if (drawLineOverridden && (g instanceof Graphics2D)) {
+                drawLine(line, (Graphics2D) g, (float) x, (float) y);
+            } else {
+                drawLine(line, g, x, y);
+            }
             y += fontHeight;
             if (line == 0) {
                 // This should never really happen, in so far as if
@@ -435,6 +487,13 @@
         int p0 = line.getStartOffset();
         Segment s = SegmentCache.getSharedSegment();
         doc.getText(p0, pos - p0, s);
+
+        if (useFloatingPointAPI) {
+            float xOffs = Utilities.getTabbedTextWidth(s, metrics, (float) tabBase, this, p0);
+            SegmentCache.releaseSharedSegment(s);
+            return new Rectangle2D.Float(lineArea.x + xOffs, lineArea.y, 1, metrics.getHeight());
+        }
+
         int xOffs = Utilities.getTabbedTextWidth(s, metrics, tabBase, this,p0);
         SegmentCache.releaseSharedSegment(s);
 
@@ -456,14 +515,13 @@
      *  given point in the view &gt;= 0
      * @see View#viewToModel
      */
-    public int viewToModel(float fx, float fy, Shape a, Position.Bias[] bias) {
+    public int viewToModel(float x, float y, Shape a, Position.Bias[] bias) {
         // PENDING(prinz) properly calculate bias
         bias[0] = Position.Bias.Forward;
 
         Rectangle alloc = a.getBounds();
         Document doc = getDocument();
-        int x = (int) fx;
-        int y = (int) fy;
+
         if (y < alloc.y) {
             // above the area covered by this icon, so the position
             // is assumed to be the start of the coverage for this view.
@@ -481,7 +539,7 @@
             Element map = doc.getDefaultRootElement();
             int fontHeight = metrics.getHeight();
             int lineIndex = (fontHeight > 0 ?
-                                Math.abs((y - alloc.y) / fontHeight) :
+                                (int)Math.abs((y - alloc.y) / fontHeight) :
                                 map.getElementCount() - 1);
             if (lineIndex >= map.getElementCount()) {
                 return getEndOffset() - 1;
@@ -507,7 +565,7 @@
                     doc.getText(p0, p1 - p0, s);
                     tabBase = alloc.x;
                     int offs = p0 + Utilities.getTabbedTextOffset(s, metrics,
-                                                                  tabBase, x, this, p0);
+                                                                  tabBase, x, this, p0, true);
                     SegmentCache.releaseSharedSegment(s);
                     return offs;
                 } catch (BadLocationException e) {
@@ -586,7 +644,7 @@
         if (tabSize == 0) {
             return x;
         }
-        int ntabs = (((int) x) - tabBase) / tabSize;
+        float ntabs = (x - tabBase) / tabSize;
         return tabBase + ((ntabs + 1) * tabSize);
     }
 
@@ -758,6 +816,28 @@
         return w;
     }
 
+    static boolean isFPMethodOverriden(String method,
+                                Class<?> cls,
+                                Class<?>[] intTypes,
+                                Class<?>[] fpTypes)
+    {
+        Module thisModule = PlainView.class.getModule();
+        while (!thisModule.equals(cls.getModule())) {
+            try {
+                cls.getDeclaredMethod(method, fpTypes);
+                return true;
+            } catch (Exception e1) {
+                try {
+                    cls.getDeclaredMethod(method, intTypes);
+                    return false;
+                } catch (Exception e2) {
+                    cls = cls.getSuperclass();
+                }
+            }
+        }
+        return true;
+    }
+
     // --- member variables -----------------------------------------------
 
     /**
@@ -780,7 +860,7 @@
     Font font;
 
     Segment lineBuffer;
-    int tabSize;
+    float tabSize;
     int tabBase;
 
     int sel0;
@@ -796,4 +876,46 @@
      */
     int firstLineOffset;
 
+    final boolean drawLineOverridden;
+    final boolean drawSelectedTextOverridden;
+    final boolean drawUnselectedTextOverridden;
+    final boolean useFloatingPointAPI;
+
+    {
+        final Class<?> CLS = getClass();
+        final Class<?> INT = Integer.TYPE;
+        final Class<?> FP = Float.TYPE;
+
+        drawLineOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {INT, Graphics.class, INT, INT};
+                Class<?>[] fpTypes = {INT, Graphics2D.class, FP, FP};
+                return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
+            }
+        });
+
+        drawUnselectedTextOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+                return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
+            }
+        });
+
+        drawSelectedTextOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+                return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
+            }
+        });
+
+        useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
+    }
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/Utilities.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/Utilities.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,24 +24,23 @@
  */
 package javax.swing.text;
 
-import java.lang.reflect.Method;
-
 import java.awt.Component;
 import java.awt.Rectangle;
 import java.awt.Graphics;
 import java.awt.FontMetrics;
 import java.awt.Shape;
-import java.awt.Toolkit;
 import java.awt.Graphics2D;
-import java.awt.font.FontRenderContext;
-import java.awt.font.TextLayout;
 import java.awt.font.TextAttribute;
+import java.awt.geom.Rectangle2D;
 
 import java.text.*;
 import javax.swing.JComponent;
 import javax.swing.SwingConstants;
 import javax.swing.text.ParagraphView.Row;
 import sun.swing.SwingUtilities2;
+import static sun.swing.SwingUtilities2.drawChars;
+import static sun.swing.SwingUtilities2.getFontCharWidth;
+import static sun.swing.SwingUtilities2.getFontCharsWidth;
 
 /**
  * A collection of methods to deal with various text
@@ -78,7 +77,11 @@
      *   tabs will be expanded as a space character.
      * @param startOffset starting offset of the text in the document &gt;= 0
      * @return  the X location at the end of the rendered text
+     *
+     * @deprecated replaced by
+     * {@link #drawTabbedText(Segment, float, float, Graphics2D, TabExpander, int)}
      */
+    @Deprecated(since = "9")
     public static final int drawTabbedText(Segment s, int x, int y, Graphics g,
                                            TabExpander e, int startOffset) {
         return drawTabbedText(null, s, x, y, g, e, startOffset);
@@ -96,6 +99,8 @@
      *           tabs will be expanded as a space character.
      * @param startOffset starting offset of the text in the document {@code >= 0}
      * @return  the X location at the end of the rendered text
+     *
+     * @since 9
      */
     public static final float drawTabbedText(Segment s, float x, float y,
                                              Graphics2D g,
@@ -138,9 +143,19 @@
                                 Segment s, int x, int y, Graphics g,
                                 TabExpander e, int startOffset,
                                 int [] justificationData) {
+        return (int) drawTabbedText(view, s, x, y, g, e, startOffset,
+                                    justificationData, false);
+    }
+
+    static final float drawTabbedText(View view,
+                                Segment s, float x, float y, Graphics g,
+                                TabExpander e, int startOffset,
+                                int [] justificationData,
+                                boolean useFPAPI)
+    {
         JComponent component = getJComponent(view);
         FontMetrics metrics = SwingUtilities2.getFontMetrics(component, g);
-        int nextX = x;
+        float nextX = x;
         char[] txt = s.array;
         int txtOffset = s.offset;
         int flushLen = 0;
@@ -174,19 +189,19 @@
                     && i <= endJustifiableContent
                     )) {
                 if (flushLen > 0) {
-                    nextX = SwingUtilities2.drawChars(component, g, txt,
-                                                flushIndex, flushLen, x, y);
+                    nextX = drawChars(component, g, txt, flushIndex, flushLen, x, y);
                     flushLen = 0;
                 }
                 flushIndex = i + 1;
                 if (txt[i] == '\t') {
                     if (e != null) {
-                        nextX = (int) e.nextTabStop((float) nextX, startOffset + i - txtOffset);
+                        nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
                     } else {
-                        nextX += metrics.charWidth(' ');
+                        nextX += getFontCharWidth(' ', metrics, useFPAPI);
                     }
                 } else if (txt[i] == ' ') {
-                    nextX += metrics.charWidth(' ') + spaceAddon;
+                    float spaceWidth = getFontCharWidth(' ', metrics, useFPAPI);
+                    nextX += spaceWidth + spaceAddon;
                     if (i <= spaceAddonLeftoverEnd) {
                         nextX++;
                     }
@@ -194,8 +209,8 @@
                 x = nextX;
             } else if ((txt[i] == '\n') || (txt[i] == '\r')) {
                 if (flushLen > 0) {
-                    nextX = SwingUtilities2.drawChars(component, g, txt,
-                                                flushIndex, flushLen, x, y);
+                    nextX = drawChars(component, g, txt, flushIndex, flushLen,
+                                      x, y, useFPAPI);
                     flushLen = 0;
                 }
                 flushIndex = i + 1;
@@ -205,8 +220,7 @@
             }
         }
         if (flushLen > 0) {
-            nextX = SwingUtilities2.drawChars(component, g,txt, flushIndex,
-                                              flushLen, x, y);
+            nextX = drawChars(component, g,txt, flushIndex, flushLen, x, y, useFPAPI);
         }
         return nextX;
     }
@@ -223,7 +237,11 @@
      *   tabs will be expanded as a space character.
      * @param startOffset starting offset of the text in the document &gt;= 0
      * @return  the width of the text
+     *
+     * @deprecated replaced by
+     *     {@link #getTabbedTextWidth(Segment, FontMetrics, float, TabExpander, int)}
      */
+    @Deprecated(since = "9")
     public static final int getTabbedTextWidth(Segment s, FontMetrics metrics, int x,
                                                TabExpander e, int startOffset) {
         return getTabbedTextWidth(null, s, metrics, x, e, startOffset, null);
@@ -240,11 +258,13 @@
      *   tabs will be expanded as a space character.
      * @param startOffset starting offset of the text in the document {@code >= 0}
      * @return  the width of the text
+     *
+     * @since 9
      */
     public static final float getTabbedTextWidth(Segment s, FontMetrics metrics,
                                                  float x, TabExpander e,
                                                  int startOffset) {
-        return getTabbedTextWidth(s, metrics, (int) x, e, startOffset);
+        return getTabbedTextWidth(null, s, metrics, x, e, startOffset, null);
     }
 
     // In addition to the previous method it can extend spaces for
@@ -254,10 +274,32 @@
     // one:
     // @param justificationData justificationData for the row.
     // if null not justification is needed
-    static final int getTabbedTextWidth(View view, Segment s, FontMetrics metrics, int x,
+    static final int getTabbedTextWidth(View view, Segment s,
+                                        FontMetrics metrics, int x,
+                                        TabExpander e, int startOffset,
+                                        int[] justificationData)
+    {
+        return (int) getTabbedTextWidth(view, s, metrics, x, e, startOffset,
+                                        justificationData, false);
+
+    }
+
+    static final float getTabbedTextWidth(View view, Segment s,
+                                        FontMetrics metrics, float x,
                                         TabExpander e, int startOffset,
-                                        int[] justificationData) {
-        int nextX = x;
+                                        int[] justificationData)
+    {
+        return  getTabbedTextWidth(view, s, metrics, x, e, startOffset,
+                                   justificationData, true);
+
+    }
+
+    static final float getTabbedTextWidth(View view, Segment s,
+                                        FontMetrics metrics, float x,
+                                        TabExpander e, int startOffset,
+                                        int[] justificationData,
+                                        boolean useFPAPI) {
+        float nextX = x;
         char[] txt = s.array;
         int txtOffset = s.offset;
         int n = s.offset + s.count;
@@ -294,13 +336,13 @@
                 charCount = 0;
                 if (txt[i] == '\t') {
                     if (e != null) {
-                        nextX = (int) e.nextTabStop((float) nextX,
-                                                    startOffset + i - txtOffset);
+                        nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
                     } else {
-                        nextX += metrics.charWidth(' ');
+                        nextX += getFontCharWidth(' ', metrics, useFPAPI);
                     }
                 } else if (txt[i] == ' ') {
-                    nextX += metrics.charWidth(' ') + spaceAddon;
+                    float spaceWidth = getFontCharWidth(' ', metrics, useFPAPI);
+                    nextX += spaceWidth + spaceAddon;
                     if (i <= spaceAddonLeftoverEnd) {
                         nextX++;
                     }
@@ -308,13 +350,15 @@
             } else if(txt[i] == '\n') {
             // Ignore newlines, they take up space and we shouldn't be
             // counting them.
-                nextX += metrics.charsWidth(txt, i - charCount, charCount);
+                nextX += getFontCharsWidth(txt, i - charCount, charCount,
+                                           metrics, useFPAPI);
                 charCount = 0;
             } else {
                 charCount++;
         }
         }
-        nextX += metrics.charsWidth(txt, n - charCount, charCount);
+        nextX += getFontCharsWidth(txt, n - charCount, charCount,
+                                   metrics, useFPAPI);
         return nextX - x;
     }
 
@@ -334,7 +378,12 @@
      *   tabs will be expanded as a space character.
      * @param startOffset starting offset of the text in the document &gt;= 0
      * @return  the offset into the text &gt;= 0
+     *
+     * @deprecated replaced by
+     *     {@link #getTabbedTextOffset(Segment, FontMetrics, float, float,
+     *                                 TabExpander, int, boolean)}
      */
+    @Deprecated(since = "9")
     public static final int getTabbedTextOffset(Segment s, FontMetrics metrics,
                                              int x0, int x, TabExpander e,
                                              int startOffset) {
@@ -346,7 +395,7 @@
                                          int startOffset,
                                          int[] justificationData) {
         return getTabbedTextOffset(view, s, metrics, x0, x, e, startOffset, true,
-                                   justificationData);
+                                   justificationData, false);
     }
 
     /**
@@ -365,13 +414,19 @@
      * @param startOffset starting offset of the text in the document &gt;= 0
      * @param round whether or not to round
      * @return  the offset into the text &gt;= 0
+     *
+     * @deprecated replaced by
+     *     {@link #getTabbedTextOffset(Segment, FontMetrics, float, float,
+     *                                 TabExpander, int, boolean)}
      */
+    @Deprecated(since = "9")
     public static final int getTabbedTextOffset(Segment s,
                                                 FontMetrics metrics,
                                                 int x0, int x, TabExpander e,
                                                 int startOffset,
                                                 boolean round) {
-        return getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset, round, null);
+        return getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset,
+                                   round, null, false);
     }
 
     /**
@@ -390,6 +445,8 @@
      * @param startOffset starting offset of the text in the document {@code >= 0}
      * @param round whether or not to round
      * @return  the offset into the text {@code >= 0}
+     *
+     * @since 9
      */
     public static final int getTabbedTextOffset(Segment s,
                                                 FontMetrics metrics,
@@ -398,8 +455,8 @@
                                                 int startOffset,
                                                 boolean round)
     {
-        return getTabbedTextOffset(null, s, metrics, (int) x0, (int) x, e,
-                                   startOffset, round, null);
+        return getTabbedTextOffset(null, s, metrics, x0, x, e,
+                                   startOffset, round, null, true);
     }
 
     // In addition to the previous method it can extend spaces for
@@ -412,15 +469,16 @@
     static final int getTabbedTextOffset(View view,
                                          Segment s,
                                          FontMetrics metrics,
-                                         int x0, int x, TabExpander e,
+                                         float x0, float x, TabExpander e,
                                          int startOffset,
                                          boolean round,
-                                         int[] justificationData) {
+                                         int[] justificationData,
+                                         boolean useFPAPI) {
         if (x0 >= x) {
             // x before x0, return.
             return 0;
         }
-        int nextX = x0;
+        float nextX = x0;
         // s may be a shared segment, so it is copied prior to calling
         // the tab expander
         char[] txt = s.array;
@@ -456,19 +514,19 @@
                     )){
                 if (txt[i] == '\t') {
                     if (e != null) {
-                        nextX = (int) e.nextTabStop((float) nextX,
-                                                    startOffset + i - txtOffset);
+                        nextX = e.nextTabStop(nextX, startOffset + i - txtOffset);
                     } else {
-                        nextX += metrics.charWidth(' ');
+                        nextX += getFontCharWidth(' ', metrics, useFPAPI);
                     }
                 } else if (txt[i] == ' ') {
-                    nextX += metrics.charWidth(' ') + spaceAddon;
+                    nextX += getFontCharWidth(' ', metrics, useFPAPI);
+                    nextX += spaceAddon;
                     if (i <= spaceAddonLeftoverEnd) {
                         nextX++;
                     }
                 }
             } else {
-                nextX += metrics.charWidth(txt[i]);
+                nextX += getFontCharWidth(txt[i], metrics, useFPAPI);
             }
             if (x < nextX) {
                 // found the hit position... return the appropriate side
@@ -480,12 +538,15 @@
                 if (round) {
                     offset = i + 1 - txtOffset;
 
-                    int width = metrics.charsWidth(txt, txtOffset, offset);
-                    int span = x - x0;
+                    float width = getFontCharsWidth(txt, txtOffset, offset,
+                                                    metrics, useFPAPI);
+                    float span = x - x0;
 
                     if (span < width) {
                         while (offset > 0) {
-                            int nextWidth = offset > 1 ? metrics.charsWidth(txt, txtOffset, offset - 1) : 0;
+                            float charsWidth = getFontCharsWidth(txt, txtOffset,
+                                    offset - 1, metrics, useFPAPI);
+                            float nextWidth = offset > 1 ? charsWidth : 0;
 
                             if (span >= nextWidth) {
                                 if (span - nextWidth < width - span) {
@@ -502,7 +563,9 @@
                 } else {
                     offset = i - txtOffset;
 
-                    while (offset > 0 && metrics.charsWidth(txt, txtOffset, offset) > (x - x0)) {
+                    while (offset > 0 && getFontCharsWidth(txt, txtOffset, offset,
+                                                           metrics, useFPAPI)
+                            > (x - x0)) {
                         offset--;
                     }
                 }
@@ -528,15 +591,26 @@
      *   tabs will be expanded as a space character.
      * @param startOffset starting offset in the document of the text
      * @return  the offset into the given text
+     *
+     * @deprecated replaced by
+     *     {@link #getBreakLocation(Segment, FontMetrics, float, float,
+     *                              TabExpander, int)}
      */
+    @Deprecated(since = "9")
     public static final int getBreakLocation(Segment s, FontMetrics metrics,
                                              int x0, int x, TabExpander e,
                                              int startOffset) {
+        return getBreakLocation(s, metrics, x0, x, e, startOffset, false);
+    }
+
+    static final int getBreakLocation(Segment s, FontMetrics metrics,
+                                      float x0, float x, TabExpander e,
+                                      int startOffset, boolean useFPIAPI) {
         char[] txt = s.array;
         int txtOffset = s.offset;
         int txtCount = s.count;
-        int index = Utilities.getTabbedTextOffset(s, metrics, x0, x,
-                                                  e, startOffset, false);
+        int index = getTabbedTextOffset(null, s, metrics, x0, x, e, startOffset,
+                                        false, null, useFPIAPI);
 
         if (index >= txtCount - 1) {
             return txtCount;
@@ -577,11 +651,13 @@
      *        tabs will be expanded as a space character.
      * @param startOffset starting offset in the document of the text
      * @return  the offset into the given text
+     *
+     * @since 9
      */
     public static final int getBreakLocation(Segment s, FontMetrics metrics,
                                              float x0, float x, TabExpander e,
                                              int startOffset) {
-        return getBreakLocation(s, metrics, (int) x0, (int) x, e, startOffset);
+        return getBreakLocation(s, metrics, x0, x, e, startOffset, false);
     }
 
     /**
@@ -627,16 +703,16 @@
      * @exception BadLocationException if the offset is out of range
      */
     public static final int getRowEnd(JTextComponent c, int offs) throws BadLocationException {
-        Rectangle r = c.modelToView(offs);
+        Rectangle2D r = c.modelToView2D(offs);
         if (r == null) {
             return -1;
         }
         int n = c.getDocument().getLength();
         int lastOffs = offs;
-        int y = r.y;
-        while ((r != null) && (y == r.y)) {
+        double y = r.getY();
+        while ((r != null) && (y == r.getY())) {
             // Skip invisible elements
-            if (r.height !=0) {
+            if (r.getHeight() !=0) {
                 offs = lastOffs;
             }
             lastOffs += 1;
@@ -657,27 +733,44 @@
      * @return the position &gt;= 0 if the request can be computed, otherwise
      *  a value of -1 will be returned.
      * @exception BadLocationException if the offset is out of range
+     *
+     * @deprecated replaced by
+     *     {@link #getPositionAbove(JTextComponent, int, float)}
      */
-    public static final int getPositionAbove(JTextComponent c, int offs, int x) throws BadLocationException {
+    @Deprecated(since = "9")
+    public static final int getPositionAbove(JTextComponent c, int offs, int x)
+            throws BadLocationException
+    {
+        return getPositionAbove(c, offs, x, false);
+    }
+
+    static final int getPositionAbove(JTextComponent c, int offs, float x,
+                                      boolean useFPAPI) throws BadLocationException
+    {
         int lastOffs = getRowStart(c, offs) - 1;
         if (lastOffs < 0) {
             return -1;
         }
-        int bestSpan = Integer.MAX_VALUE;
-        int y = 0;
-        Rectangle r = null;
+        double bestSpan = Integer.MAX_VALUE;
+        double y = 0;
+        Rectangle2D r = null;
         if (lastOffs >= 0) {
-            r = c.modelToView(lastOffs);
-            y = r.y;
+            r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+            y = r.getY();
         }
-        while ((r != null) && (y == r.y)) {
-            int span = Math.abs(r.x - x);
+        while ((r != null) && (y == r.getY())) {
+            double span = Math.abs(r.getX() - x);
             if (span < bestSpan) {
                 offs = lastOffs;
                 bestSpan = span;
             }
             lastOffs -= 1;
-            r = (lastOffs >= 0) ? c.modelToView(lastOffs) : null;
+
+            if ((lastOffs >= 0)) {
+                r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+            } else {
+                r = null;
+            }
         }
         return offs;
     }
@@ -694,10 +787,12 @@
      * @return the position {@code >= 0} if the request can be computed, otherwise
      *  a value of -1 will be returned.
      * @exception BadLocationException if the offset is out of range
+     *
+     * @since 9
      */
     public static final int getPositionAbove(JTextComponent c, int offs, float x)
             throws BadLocationException {
-        return getPositionAbove(c, offs, (int) x);
+        return getPositionAbove(c, offs, x, true);
     }
 
     /**
@@ -712,28 +807,45 @@
      * @return the position &gt;= 0 if the request can be computed, otherwise
      *  a value of -1 will be returned.
      * @exception BadLocationException if the offset is out of range
+     *
+     * @deprecated replaced by
+     *     {@link #getPositionBelow(JTextComponent, int, float)}
      */
-    public static final int getPositionBelow(JTextComponent c, int offs, int x) throws BadLocationException {
+    @Deprecated(since = "9")
+    public static final int getPositionBelow(JTextComponent c, int offs, int x)
+            throws BadLocationException
+    {
+        return getPositionBelow(c, offs, x, false);
+    }
+
+    static final int getPositionBelow(JTextComponent c, int offs, float x,
+                                      boolean useFPAPI) throws BadLocationException
+    {
         int lastOffs = getRowEnd(c, offs) + 1;
         if (lastOffs <= 0) {
             return -1;
         }
-        int bestSpan = Integer.MAX_VALUE;
+        double bestSpan = Integer.MAX_VALUE;
         int n = c.getDocument().getLength();
-        int y = 0;
-        Rectangle r = null;
+        double y = 0;
+        Rectangle2D r = null;
         if (lastOffs <= n) {
-            r = c.modelToView(lastOffs);
-            y = r.y;
+            r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+            y = r.getY();
         }
-        while ((r != null) && (y == r.y)) {
-            int span = Math.abs(x - r.x);
+        while ((r != null) && (y == r.getY())) {
+            double span = Math.abs(x - r.getX());
             if (span < bestSpan) {
                 offs = lastOffs;
                 bestSpan = span;
             }
             lastOffs += 1;
-            r = (lastOffs <= n) ? c.modelToView(lastOffs) : null;
+
+            if (lastOffs <= n) {
+                r = useFPAPI ? c.modelToView2D(lastOffs) : c.modelToView(lastOffs);
+            } else {
+                r = null;
+            }
         }
         return offs;
     }
@@ -750,10 +862,12 @@
      * @return the position {@code >= 0} if the request can be computed, otherwise
      *  a value of -1 will be returned.
      * @exception BadLocationException if the offset is out of range
+     *
+     * @since 9
      */
     public static final int getPositionBelow(JTextComponent c, int offs, float x)
             throws BadLocationException {
-        return getPositionBelow(c, offs, (int) x);
+        return getPositionBelow(c, offs, x, true);
     }
 
     /**
@@ -1029,7 +1143,23 @@
      */
     static int drawComposedText(View view, AttributeSet attr, Graphics g,
                                 int x, int y, int p0, int p1)
-                                     throws BadLocationException {
+            throws BadLocationException
+    {
+        return (int) drawComposedText(view, attr, g, x, y, p0, p1, false);
+    }
+
+    static float drawComposedText(View view, AttributeSet attr, Graphics g,
+                                  float x, float y, int p0, int p1)
+            throws BadLocationException
+    {
+        return drawComposedText(view, attr, g, x, y, p0, p1, true);
+    }
+
+    static float drawComposedText(View view, AttributeSet attr, Graphics g,
+                                  float x, float y, int p0, int p1,
+                                  boolean useFPAPI)
+            throws BadLocationException
+    {
         Graphics2D g2d = (Graphics2D)g;
         AttributedString as = (AttributedString)attr.getAttribute(
             StyleConstants.ComposedTextAttribute);
@@ -1039,8 +1169,7 @@
             return x;
 
         AttributedCharacterIterator aci = as.getIterator(null, p0, p1);
-        return x + (int)SwingUtilities2.drawString(
-                             getJComponent(view), g2d,aci,x,y);
+        return x + SwingUtilities2.drawString(getJComponent(view), g2d, aci, x, y);
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/WrappedPlainView.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,8 +25,12 @@
 package javax.swing.text;
 
 import java.awt.*;
+import java.awt.font.FontRenderContext;
 import java.lang.ref.SoftReference;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import javax.swing.event.*;
+import static javax.swing.text.PlainView.isFPMethodOverriden;
 
 /**
  * View of plain text (text with only one font and color)
@@ -87,17 +91,6 @@
     }
 
     /**
-     * Returns the tab size set for the document, defaulting to 8.
-     *
-     * @implSpec This implementation calls {@link #getTabSize() getTabSize()}.
-     *
-     * @return the tab size
-     */
-    protected float getFractionalTabSize() {
-        return getTabSize();
-    }
-
-    /**
      * Renders a line of text, suppressing whitespace at the end
      * and expanding any tabs.  This is implemented to make calls
      * to the methods <code>drawUnselectedText</code> and
@@ -111,8 +104,17 @@
      * @param y the starting Y position &gt;= 0
      * @see #drawUnselectedText
      * @see #drawSelectedText
+     *
+     * @deprecated replaced by
+     *     {@link #drawLine(int, int, Graphics2D, float, float)}
      */
+    @Deprecated(since = "9")
     protected void drawLine(int p0, int p1, Graphics g, int x, int y) {
+        drawLineImpl(p0, p1, g, x, y, false);
+    }
+
+    private void drawLineImpl(int p0, int p1, Graphics g, float x, float y,
+                              boolean useFPAPI) {
         Element lineMap = getElement();
         Element line = lineMap.getElement(lineMap.getElementIndex(p0));
         Element elem;
@@ -143,10 +145,6 @@
      * <code>drawSelectedText</code> so that the way selected and
      * unselected text are rendered can be customized.
      *
-     * @implSpec This implementation calls
-     * {@link #drawLine(int, int, Graphics, int, int)
-     * drawLine(p0, p1, (Graphics) g, (int) x, (int) y)}.
-     *
      * @param p0 the starting document location to use &gt;= 0
      * @param p1 the ending document location to use &gt;= p1
      * @param g the graphics context
@@ -154,12 +152,17 @@
      * @param y the starting Y position &gt;= 0
      * @see #drawUnselectedText
      * @see #drawSelectedText
+     *
+     * @since 9
      */
     protected void drawLine(int p0, int p1, Graphics2D g, float x, float y) {
-        drawLine(p0, p1, (Graphics) g, (int) x, (int) y);
+        drawLineImpl(p0, p1, g, x, y, true);
     }
 
-    private int drawText(Element elem, int p0, int p1, Graphics g, int x, int y) throws BadLocationException {
+    private float drawText(Element elem, int p0, int p1, Graphics g,
+                           float x, float y)
+            throws BadLocationException
+    {
         p1 = Math.min(getDocument().getLength(), p1);
         AttributeSet attr = elem.getAttributes();
 
@@ -171,23 +174,23 @@
         } else {
             if (sel0 == sel1 || selected == unselected) {
                 // no selection, or it is invisible
-                x = drawUnselectedText(g, x, y, p0, p1);
+                x = callDrawUnselectedText(g, x, y, p0, p1);
             } else if ((p0 >= sel0 && p0 <= sel1) && (p1 >= sel0 && p1 <= sel1)) {
-                x = drawSelectedText(g, x, y, p0, p1);
+                x = callDrawSelectedText(g, x, y, p0, p1);
             } else if (sel0 >= p0 && sel0 <= p1) {
                 if (sel1 >= p0 && sel1 <= p1) {
-                    x = drawUnselectedText(g, x, y, p0, sel0);
-                    x = drawSelectedText(g, x, y, sel0, sel1);
-                    x = drawUnselectedText(g, x, y, sel1, p1);
+                    x = callDrawUnselectedText(g, x, y, p0, sel0);
+                    x = callDrawSelectedText(g, x, y, sel0, sel1);
+                    x = callDrawUnselectedText(g, x, y, sel1, p1);
                 } else {
-                    x = drawUnselectedText(g, x, y, p0, sel0);
-                    x = drawSelectedText(g, x, y, sel0, p1);
+                    x = callDrawUnselectedText(g, x, y, p0, sel0);
+                    x = callDrawSelectedText(g, x, y, sel0, p1);
                 }
             } else if (sel1 >= p0 && sel1 <= p1) {
-                x = drawSelectedText(g, x, y, p0, sel1);
-                x = drawUnselectedText(g, x, y, sel1, p1);
+                x = callDrawSelectedText(g, x, y, p0, sel1);
+                x = callDrawUnselectedText(g, x, y, sel1, p1);
             } else {
-                x = drawUnselectedText(g, x, y, p0, p1);
+                x = callDrawUnselectedText(g, x, y, p0, p1);
             }
         }
 
@@ -205,14 +208,36 @@
      * @param p1 the ending position in the model &gt;= p0
      * @return the X location of the end of the range &gt;= 0
      * @exception BadLocationException if the range is invalid
+     *
+     * @deprecated replaced by
+     *     {@link #drawUnselectedText(Graphics2D, float, float, int, int)}
      */
+    @Deprecated(since = "9")
     protected int drawUnselectedText(Graphics g, int x, int y,
-                                     int p0, int p1) throws BadLocationException {
+                                     int p0, int p1) throws BadLocationException
+    {
+        return (int) drawUnselectedTextImpl(g, x, y, p0, p1, false);
+    }
+
+    private float callDrawUnselectedText(Graphics g, float x, float y,
+                                         int p0, int p1)
+                                         throws BadLocationException
+    {
+        return drawUnselectedTextOverridden && g instanceof Graphics2D
+                ? drawUnselectedText((Graphics2D) g, x, y, p0, p1)
+                : drawUnselectedText(g, (int) x, (int) y, p0, p1);
+    }
+
+    private float drawUnselectedTextImpl(Graphics g, float x, float y,
+                                         int p0, int p1, boolean useFPAPI)
+            throws BadLocationException
+    {
         g.setColor(unselected);
         Document doc = getDocument();
         Segment segment = SegmentCache.getSharedSegment();
         doc.getText(p0, p1 - p0, segment);
-        int ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0);
+        float ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0,
+                                             null, useFPAPI);
         SegmentCache.releaseSharedSegment(segment);
         return ret;
     }
@@ -221,10 +246,6 @@
      * Renders the given range in the model as normal unselected
      * text.
      *
-     * @implSpec This implementation calls
-     * {@link #drawUnselectedText(Graphics, int, int, int, int)
-     * drawUnselectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
-     *
      * @param g the graphics context
      * @param x the starting X coordinate &gt;= 0
      * @param y the starting Y coordinate &gt;= 0
@@ -232,10 +253,12 @@
      * @param p1 the ending position in the model &gt;= p0
      * @return the X location of the end of the range &gt;= 0
      * @exception BadLocationException if the range is invalid
+     *
+     * @since 9
      */
     protected float drawUnselectedText(Graphics2D g, float x, float y,
                                      int p0, int p1) throws BadLocationException {
-        return drawUnselectedText((Graphics) g, (int) x, (int) y, p0, p1);
+        return drawUnselectedTextImpl(g, x, y, p0, p1, true);
     }
     /**
      * Renders the given range in the model as selected text.  This
@@ -250,14 +273,37 @@
      * @param p1 the ending position in the model &gt;= p0
      * @return the location of the end of the range.
      * @exception BadLocationException if the range is invalid
+     *
+     * @deprecated replaced by
+     *     {@link #drawSelectedText(Graphics2D, float, float, int, int)}
      */
-    protected int drawSelectedText(Graphics g, int x,
-                                   int y, int p0, int p1) throws BadLocationException {
+    @Deprecated(since = "9")
+    protected int drawSelectedText(Graphics g, int x, int y, int p0, int p1)
+            throws BadLocationException
+    {
+        return (int) drawSelectedTextImpl(g, x, y, p0, p1, false);
+    }
+
+    private float callDrawSelectedText(Graphics g, float x, float y,
+                                       int p0, int p1)
+                                       throws BadLocationException
+    {
+        return drawSelectedTextOverridden && g instanceof Graphics2D
+                ? drawSelectedText((Graphics2D) g, x, y, p0, p1)
+                : drawSelectedText(g, (int) x, (int) y, p0, p1);
+    }
+
+    private float drawSelectedTextImpl(Graphics g, float x, float y,
+                                       int p0, int p1,
+                                       boolean useFPAPI)
+            throws BadLocationException
+    {
         g.setColor(selected);
         Document doc = getDocument();
         Segment segment = SegmentCache.getSharedSegment();
         doc.getText(p0, p1 - p0, segment);
-        int ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0);
+        float ret = Utilities.drawTabbedText(this, segment, x, y, g, this, p0,
+                                             null, useFPAPI);
         SegmentCache.releaseSharedSegment(segment);
         return ret;
     }
@@ -268,10 +314,6 @@
      * the hosting component.  It assumes the highlighter will render
      * the selected background.
      *
-     * @implSpec This implementation calls
-     * {@link #drawSelectedText(Graphics, int, int, int, int)
-     * drawSelectedText((Graphics)g, (int) x, (int) y, p0, p1)}.
-     *
      * @param g the graphics context
      * @param x the starting X coordinate &gt;= 0
      * @param y the starting Y coordinate &gt;= 0
@@ -279,10 +321,12 @@
      * @param p1 the ending position in the model &gt;= p0
      * @return the location of the end of the range.
      * @exception BadLocationException if the range is invalid
+     *
+     * @since 9
      */
     protected float drawSelectedText(Graphics2D g, float x, float y,
                                      int p0, int p1) throws BadLocationException {
-        return drawSelectedText((Graphics) g, (int) x, (int) y, p0, p1);
+        return drawSelectedTextImpl(g, x, y, p0, p1, true);
     }
     /**
      * Gives access to a buffer that can be used to fetch
@@ -395,7 +439,13 @@
         Component host = getContainer();
         Font f = host.getFont();
         metrics = host.getFontMetrics(f);
-        tabSize = getTabSize() * metrics.charWidth('m');
+        if (useFloatingPointAPI) {
+            FontRenderContext frc = metrics.getFontRenderContext();
+            float tabWidth = (float) f.getStringBounds("m", frc).getWidth();
+            tabSize = getTabSize() * tabWidth;
+        } else {
+            tabSize = getTabSize() * metrics.charWidth('m');
+        }
     }
 
     // --- TabExpander methods ------------------------------------------
@@ -413,7 +463,7 @@
     public float nextTabStop(float x, int tabOffset) {
         if (tabSize == 0)
             return x;
-        int ntabs = ((int) x - tabBase) / tabSize;
+        float ntabs = (x - tabBase) / tabSize;
         return tabBase + ((ntabs + 1) * tabSize);
     }
 
@@ -591,7 +641,7 @@
     Segment lineBuffer;
     boolean widthChanging;
     int tabBase;
-    int tabSize;
+    float tabSize;
     boolean wordWrap;
 
     int sel0;
@@ -668,6 +718,7 @@
             int end = getEndOffset();
             int p0 = start;
             int[] lineEnds = getLineEnds();
+            boolean useDrawLineFP = drawLineOverridden && g instanceof Graphics2D;
             for (int i = 0; i < lineCount; i++) {
                 int p1 = (lineEnds == null) ? end :
                                              start + lineEnds[i];
@@ -677,8 +728,11 @@
                                   : p1;
                     dh.paintLayeredHighlights(g, p0, hOffset, a, host, this);
                 }
-                drawLine(p0, p1, g, x, y);
-
+                if (useDrawLineFP) {
+                    drawLine(p0, p1, (Graphics2D) g, (float) x, (float) y);
+                } else {
+                    drawLine(p0, p1, g, x, y);
+                }
                 p0 = p1;
                 y += metrics.getHeight();
             }
@@ -929,4 +983,47 @@
         int lineCount;
         SoftReference<int[]> lineCache = null;
     }
+
+    private final boolean drawLineOverridden;
+    private final boolean drawSelectedTextOverridden;
+    private final boolean drawUnselectedTextOverridden;
+    private final boolean useFloatingPointAPI;
+
+    {
+        final Class<?> CLS = getClass();
+        final Class<?> INT = Integer.TYPE;
+        final Class<?> FP = Float.TYPE;
+
+        drawLineOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {INT, INT, Graphics.class, INT, INT};
+                Class<?>[] fpTypes = {INT, INT, Graphics2D.class, FP, FP};
+                return isFPMethodOverriden("drawLine", CLS, intTypes, fpTypes);
+            }
+        });
+
+        drawUnselectedTextOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+                return isFPMethodOverriden("drawUnselectedText", CLS, intTypes, fpTypes);
+            }
+        });
+
+        drawSelectedTextOverridden = AccessController
+                .doPrivileged(new PrivilegedAction<Boolean>() {
+            @Override
+            public Boolean run() {
+                Class<?>[] intTypes = {Graphics.class, INT, INT, INT, INT};
+                Class<?>[] fpTypes = {Graphics2D.class, FP, FP, INT, INT};
+                return isFPMethodOverriden("drawSelectedText", CLS, intTypes, fpTypes);
+            }
+        });
+
+        useFloatingPointAPI = drawUnselectedTextOverridden || drawSelectedTextOverridden;
+    }
 }
--- a/jdk/src/java.desktop/share/classes/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -88,6 +88,9 @@
     exports sun.awt to
         jdk.accessibility;
 
+    exports com.sun.awt to
+        jdk.desktop;
+
     uses java.awt.im.spi.InputMethodDescriptor;
     uses javax.accessibility.AccessibilityProvider;
     uses javax.imageio.spi.ImageInputStreamSpi;
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -107,7 +107,7 @@
         /*
          * Requests focus to the component.
          */
-        boolean requestFocus(Component comp, Cause cause);
+        void requestFocus(Component comp, Cause cause);
         /*
          * Determines if the component can gain focus.
          */
@@ -1392,4 +1392,4 @@
         AWTAccessor.dropTargetContextAccessor = accessor;
     }
 
-}
\ No newline at end of file
+}
--- a/jdk/src/java.desktop/share/classes/sun/awt/IconInfo.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/IconInfo.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -103,7 +103,7 @@
         }
         this.scaledWidth = width;
         this.scaledHeight = height;
-        this.rawLength = getScaledRawLength();
+        this.rawLength = getScaledRawLength(width, height);
     }
 
     /*
@@ -112,14 +112,14 @@
     public void setScaledSize(int width, int height) {
         this.scaledWidth = width;
         this.scaledHeight = height;
-        this.rawLength = getScaledRawLength();
+        this.rawLength = getScaledRawLength(width, height);
     }
 
     /*
     * returns scaled raw length.
      */
-    private int getScaledRawLength() {
-        int scaledWidthAndHeight[] = getScaledWidthAndHeight(width, height);
+    private int getScaledRawLength(int w, int h) {
+        int scaledWidthAndHeight[] = getScaledWidthAndHeight(w, h);
         return scaledWidthAndHeight[0] * scaledWidthAndHeight[1] + 2;
     }
 
--- a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -142,8 +142,8 @@
     }
 
     // WARNING: Don't call it on the Toolkit thread.
-    public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) {
-        return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
+    public static void requestFocusFor(Component target, FocusEvent.Cause cause) {
+        AWTAccessor.getComponentAccessor().requestFocus(target, cause);
     }
 
     // WARNING: Don't call it on the Toolkit thread.
--- a/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/SunToolkit.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1512,9 +1512,9 @@
      */
     protected abstract boolean syncNativeQueue(final long timeout);
 
-    private boolean eventDispatched = false;
-    private boolean queueEmpty = false;
-    private final Object waitLock = "Wait Lock";
+    private boolean eventDispatched;
+    private boolean queueEmpty;
+    private final Object waitLock = new Object();
 
     private boolean isEQEmpty() {
         EventQueue queue = getSystemEventQueueImpl();
@@ -1531,10 +1531,11 @@
     @SuppressWarnings("serial")
     protected final boolean waitForIdle(final long timeout) {
         flushPendingEvents();
-        boolean queueWasEmpty = isEQEmpty();
-        queueEmpty = false;
-        eventDispatched = false;
-        synchronized(waitLock) {
+        final boolean queueWasEmpty;
+        synchronized (waitLock) {
+            queueWasEmpty = isEQEmpty();
+            queueEmpty = false;
+            eventDispatched = false;
             postEvent(AppContext.getAppContext(),
                       new PeerEvent(getSystemEventQueueImpl(), null, PeerEvent.LOW_PRIORITY_EVENT) {
                           @Override
--- a/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/awt/shell/ShellFolder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -30,6 +30,9 @@
 import java.awt.Toolkit;
 import java.io.*;
 import java.io.FileNotFoundException;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
 import java.util.*;
 import java.util.concurrent.Callable;
 
@@ -243,7 +246,8 @@
         if (file instanceof ShellFolder) {
             return (ShellFolder)file;
         }
-        if (!file.exists()) {
+
+        if (!Files.exists(file.toPath(), LinkOption.NOFOLLOW_LINKS)) {
             throw new FileNotFoundException();
         }
         return shellFolderManager.createShellFolder(file);
--- a/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/font/NullFontScaler.java	Fri Nov 11 16:44:36 2016 +0100
@@ -36,8 +36,8 @@
         boolean supportsCJK, int filesize) {}
 
     StrikeMetrics getFontMetrics(long pScalerContext) {
-        return new StrikeMetrics(0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
-        0xf0,0xf0,0xf0,0xf0);
+        return new StrikeMetrics(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+                                 0.0f, 0.0f, 0.0f, 0.0f);
     }
 
     float getGlyphAdvance(long pScalerContext, int glyphCode) {
@@ -71,7 +71,7 @@
         return getNullScalerContext();
     }
 
-    void invalidateScalerContext(long ppScalerContext) {
+    void invalidateScalerContext(long pScalerContext) {
         //nothing to do
     }
 
--- a/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/SunGraphics2D.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1902,11 +1902,7 @@
             clipRegion = devClip;
         } else if (usrClip instanceof Rectangle2D) {
             clipState = CLIP_RECTANGULAR;
-            if (usrClip instanceof Rectangle) {
-                clipRegion = devClip.getIntersection((Rectangle)usrClip);
-            } else {
-                clipRegion = devClip.getIntersection(usrClip.getBounds());
-            }
+            clipRegion = devClip.getIntersection((Rectangle2D) usrClip);
         } else {
             PathIterator cpi = usrClip.getPathIterator(null);
             int box[] = new int[4];
--- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/Region.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,10 +28,13 @@
 import java.awt.Rectangle;
 import java.awt.Shape;
 import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
 import java.awt.geom.RectangularShape;
 
 import sun.java2d.loops.TransformHelper;
 
+import static java.lang.Double.isNaN;
+
 /**
  * This class encapsulates a definition of a two dimensional region which
  * consists of a number of Y ranges each containing multiple X bands.
@@ -118,6 +121,34 @@
     }
 
     /**
+     * Returns the closest {@code int} to the argument, with ties rounding to
+     * negative infinity.
+     * <p>
+     * Special cases:
+     * <ul><li>If the argument is NaN, the result is 0.
+     * <li>If the argument is negative infinity or any value less than or
+     * equal to the value of {@code Integer.MIN_VALUE}, the result is
+     * equal to the value of {@code Integer.MIN_VALUE}.
+     * <li>If the argument is positive infinity or any value greater than or
+     * equal to the value of {@code Integer.MAX_VALUE}, the result is
+     * equal to the value of {@code Integer.MAX_VALUE}.</ul>
+     *
+     * @param   coordinate a floating-point value to be rounded to an integer
+     * @return  the value of the argument rounded to the nearest
+     *          {@code int} value.
+     */
+    public static int clipRound(final double coordinate) {
+        final double newv = coordinate - 0.5;
+        if (newv < Integer.MIN_VALUE) {
+            return Integer.MIN_VALUE;
+        }
+        if (newv > Integer.MAX_VALUE) {
+            return Integer.MAX_VALUE;
+        }
+        return (int) Math.ceil(newv);
+    }
+
+    /**
      * Multiply the scale factor {@code sv} and the value {@code v} with
      * appropriate clipping to the bounds of Integer resolution. If the answer
      * would be greater than {@code Integer.MAX_VALUE} then {@code
@@ -559,6 +590,33 @@
 
     /**
      * Returns a Region object that represents the intersection of
+     * this object with the specified Rectangle2D. The return value
+     * may be this same object if no clipping occurs.
+     */
+    public Region getIntersection(final Rectangle2D r) {
+        if (r instanceof Rectangle) {
+            return getIntersection((Rectangle) r);
+        }
+        return getIntersectionXYXY(r.getMinX(), r.getMinY(), r.getMaxX(),
+                                   r.getMaxY());
+    }
+
+    /**
+     * Returns a Region object that represents the intersection of
+     * this object with the specified rectangular area. The return
+     * value may be this same object if no clipping occurs.
+     */
+    public Region getIntersectionXYXY(double lox, double loy, double hix,
+                                      double hiy) {
+        if (isNaN(lox) || isNaN(loy) || isNaN(hix) || isNaN(hiy)) {
+            return EMPTY_REGION;
+        }
+        return getIntersectionXYXY(clipRound(lox), clipRound(loy),
+                                   clipRound(hix), clipRound(hiy));
+    }
+
+    /**
+     * Returns a Region object that represents the intersection of
      * this object with the specified rectangular area.  The return
      * value may be this same object if no clipping occurs.
      */
--- a/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/swing/SwingUtilities2.java	Fri Nov 11 16:44:36 2016 +0100
@@ -30,6 +30,7 @@
 import static java.awt.RenderingHints.*;
 import java.awt.event.*;
 import java.awt.font.*;
+import java.awt.geom.Rectangle2D;
 import java.awt.geom.AffineTransform;
 import static java.awt.geom.AffineTransform.TYPE_FLIP;
 import static java.awt.geom.AffineTransform.TYPE_TRANSLATION;
@@ -723,10 +724,31 @@
                                  int length,
                                  int x,
                                  int y) {
+        return (int) drawChars(c, g, data, offset, length, x, y, false);
+    }
+
+    public static float drawChars(JComponent c, Graphics g,
+                                 char[] data,
+                                 int offset,
+                                 int length,
+                                 float x,
+                                 float y) {
+        return drawChars(c, g, data, offset, length, x, y, true);
+    }
+
+    public static float drawChars(JComponent c, Graphics g,
+                                 char[] data,
+                                 int offset,
+                                 int length,
+                                 float x,
+                                 float y,
+                                 boolean useFPAPI) {
         if ( length <= 0 ) { //no need to paint empty strings
             return x;
         }
-        int nextX = x + getFontMetrics(c, g).charsWidth(data, offset, length);
+        float nextX = x + getFontCharsWidth(data, offset, length,
+                                            getFontMetrics(c, g),
+                                            useFPAPI);
         if (isPrinting(g)) {
             Graphics2D g2d = getGraphics2D(g);
             if (g2d != null) {
@@ -766,8 +788,14 @@
         Object aaHint = (c == null)
                             ? null
                             : c.getClientProperty(KEY_TEXT_ANTIALIASING);
-        if (aaHint != null && (g instanceof Graphics2D)) {
-            Graphics2D g2 = (Graphics2D)g;
+
+        if (!(g instanceof Graphics2D)) {
+            g.drawChars(data, offset, length, (int) x, (int) y);
+            return nextX;
+        }
+
+        Graphics2D g2 = (Graphics2D) g;
+        if (aaHint != null) {
 
             Object oldContrast = null;
             Object oldAAValue = g2.getRenderingHint(KEY_TEXT_ANTIALIASING);
@@ -788,7 +816,7 @@
                 }
             }
 
-            g.drawChars(data, offset, length, x, y);
+            g2.drawString(new String(data, offset, length), x, y);
 
             if (oldAAValue != null) {
                 g2.setRenderingHint(KEY_TEXT_ANTIALIASING, oldAAValue);
@@ -798,19 +826,59 @@
             }
         }
         else {
-            g.drawChars(data, offset, length, x, y);
+            g2.drawString(new String(data, offset, length), x, y);
         }
         return nextX;
     }
 
+    public static float getFontCharWidth(char c, FontMetrics fm,
+                                         boolean useFPAPI)
+    {
+        return getFontCharsWidth(new char[]{c}, 0, 1, fm, useFPAPI);
+    }
+
+    public static float getFontCharsWidth(char[] data, int offset, int len,
+                                          FontMetrics fm,
+                                          boolean useFPAPI)
+    {
+        return len == 0 ? 0 : getFontStringWidth(new String(data, offset, len),
+                                                 fm, useFPAPI);
+    }
+
+    public static float getFontStringWidth(String data, FontMetrics fm,
+                                           boolean useFPAPI)
+    {
+        if (useFPAPI) {
+            Rectangle2D bounds = fm.getFont()
+                    .getStringBounds(data, fm.getFontRenderContext());
+            return (float) bounds.getWidth();
+        } else {
+            return fm.stringWidth(data);
+        }
+    }
+
     /*
      * see documentation for drawChars
      * returns the advance
      */
     public static float drawString(JComponent c, Graphics g,
                                    AttributedCharacterIterator iterator,
-                                   int x,
-                                   int y) {
+                                   int x, int y)
+    {
+        return drawStringImpl(c, g, iterator, x, y);
+    }
+
+    public static float drawString(JComponent c, Graphics g,
+                                   AttributedCharacterIterator iterator,
+                                   float x, float y)
+    {
+        return drawStringImpl(c, g, iterator, x, y);
+    }
+
+    private static float drawStringImpl(JComponent c, Graphics g,
+                                   AttributedCharacterIterator iterator,
+                                   float x, float y)
+    {
 
         float retVal;
         boolean isPrinting = isPrinting(g);
@@ -825,8 +893,8 @@
 
         Graphics2D g2d = getGraphics2D(g);
         if (g2d == null) {
-            g.drawString(iterator,x,y); //for the cases where advance
-                                        //matters it should not happen
+            g.drawString(iterator, (int)x, (int)y); //for the cases where advance
+                                                    //matters it should not happen
             retVal = x;
 
         } else {
--- a/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/classes/sun/swing/plaf/GTKKeybindings.java	Fri Nov 11 16:44:36 2016 +0100
@@ -219,6 +219,38 @@
                         "KP_UP", "selectPrevious"
 
                 }),
+                "Desktop.ancestorInputMap",
+                new UIDefaults.LazyInputMap(new Object[] {
+                        "ctrl F5", "restore",
+                        "ctrl F4", "close",
+                        "ctrl F7", "move",
+                        "ctrl F8", "resize",
+                        "RIGHT", "right",
+                        "KP_RIGHT", "right",
+                        "shift RIGHT", "shrinkRight",
+                        "shift KP_RIGHT", "shrinkRight",
+                        "LEFT", "left",
+                        "KP_LEFT", "left",
+                        "shift LEFT", "shrinkLeft",
+                        "shift KP_LEFT", "shrinkLeft",
+                        "UP", "up",
+                        "KP_UP", "up",
+                        "shift UP", "shrinkUp",
+                        "shift KP_UP", "shrinkUp",
+                        "DOWN", "down",
+                        "KP_DOWN", "down",
+                        "shift DOWN", "shrinkDown",
+                        "shift KP_DOWN", "shrinkDown",
+                        "ESCAPE", "escape",
+                        "ctrl F9", "minimize",
+                        "ctrl F10", "maximize",
+                        "ctrl F6", "selectNextFrame",
+                        "ctrl TAB", "selectNextFrame",
+                        "ctrl alt F6", "selectNextFrame",
+                        "shift ctrl alt F6", "selectPreviousFrame",
+                        "ctrl F12", "navigateNext",
+                        "shift ctrl F12", "navigatePrevious"
+                }),
                 "EditorPane.focusInputMap", multilineInputMap,
                 "FileChooser.ancestorInputMap",
                 new UIDefaults.LazyInputMap(new Object[]{
--- a/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.c	Fri Nov 11 16:44:36 2016 +0100
@@ -25,7 +25,12 @@
 
 #include "splashscreen_impl.h"
 #include "splashscreen_gfx_impl.h"
-
+#define BUFF_SIZE 1024
+#ifdef _MSC_VER
+# ifndef snprintf
+#       define snprintf _snprintf
+# endif
+#endif
 int splashIsVisible = 0;
 
 Splash *
@@ -392,5 +397,101 @@
 
 SPLASHEXPORT int
 SplashGetScaledImgNameMaxPstfixLen(const char *fileName){
-    return strlen(fileName) + strlen(".java-scale-200") + 1;
+    return strlen(fileName) + strlen("@100pct") + 1;
 }
+
+jboolean GetScaledImageName(const char *fileName, char *scaleImageName,
+        float *scaleFactor, const size_t scaledImageLength) {
+    if (*scaleFactor > 1.0) {
+        FILE *fp = NULL;
+        char scaledImgPct[BUFF_SIZE];
+        char scaledImgX[BUFF_SIZE];
+        char *scaledImageXName = NULL;
+        char *scaledImagePctName = malloc(scaledImageLength);
+        char *dupFileName = strdup(fileName);
+        char *fileExtension = strrchr(dupFileName, '.');
+        size_t lengthPct = 0;
+        size_t lengthX = 0;
+        int retValPct = 0;
+        int retValX = 0;
+        jboolean isPctScaledImage = (*scaleFactor * 100) != ((int) (*scaleFactor)) *100;
+        snprintf(scaledImgPct, BUFF_SIZE, "%s%d%s", "@",
+                (int) (*scaleFactor * 100), "pct");
+        if (!isPctScaledImage) {
+            scaledImageXName = malloc(scaledImageLength);
+            snprintf(scaledImgX, BUFF_SIZE, "%s%d%s", "@", (int) (*scaleFactor), "x");
+        }
+        /*File is missing extension */
+        if (fileExtension == NULL) {
+            lengthPct = strlen(dupFileName) +
+                    strlen(scaledImgPct) + 1;
+            if (!isPctScaledImage) {
+                lengthX = strlen(dupFileName) +
+                        strlen(scaledImgX) + 1;
+            }
+            if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
+                cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+                return JNI_FALSE;
+            }
+            retValPct = snprintf(scaledImagePctName, lengthPct, "%s%s", dupFileName,
+                    scaledImgPct);
+            if (!isPctScaledImage) {
+                retValX = snprintf(scaledImageXName, lengthX, "%s%s", dupFileName,
+                        scaledImgX);
+            }
+            if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
+                    (retValX < 0 || (retValX > lengthX - 1))) {
+                cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+                return JNI_FALSE;
+            }
+        } else {
+            int length_Without_Ext = fileExtension - dupFileName;
+            lengthPct = length_Without_Ext + strlen(scaledImgPct) +
+                    strlen(fileExtension) + 1;
+            if (!isPctScaledImage) {
+                lengthX = length_Without_Ext + strlen(scaledImgX) +
+                        strlen(fileExtension) + 1;
+            }
+            if (lengthPct > scaledImageLength || lengthX > scaledImageLength) {
+                cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+                return JNI_FALSE;
+            }
+            retValPct = snprintf(scaledImagePctName, lengthPct, "%.*s%s%s",
+                    length_Without_Ext, dupFileName, scaledImgPct, fileExtension);
+            if (!isPctScaledImage) {
+                retValX = snprintf(scaledImageXName, lengthX, "%.*s%s%s",
+                        length_Without_Ext, dupFileName, scaledImgX, fileExtension);
+            }
+            if ((retValPct < 0 || (retValPct > lengthPct - 1)) ||
+                    (retValX < 0 || (retValX > lengthX - 1))) {
+                cleanUp(dupFileName, scaledImageXName, scaledImagePctName, scaleFactor);
+                return JNI_FALSE;
+            }
+        }
+        free(dupFileName);
+        if (!(fp = fopen(scaledImagePctName, "r"))) {
+            if (!isPctScaledImage && (fp = fopen(scaledImageXName, "r"))) {
+                fclose(fp);
+                strcpy(scaleImageName, scaledImageXName);
+                free(scaledImageXName);
+                free(scaledImagePctName);
+                return JNI_TRUE;
+            }
+            cleanUp(NULL, scaledImageXName, scaledImagePctName, scaleFactor);
+            return JNI_FALSE;
+        }
+        fclose(fp);
+        strcpy(scaleImageName, scaledImagePctName);
+        free(scaledImageXName);
+        free(scaledImagePctName);
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor) {
+    *scaleFactor = 1;
+    free(fName);
+    free(xName);
+    free(pctName);
+}
--- a/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h	Fri Nov 11 16:44:36 2016 +0100
@@ -150,7 +150,9 @@
 void SplashCleanup(Splash * splash);
 void SplashSetScaleFactor(float scaleFactor);
 int  SplashGetScaledImgNameMaxPstfixLen(const char *fileName);
-
+void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor);
+jboolean GetScaledImageName(const char *fileName, char *scaledImgName,
+                  float *scaleFactor, const size_t scaledImageLength);
 typedef struct SplashStream {
     int (*read)(void* pStream, void* pData, int nBytes);
     int (*peek)(void* pStream);
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -301,7 +301,10 @@
     }
 
     private void resetWMSetInsets() {
-        wm_set_insets = null;
+        if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
+            currentInsets = new Insets(0, 0, 0, 0);
+            wm_set_insets = null;
+        }
     }
 
     public void handlePropertyNotify(XEvent xev) {
@@ -352,7 +355,7 @@
                         // and the initially guessed insets were wrong
                         handleCorrectInsets(in);
                     }
-                } else if (!dimensions.isClientSizeSet()) {
+                } else if (!insets_corrected || !dimensions.isClientSizeSet()) {
                     insets_corrected = true;
                     // initial insets were guessed correctly. Re-request
                     // frame bounds because they may be changed by WM if the
@@ -908,7 +911,6 @@
     public void setResizable(boolean resizable) {
         int fs = winAttr.functions;
         if (!isResizable() && resizable) {
-            currentInsets = new Insets(0, 0, 0, 0);
             resetWMSetInsets();
             if (!isEmbedded()) {
                 setReparented(false);
@@ -922,7 +924,6 @@
             winAttr.functions = fs;
             XWM.setShellResizable(this);
         } else if (isResizable() && !resizable) {
-            currentInsets = new Insets(0, 0, 0, 0);
             resetWMSetInsets();
             if (!isEmbedded()) {
                 setReparented(false);
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/Xrandr.h	Fri Nov 11 16:44:36 2016 +0100
@@ -118,6 +118,19 @@
     RRMode          *modes;
 } XRROutputInfo;
 
+typedef struct {
+    Time            timestamp;
+    int             x, y;
+    unsigned int    width, height;
+    RRMode          mode;
+    Rotation        rotation;
+    int             noutput;
+    RROutput        *outputs;
+    Rotation        rotations;
+    int             npossible;
+    RROutput        *possible;
+} XRRCrtcInfo;
+
 XRRScreenResources *XRRGetScreenResources (Display *dpy, Window window);
 
 void XRRFreeScreenResources (XRRScreenResources *resources);
@@ -126,6 +139,11 @@
                                                                RROutput output);
 void XRRFreeOutputInfo (XRROutputInfo *outputInfo);
 
+XRRCrtcInfo *XRRGetCrtcInfo (Display *dpy, XRRScreenResources *resources,
+                                                                   RRCrtc crtc);
+void XRRFreeCrtcInfo (XRRCrtcInfo *crtcInfo);
+
+
 /* internal representation is private to the library */
 typedef struct _XRRScreenConfiguration XRRScreenConfiguration;
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c	Fri Nov 11 16:44:36 2016 +0100
@@ -1667,6 +1667,11 @@
 
 typedef void (*XRRFreeOutputInfoType)(XRROutputInfo *outputInfo);
 
+typedef XRRCrtcInfo* (*XRRGetCrtcInfoType)(Display *dpy,
+                                    XRRScreenResources *resources, RRCrtc crtc);
+
+typedef void (*XRRFreeCrtcInfoType)(XRRCrtcInfo *crtcInfo);
+
 static XRRQueryVersionType               awt_XRRQueryVersion;
 static XRRGetScreenInfoType              awt_XRRGetScreenInfo;
 static XRRFreeScreenConfigInfoType       awt_XRRFreeScreenConfigInfo;
@@ -1680,6 +1685,8 @@
 static XRRFreeScreenResourcesType        awt_XRRFreeScreenResources;
 static XRRGetOutputInfoType              awt_XRRGetOutputInfo;
 static XRRFreeOutputInfoType             awt_XRRFreeOutputInfo;
+static XRRGetCrtcInfoType                awt_XRRGetCrtcInfo;
+static XRRFreeCrtcInfoType               awt_XRRFreeCrtcInfo;
 
 #define LOAD_XRANDR_FUNC(f) \
     do { \
@@ -1755,6 +1762,8 @@
     LOAD_XRANDR_FUNC(XRRFreeScreenResources);
     LOAD_XRANDR_FUNC(XRRGetOutputInfo);
     LOAD_XRANDR_FUNC(XRRFreeOutputInfo);
+    LOAD_XRANDR_FUNC(XRRGetCrtcInfo);
+    LOAD_XRANDR_FUNC(XRRFreeCrtcInfo);
 
     return JNI_TRUE;
 }
@@ -1895,7 +1904,49 @@
 
     AWT_LOCK();
 
-    if (screen < ScreenCount(awt_display)) {
+    if (usingXinerama && XScreenCount(awt_display) > 0) {
+        XRRScreenResources *res = awt_XRRGetScreenResources(awt_display,
+                                                    RootWindow(awt_display, 0));
+        if (res) {
+            if (res->noutput > screen) {
+                XRROutputInfo *output_info = awt_XRRGetOutputInfo(awt_display,
+                                                     res, res->outputs[screen]);
+                if (output_info) {
+                    if (output_info->crtc) {
+                        XRRCrtcInfo *crtc_info =
+                                    awt_XRRGetCrtcInfo (awt_display, res,
+                                                        output_info->crtc);
+                        if (crtc_info) {
+                            if (crtc_info->mode) {
+                                int i;
+                                for (i = 0; i < res->nmode; i++) {
+                                    XRRModeInfo *mode = &res->modes[i];
+                                    if (mode->id == crtc_info->mode) {
+                                        float rate = 0;
+                                        if (mode->hTotal && mode->vTotal) {
+                                             rate = ((float)mode->dotClock /
+                                                    ((float)mode->hTotal *
+                                                    (float)mode->vTotal));
+                                        }
+                                        displayMode = X11GD_CreateDisplayMode(
+                                                           env,
+                                                           mode->width,
+                                                           mode->height,
+                                                           BIT_DEPTH_MULTI,
+                                                           (int)(rate +.2));
+                                        break;
+                                    }
+                                }
+                            }
+                            awt_XRRFreeCrtcInfo(crtc_info);
+                        }
+                    }
+                    awt_XRRFreeOutputInfo(output_info);
+                }
+            }
+            awt_XRRFreeScreenResources(res);
+        }
+    } else {
 
         config = awt_XRRGetScreenInfo(awt_display,
                                       RootWindow(awt_display, screen));
@@ -1954,7 +2005,7 @@
                                                      res, res->outputs[screen]);
                 if (output_info) {
                     int i;
-                    for (i = 0; i < res->nmode; i++) {
+                    for (i = 0; i < output_info->nmode; i++) {
                         RRMode m = output_info->modes[i];
                         int j;
                         XRRModeInfo *mode;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c	Fri Nov 11 16:44:36 2016 +0100
@@ -35,9 +35,6 @@
 #include <jni_util.h>
 #include "awt.h"
 
-#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
-#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
-
 #define GTK_TYPE_BORDER                 ((*fp_gtk_border_get_type)())
 
 #define G_TYPE_FUNDAMENTAL_SHIFT        (2)
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h	Fri Nov 11 16:44:36 2016 +0100
@@ -351,9 +351,6 @@
   guint ellipsize : 3;
 };
 
-
-typedef struct _GThreadFunctions GThreadFunctions;
-
 /**
  * Returns :
  * NULL if the GLib library is compatible with the given version, or a string
@@ -449,17 +446,6 @@
 static void (*fp_g_list_free) (GList *list);
 static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
 
-/**
- * This function is available for GLIB > 2.20, so it MUST be
- * called within GLIB_CHECK_VERSION(2, 20, 0) check.
- */
-static gboolean (*fp_g_thread_get_initialized)(void);
-
-static void (*fp_g_thread_init)(GThreadFunctions *vtable);
-static void (*fp_gdk_threads_init)(void);
-static void (*fp_gdk_threads_enter)(void);
-static void (*fp_gdk_threads_leave)(void);
-
 static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
     guint32 timestamp, GError **error);
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Fri Nov 11 16:44:36 2016 +0100
@@ -35,6 +35,7 @@
 #include "awt.h"
 
 static void *gtk3_libhandle = NULL;
+static void *gthread_libhandle = NULL;
 
 static jmp_buf j;
 
@@ -87,6 +88,15 @@
     return result;
 }
 
+static void* dl_symbol_gthread(const char* name)
+{
+    void* result = dlsym(gthread_libhandle, name);
+    if (!result)
+        longjmp(j, NO_SYMBOL_EXCEPTION);
+
+    return result;
+}
+
 gboolean gtk3_check(const char* lib_name, gboolean load)
 {
     if (gtk3_libhandle != NULL) {
@@ -261,6 +271,13 @@
         return FALSE;
     }
 
+    gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+    if (gthread_libhandle == NULL) {
+        gthread_libhandle = dlopen(GTHREAD_LIB, RTLD_LAZY | RTLD_LOCAL);
+        if (gthread_libhandle == NULL)
+            return FALSE;
+    }
+
     if (setjmp(j) == 0)
     {
         fp_gtk_check_version = dl_symbol("gtk_check_version");
@@ -530,8 +547,8 @@
 
         fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");
 
-        fp_gdk_threads_enter = &empty;
-        fp_gdk_threads_leave = &empty;
+        fp_gdk_threads_enter = dl_symbol("gdk_threads_enter");
+        fp_gdk_threads_leave = dl_symbol("gdk_threads_leave");
 
         /**
          * Functions for sun_awt_X11_GtkFileDialogPeer.c
@@ -556,6 +573,9 @@
         dlclose(gtk3_libhandle);
         gtk3_libhandle = NULL;
 
+        dlclose(gthread_libhandle);
+        gthread_libhandle = NULL;
+
         return NULL;
     }
 
@@ -651,6 +671,7 @@
 
     dlerror();
     dlclose(gtk3_libhandle);
+    dlclose(gthread_libhandle);
     if ((gtk3_error = dlerror()) != NULL)
     {
         return FALSE;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h	Fri Nov 11 16:44:36 2016 +0100
@@ -33,6 +33,9 @@
 #define TRUE            (!FALSE)
 #endif
 
+#define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
+#define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
+
 #define _G_TYPE_CIC(ip, gt, ct)       ((ct*) ip)
 #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type)  \
                                     (_G_TYPE_CIC ((instance), (g_type), c_type))
@@ -555,6 +558,13 @@
 gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose);
 gboolean gtk_check_version(GtkVersion version);
 
+typedef struct _GThreadFunctions GThreadFunctions;
+static gboolean (*fp_g_thread_get_initialized)(void);
+static void (*fp_g_thread_init)(GThreadFunctions *vtable);
+static void (*fp_gdk_threads_init)(void);
+static void (*fp_gdk_threads_enter)(void);
+static void (*fp_gdk_threads_leave)(void);
+
 extern GtkApi* gtk;
 
 #endif /* !_GTK_INTERFACE_H */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XWindow.c	Fri Nov 11 16:44:36 2016 +0100
@@ -818,6 +818,32 @@
     }
     return awt_UseXKB;
 }
+
+/*
+ * Map a keycode to the corresponding keysym.
+ * This replaces the deprecated X11 function XKeycodeToKeysym
+ */
+KeySym
+keycodeToKeysym(Display *display, KeyCode keycode, int index) {
+    static int min_kc = -1;
+    static int max_kc;
+    if (min_kc == -1) {
+        (void) XDisplayKeycodes(display, &min_kc, &max_kc);
+    }
+    if (keycode < min_kc || keycode > max_kc || index < 0) {
+        return NoSymbol;
+    }
+    int num_syms;
+    KeySym *key_syms = XGetKeyboardMapping(display, keycode, 1, &num_syms);
+    if (index >= num_syms) {
+        XFree(key_syms);
+        return NoSymbol;
+    }
+    KeySym ks = key_syms[index];
+    XFree(key_syms);
+    return ks;
+}
+
 static Boolean
 isKPevent(XEvent *event)
 {
@@ -833,14 +859,14 @@
      */
     Boolean bsun = isXsunServer( event );
     Boolean bxkb = isXKBenabled( event->xkey.display );
-    return IsKeypadKey( XKeycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) );
+    return IsKeypadKey( keycodeToKeysym(event->xkey.display, event->xkey.keycode,(bsun && !bxkb ? 2 : 1) ) );
 }
 static void
 dumpKeysymArray(XEvent *event) {
-    printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 0));
-    printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 1));
-    printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 2));
-    printf("    0x%X\n",XKeycodeToKeysym(event->xkey.display, event->xkey.keycode, 3));
+    printf("    0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 0));
+    printf("    0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 1));
+    printf("    0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 2));
+    printf("    0x%X\n",keycodeToKeysym(event->xkey.display, event->xkey.keycode, 3));
 }
 /*
  * In a next redesign, get rid of this code altogether.
@@ -855,20 +881,20 @@
     }
     if( isXsunServer( event ) && !awt_UseXKB) {
         if( (event->xkey.state & ShiftMask) ) { // shift modifier is on
-            *keysym = XKeycodeToKeysym(event->xkey.display,
+            *keysym = keycodeToKeysym(event->xkey.display,
                                    event->xkey.keycode, 3);
          }else {
-            *keysym = XKeycodeToKeysym(event->xkey.display,
+            *keysym = keycodeToKeysym(event->xkey.display,
                                    event->xkey.keycode, 2);
          }
     } else {
         if( (event->xkey.state & ShiftMask) || // shift modifier is on
             ((event->xkey.state & LockMask) && // lock modifier is on
              (awt_ModLockIsShiftLock)) ) {     // it is interpreted as ShiftLock
-            *keysym = XKeycodeToKeysym(event->xkey.display,
+            *keysym = keycodeToKeysym(event->xkey.display,
                                    event->xkey.keycode, 0);
         }else{
-            *keysym = XKeycodeToKeysym(event->xkey.display,
+            *keysym = keycodeToKeysym(event->xkey.display,
                                    event->xkey.keycode, 1);
         }
     }
@@ -903,7 +929,7 @@
        Perhaps using the index (modn in awt_MToolkit.c:setup_modifier_map)
        would be more correct.
      */
-    *keysym = XKeycodeToKeysym(event->xkey.display,
+    *keysym = keycodeToKeysym(event->xkey.display,
                                event->xkey.keycode, 2);
     if (originalKeysym != *keysym) {
         DTRACE_PRINTLN3("%s originalKeysym=0x%x, keysym=0x%x",
@@ -999,7 +1025,6 @@
     }
 }
 
-
 /* This function is called as the keyChar parameter of a call to
  * awt_post_java_key_event.  It depends on being called after adjustKeySym.
  *
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c	Fri Nov 11 16:44:36 2016 +0100
@@ -49,6 +49,9 @@
 
 #include <X11/XKBlib.h>
 
+// From XWindow.c
+extern KeySym keycodeToKeysym(Display *display, KeyCode keycode, int index);
+
 #if defined(DEBUG)
 static jmethodID lockIsHeldMID = NULL;
 
@@ -1286,7 +1289,7 @@
         // report arbitrarily false.
         return JNI_FALSE;
     } else {
-        long ks2 = XKeycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2);
+        long ks2 = keycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2);
         if( ks2 == XK_KP_7 ) {
             //XXX If some Xorg server would put XK_KP_7 in keysymarray[2] as well,
             //XXX for yet unknown to me reason, the sniffer would lie.
@@ -1915,12 +1918,13 @@
     XQueryKeymap( (Display *) jlong_to_ptr(display), (char *) jlong_to_ptr(vector));
 }
 
+// XKeycodeToKeysym is deprecated but for compatibility we keep the API.
 JNIEXPORT jlong JNICALL
 Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz,
                                               jlong display, jint keycode,
                                               jint index) {
     AWT_CHECK_HAVE_LOCK_RETURN(0);
-    return XKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (int)index);
+    return keycodeToKeysym((Display*)jlong_to_ptr(display), (unsigned int)keycode, (int)index);
 }
 
 JNIEXPORT jint JNICALL
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c	Fri Nov 11 16:44:36 2016 +0100
@@ -97,10 +97,7 @@
 
 void callback(DbusmenuMenuitem* mi, guint ts, jobject data) {
     JNIEnv* env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2);
-    (*env)->CallStaticVoidMethod(env, jTaskbarCls, jTaskbarCallback, data,
-            fp_dbusmenu_menuitem_property_get_int(mi, "toggle-state")
-            ? JNI_FALSE
-            : JNI_TRUE);
+    (*env)->CallStaticVoidMethod(env, jTaskbarCls, jTaskbarCallback, data);
 }
 
 /*
@@ -243,10 +240,9 @@
 
     if (!menu) {
         menu = fp_dbusmenu_menuitem_new();
+        fp_unity_launcher_entry_set_quicklist(entry, menu);
     }
 
-    fp_unity_launcher_entry_set_quicklist(entry, menu);
-
     GList* list = fp_dbusmenu_menuitem_take_children(menu);
     gtk->g_list_free_full(list, gtk->g_object_unref);
 
--- a/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/unix/native/libsplashscreen/splashscreen_sys.c	Fri Nov 11 16:44:36 2016 +0100
@@ -753,6 +753,9 @@
         XMapRaised(splash->display, splash->window);
         SplashUpdateShape(splash);
         SplashRedrawWindow(splash);
+        //map the splash co-ordinates as per system scale
+        splash->x /= splash->scaleFactor;
+        splash->y /= splash->scaleFactor;
         SplashEventLoop(splash);
     }
     SplashUnlock(splash);
@@ -807,50 +810,6 @@
     return JNI_FALSE;
 #endif
     *scaleFactor = getNativeScaleFactor(NULL);
-    if (*scaleFactor == 2.0) {
-        size_t length = 0;
-        char *stringToAppend = ".java-scale2x";
-        char *dupFileName = strdup(fileName);
-        char *fileExtension = strrchr(dupFileName, '.');
-        if (fileExtension == NULL) {
-            length = strlen(dupFileName) + strlen(stringToAppend) + 1;
-            if (length > scaledImageNameLength) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-            int retVal = snprintf(scaledImgName, length, "%s%s",
-                dupFileName, stringToAppend);
-            if (retVal < 0 || (retVal != length - 1)) {
-                free(dupFileName);
-                *scaleFactor = 1;
-                return JNI_FALSE;
-            }
-        } else {
-            int length_without_ext = fileExtension - dupFileName;
-            length = length_without_ext +
-                strlen(stringToAppend) + strlen(fileExtension) + 1;
-            if (length > scaledImageNameLength) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-            int retVal = snprintf(scaledImgName, length, "%.*s%s%s",
-                length_without_ext, dupFileName, stringToAppend, fileExtension);
-            if (retVal < 0 || retVal != length - 1) {
-                free(dupFileName);
-                *scaleFactor = 1;
-                return JNI_FALSE;
-            }
-        }
-        free(dupFileName);
-        FILE *fp;
-        if (!(fp = fopen(scaledImgName, "r"))) {
-            *scaleFactor = 1;
-            return JNI_FALSE;
-        }
-        fclose(fp);
-        return JNI_TRUE;
-    }
-    return JNI_FALSE;
+    return GetScaledImageName(fileName, scaledImgName, scaleFactor, scaledImageNameLength);
 }
+
--- a/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c	Fri Nov 11 16:44:36 2016 +0100
@@ -535,6 +535,9 @@
     splash->hWnd = SplashCreateWindow(splash);
     if (splash->hWnd) {
         SplashRedrawWindow(splash);
+        //map the splash co-ordinates as per system scale
+        splash->x /= splash->scaleFactor;
+        splash->y /= splash->scaleFactor;
         SplashUnlock(splash);
         SplashMessagePump();
         SplashLock(splash);
@@ -582,55 +585,7 @@
     *scaleFactor = 1.0;
     GetScreenDpi(getPrimaryMonitor(), &dpiScaleX, &dpiScaleY);
     *scaleFactor = dpiScaleX > 0 ? dpiScaleX / 96 : *scaleFactor;
-    if (*scaleFactor > 1.0) {
-        char strDpi[BUFF_SIZE];
-        char *dupFileName = strdup(fileName);
-        char *fileExtension = strrchr(dupFileName, '.');
-        char *nameToAppend = ".scale-";
-        size_t length = 0;
-        int retVal = 0;
-        _snprintf(strDpi, BUFF_SIZE, "%d", (int)dpiScaleX);
-        /*File is missing extension */
-        if (fileExtension == NULL) {
-            length = strlen(dupFileName) + strlen(nameToAppend) +
-                strlen(strDpi) + 1;
-            if (length > scaledImageLength) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-            retVal = _snprintf(scaleImageName, length, "%s%s%s", dupFileName,
-                nameToAppend, strDpi);
-            if (retVal < 0 || (retVal != length - 1)) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-        }
-        else {
-            size_t length_Without_Ext = fileExtension - dupFileName;
-            length = length_Without_Ext + strlen(nameToAppend) + strlen(strDpi) +
-                strlen(fileExtension) + 1;
-            if (length > scaledImageLength) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-            retVal = _snprintf(scaleImageName, length, "%.*s%s%s%s",
-                length_Without_Ext, dupFileName, nameToAppend, strDpi, fileExtension);
-            if (retVal < 0 || (retVal != length - 1)) {
-                *scaleFactor = 1;
-                free(dupFileName);
-                return JNI_FALSE;
-            }
-        }
-        free(dupFileName);
-        if (!(fp = fopen(scaleImageName, "r"))) {
-            *scaleFactor = 1;
-            return JNI_FALSE;
-        }
-        fclose(fp);
-        return JNI_TRUE;
-    }
-    return JNI_FALSE;
+    return GetScaledImageName(fileName, scaleImageName,
+        scaleFactor, scaledImageLength);
 }
+
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1449,6 +1449,11 @@
                 h.close();
             } catch (Exception ex) {
                 // Problems closing a handler?  Keep going...
+            } catch (Error e) {
+                // ignore Errors while shutting down
+                if (globalHandlersState != STATE_SHUTDOWN) {
+                    throw e;
+                }
             }
         }
     }
--- a/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java	Fri Nov 11 16:44:36 2016 +0100
@@ -58,7 +58,8 @@
                                          getString(cd, FILE_NAME),
                                          getInt(cd, LINE_NUMBER));
         } else {
-            return new StackTraceElement(getString(cd, MODULE_NAME),
+            return new StackTraceElement(getString(cd, CLASS_LOADER_NAME),
+                                         getString(cd, MODULE_NAME),
                                          getString(cd, MODULE_VERSION),
                                          getString(cd, CLASS_NAME),
                                          getString(cd, METHOD_NAME),
@@ -76,13 +77,14 @@
         // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
         // stackTraceElementItemNames!
         final Object[] stackTraceElementItemValues = {
+            ste.getClassLoaderName(),
+            ste.getModuleName(),
+            ste.getModuleVersion(),
             ste.getClassName(),
             ste.getMethodName(),
             ste.getFileName(),
             ste.getLineNumber(),
             ste.isNativeMethod(),
-            ste.getModuleName(),
-            ste.getModuleVersion(),
         };
         try {
             return new CompositeDataSupport(stackTraceElementCompositeType,
@@ -95,25 +97,29 @@
     }
 
     // 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 CLASS_LOADER_NAME = "classLoaderName";
+    private static final String MODULE_NAME       = "moduleName";
+    private static final String MODULE_VERSION    = "moduleVersion";
+    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[] stackTraceElementItemNames = {
+        CLASS_LOADER_NAME,
+        MODULE_NAME,
+        MODULE_VERSION,
         CLASS_NAME,
         METHOD_NAME,
         FILE_NAME,
         LINE_NUMBER,
         NATIVE_METHOD,
-        MODULE_NAME,
-        MODULE_VERSION,
     };
 
     private static final String[] stackTraceElementV9ItemNames = {
+        CLASS_LOADER_NAME,
         MODULE_NAME,
         MODULE_VERSION,
     };
--- a/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/server/Activation.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1970,6 +1970,11 @@
                 AccessController.doPrivileged(
                     new PrivilegedExceptionAction<Void>() {
                         public Void run() throws IOException {
+                            boolean disable = Boolean.getBoolean(
+                                    "sun.rmi.server.activation.disableErrRedirect");
+                            if (disable)
+                                return null;
+
                             File file =
                                 Files.createTempFile("rmid-err", null).toFile();
                             PrintStream errStream =
--- a/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.rmi/share/classes/sun/rmi/transport/tcp/TCPTransport.java	Fri Nov 11 16:44:36 2016 +0100
@@ -102,6 +102,11 @@
         AccessController.doPrivileged((PrivilegedAction<Long>) () ->
             Long.getLong("sun.rmi.transport.tcp.threadKeepAliveTime", 60000));
 
+    /** enable multiplexing protocol */
+    private static final boolean enableMultiplexProtocol =     // default false
+            AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
+                    Boolean.getBoolean("sun.rmi.transport.tcp.enableMultiplexProtocol"));
+
     /** thread pool for connection handlers */
     private static final ExecutorService connectionThreadPool =
         new ThreadPoolExecutor(0, maxConnectionThreads,
@@ -796,6 +801,19 @@
                     break;
 
                 case TransportConstants.MultiplexProtocol:
+
+                    if (!enableMultiplexProtocol) {
+                        if (tcpLog.isLoggable(Log.VERBOSE)) {
+                            tcpLog.log(Log.VERBOSE, "(port " + port +
+                                    ") rejecting multiplex protocol");
+                        }
+
+                        // If MultiplexProtocol is disabled, send NACK immediately.
+                        out.writeByte(TransportConstants.ProtocolNack);
+                        out.flush();
+                        break;
+                    }
+
                     if (tcpLog.isLoggable(Log.VERBOSE)) {
                         tcpLog.log(Log.VERBOSE, "(port " + port +
                             ") accepting multiplex protocol");
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/KrbApReq.java	Fri Nov 11 16:44:36 2016 +0100
@@ -301,12 +301,13 @@
         if (!authenticator.ctime.inClockSkew())
             throw new KrbApErrException(Krb5.KRB_AP_ERR_SKEW);
 
+        String alg = AuthTimeWithHash.DEFAULT_HASH_ALG;
         byte[] hash;
         try {
-            hash = MessageDigest.getInstance("MD5")
+            hash = MessageDigest.getInstance(AuthTimeWithHash.realAlg(alg))
                     .digest(apReqMessg.authenticator.cipher);
         } catch (NoSuchAlgorithmException ex) {
-            throw new AssertionError("Impossible");
+            throw new AssertionError("Impossible " + alg);
         }
 
         char[] h = new char[hash.length * 2];
@@ -319,6 +320,7 @@
                 apReqMessg.ticket.sname.toString(),
                 authenticator.ctime.getSeconds(),
                 authenticator.cusec,
+                alg,
                 new String(h));
         rcache.checkAndStore(KerberosTime.now(), time);
 
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTime.java	Fri Nov 11 16:44:36 2016 +0100
@@ -116,14 +116,14 @@
             if (st.countTokens() != 6) {
                 throw new IOException("Incorrect rcache style");
             }
-            st.nextToken();
+            String hashAlg = st.nextToken();
             String hash = st.nextToken();
             st.nextToken();
             client = st.nextToken();
             st.nextToken();
             server = st.nextToken();
             return new AuthTimeWithHash(
-                    client, server, ctime, cusec, hash);
+                    client, server, ctime, cusec, hashAlg, hash);
         } else {
             return new AuthTime(
                     client, server, ctime, cusec);
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/AuthTimeWithHash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,6 +25,8 @@
 
 package sun.security.krb5.internal.rcache;
 
+import sun.security.action.GetPropertyAction;
+
 import java.util.Objects;
 
 /**
@@ -34,14 +36,39 @@
 public class AuthTimeWithHash extends AuthTime
         implements Comparable<AuthTimeWithHash> {
 
+    // The hash algorithm can be "HASH" or "SHA256".
+    public static final String DEFAULT_HASH_ALG;
+
+    static {
+        if (GetPropertyAction.privilegedGetProperty(
+                "jdk.krb5.rcache.useMD5", "false").equals("true")) {
+            DEFAULT_HASH_ALG = "HASH";
+        } else {
+            DEFAULT_HASH_ALG = "SHA256";
+        }
+    }
+
+    public static String realAlg(String alg) {
+        switch (alg) {
+            case "HASH":
+                return "MD5";
+            case "SHA256":
+                return "SHA-256";
+            default:
+                throw new AssertionError(alg + " is not HASH or SHA256");
+        }
+    }
+
+    final String hashAlg;
     final String hash;
 
     /**
      * Constructs a new <code>AuthTimeWithHash</code>.
      */
     public AuthTimeWithHash(String client, String server,
-            int ctime, int cusec, String hash) {
+            int ctime, int cusec, String hashAlg, String hash) {
         super(client, server, ctime, cusec);
+        this.hashAlg = hashAlg;
         this.hash = hash;
     }
 
@@ -56,6 +83,7 @@
         if (!(o instanceof AuthTimeWithHash)) return false;
         AuthTimeWithHash that = (AuthTimeWithHash)o;
         return Objects.equals(hash, that.hash)
+                && Objects.equals(hashAlg, that.hashAlg)
                 && Objects.equals(client, that.client)
                 && Objects.equals(server, that.server)
                 && ctime == that.ctime
@@ -91,6 +119,19 @@
     /**
      * Compares with a possibly old style object. Used
      * in DflCache$Storage#loadAndCheck.
+     * @return true if all AuthTime fields are the same but different hash
+     */
+    public boolean sameTimeDiffHash(AuthTimeWithHash old) {
+        if (!this.isSameIgnoresHash(old)) {
+            return false;
+        }
+        return this.hashAlg.equals(old.hashAlg) &&
+                !this.hash.equals(old.hash);
+    }
+
+    /**
+     * Compares with a possibly old style object. Used
+     * in DflCache$Storage#loadAndCheck.
      * @return true if all AuthTime fields are the same
      */
     public boolean isSameIgnoresHash(AuthTime old) {
@@ -112,7 +153,7 @@
         String sstring;
         if (withHash) {
             cstring = "";
-            sstring = String.format("HASH:%s %d:%s %d:%s", hash,
+            sstring = String.format("%s:%s %d:%s %d:%s", hashAlg, hash,
                     client.length(), client,
                     server.length(), server);
         } else {
--- a/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.security.jgss/share/classes/sun/security/krb5/internal/rcache/DflCache.java	Fri Nov 11 16:44:36 2016 +0100
@@ -96,6 +96,8 @@
  * Java also does this way.
  *
  * See src/lib/krb5/rcache/rc_io.c and src/lib/krb5/rcache/rc_dfl.c.
+ *
+ * Update: New version can use other hash algorithms.
  */
 public class DflCache extends ReplayCache {
 
@@ -300,7 +302,7 @@
                         if (time.equals(a)) {
                             // Exact match, must be a replay
                             throw new KrbApErrException(Krb5.KRB_AP_ERR_REPEAT);
-                        } else if (time.isSameIgnoresHash(a)) {
+                        } else if (time.sameTimeDiffHash((AuthTimeWithHash)a)) {
                             // Two different authenticators in the same second.
                             // Remember it
                             seeNewButNotSame = true;
--- a/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/CallableStatement.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -295,7 +295,7 @@
      *             or <code>getBigDecimal(String parameterName)</code>
      * @see #setBigDecimal
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     BigDecimal getBigDecimal(int parameterIndex, int scale)
         throws SQLException;
 
--- a/jdk/src/java.sql/share/classes/java/sql/Date.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/Date.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -58,7 +58,7 @@
      * @param day 1 to 31
      * @deprecated instead use the constructor <code>Date(long date)</code>
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public Date(int year, int month, int day) {
         super(year, month, day);
     }
@@ -199,7 +199,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setHours
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getHours() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -212,7 +212,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setMinutes
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getMinutes() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -225,7 +225,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #setSeconds
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getSeconds() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -238,7 +238,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getHours
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setHours(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -251,7 +251,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getMinutes
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setMinutes(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -264,7 +264,7 @@
     * @exception java.lang.IllegalArgumentException if this method is invoked
     * @see #getSeconds
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setSeconds(int i) {
         throw new java.lang.IllegalArgumentException();
     }
--- a/jdk/src/java.sql/share/classes/java/sql/DriverManager.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/DriverManager.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -515,7 +515,7 @@
      * @see SecurityManager#checkPermission
      * @see #getLogStream
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public static void setLogStream(java.io.PrintStream out) {
 
         SecurityManager sec = System.getSecurityManager();
@@ -538,7 +538,7 @@
      * @deprecated  Use {@code getLogWriter}
      * @see #setLogStream
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public static java.io.PrintStream getLogStream() {
         return logStream;
     }
--- a/jdk/src/java.sql/share/classes/java/sql/PreparedStatement.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/PreparedStatement.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -344,7 +344,7 @@
      * this method
      * @deprecated Use {@code setCharacterStream}
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     void setUnicodeStream(int parameterIndex, java.io.InputStream x,
                           int length) throws SQLException;
 
--- a/jdk/src/java.sql/share/classes/java/sql/ResultSet.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/ResultSet.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -358,7 +358,7 @@
      * @deprecated Use {@code getBigDecimal(int columnIndex)}
      *             or {@code getBigDecimal(String columnLabel)}
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException;
 
     /**
@@ -478,7 +478,7 @@
      * @deprecated use <code>getCharacterStream</code> in place of
      *              <code>getUnicodeStream</code>
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     java.io.InputStream getUnicodeStream(int columnIndex) throws SQLException;
 
     /**
@@ -646,7 +646,7 @@
      * @deprecated Use {@code getBigDecimal(int columnIndex)}
      *             or {@code getBigDecimal(String columnLabel)}
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException;
 
     /**
@@ -764,7 +764,7 @@
      * this method
      * @deprecated use <code>getCharacterStream</code> instead
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     java.io.InputStream getUnicodeStream(String columnLabel) throws SQLException;
 
     /**
--- a/jdk/src/java.sql/share/classes/java/sql/Time.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/Time.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -60,7 +60,7 @@
      * @deprecated Use the constructor that takes a milliseconds value
      *             in place of this constructor
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public Time(int hour, int minute, int second) {
         super(70, 0, 1, hour, minute, second);
     }
@@ -146,7 +146,7 @@
     *           method is invoked
     * @see #setYear
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getYear() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -160,7 +160,7 @@
     *           method is invoked
     * @see #setMonth
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getMonth() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -173,7 +173,7 @@
     * @exception java.lang.IllegalArgumentException if this
     *           method is invoked
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getDay() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -187,7 +187,7 @@
     *           method is invoked
     * @see #setDate
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public int getDate() {
         throw new java.lang.IllegalArgumentException();
     }
@@ -201,7 +201,7 @@
     *           method is invoked
     * @see #getYear
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setYear(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -215,7 +215,7 @@
     *           method is invoked
     * @see #getMonth
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setMonth(int i) {
         throw new java.lang.IllegalArgumentException();
     }
@@ -229,7 +229,7 @@
     *           method is invoked
     * @see #getDate
     */
-    @Deprecated
+    @Deprecated(since="1.2")
     public void setDate(int i) {
         throw new java.lang.IllegalArgumentException();
     }
--- a/jdk/src/java.sql/share/classes/java/sql/Timestamp.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/java.sql/share/classes/java/sql/Timestamp.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,7 @@
      * @deprecated instead use the constructor {@code Timestamp(long millis)}
      * @exception IllegalArgumentException if the nano argument is out of bounds
      */
-    @Deprecated
+    @Deprecated(since="1.2")
     public Timestamp(int year, int month, int date,
                      int hour, int minute, int second, int nano) {
         super(year, month, date, hour, minute, second);
--- a/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.accessibility/windows/classes/com/sun/java/accessibility/internal/AccessBridge.java	Fri Nov 11 16:44:36 2016 +0100
@@ -41,13 +41,13 @@
 
 import javax.accessibility.*;
 import com.sun.java.accessibility.util.*;
+import java.awt.geom.Rectangle2D;
 import sun.awt.AWTAccessor;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.CountDownLatch;
 
 /*
  * Note: This class has to be public.  It's loaded from the VM like this:
@@ -1754,7 +1754,7 @@
                     if (child instanceof JTextComponent) {
                         JTextComponent text = (JTextComponent) child;
                         try {
-                            r = text.modelToView(text.getCaretPosition());
+                            r = text.modelToView2D(text.getCaretPosition()).getBounds();
                             if (r != null) {
                                 Point p = text.getLocationOnScreen();
                                 r.translate(p.x, p.y);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.desktop/share/classes/jdk/awt/AWTUtils.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.awt;
+
+import java.awt.Component;
+import java.awt.Shape;
+
+import com.sun.awt.AWTUtilities;
+
+/**
+ * A class to allow access to JDK-specific utility methods.
+ * Methods in this class are always deprecated since a caller
+ * should be aware they may be removed and replaced in the future.
+ * Access using reflection is highly recommended.
+ * @since 9
+ */
+public final class AWTUtils {
+
+    /**
+     * No-one should be creating instances of this class.
+     */
+    private AWTUtils() {
+    }
+
+    /**
+     * Sets a 'mixing-cutout' shape for the given component.
+     *
+     * By default a lightweight component is treated as an opaque rectangle for
+     * the purposes of the Heavyweight/Lightweight Components Mixing feature.
+     * This method enables developers to set an arbitrary shape to be cut out
+     * from heavyweight components positioned underneath the lightweight
+     * component in the z-order.
+     * <p>
+     * The {@code shape} argument may have the following values:
+     * <ul>
+     * <li>{@code null} - reverts the default cutout shape (the rectangle equal
+     * to the component's {@code getBounds()})
+     * <li><i>empty-shape</i> - does not cut out anything from heavyweight
+     * components. This makes the given lightweight component effectively
+     * transparent. Note that descendants of the lightweight component still
+     * affect the shapes of heavyweight components.  An example of an
+     * <i>empty-shape</i> is {@code new Rectangle()}.
+     * <li><i>non-empty-shape</i> - the given shape will be cut out from
+     * heavyweight components.
+     * </ul>
+     * <p>
+     * The most common example when the 'mixing-cutout' shape is needed is a
+     * glass pane component. The {@link JRootPane#setGlassPane()} method
+     * automatically sets the <i>empty-shape</i> as the 'mixing-cutout' shape
+     * for the given glass pane component.  If a developer needs some other
+     * 'mixing-cutout' shape for the glass pane (which is rare), this must be
+     * changed manually after installing the glass pane to the root pane.
+     * <p>
+     * Note that the 'mixing-cutout' shape neither affects painting, nor the
+     * mouse events handling for the given component. It is used exclusively
+     * for the purposes of the Heavyweight/Lightweight Components Mixing
+     * feature.
+     *
+     * @param component the component that needs non-default
+     * 'mixing-cutout' shape
+     * @param shape the new 'mixing-cutout' shape
+     * @throws NullPointerException if the component argument is {@code null}
+     * @deprecated This API may be removed or replaced.
+     */
+    @Deprecated
+    @SuppressWarnings("deprecation")
+    public static void setComponentMixingCutoutShape(Component component,
+                                                     Shape shape) {
+
+        AWTUtilities.setComponentMixingCutoutShape(component, shape);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.desktop/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 non-SE desktop APIs.
+ */
+
+module jdk.desktop {
+    requires public java.desktop;
+
+    exports jdk.awt;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPad.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 jdk.editpad;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.function.Consumer;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+/**
+ * A minimal Swing editor as a fallback when the user does not specify an
+ * external editor.
+ */
+class EditPad implements Runnable {
+
+    private static final String L10N_RB_NAME  = "jdk.editpad.resources.l10n";
+    private ResourceBundle rb  = null;
+    private final String windowLabel;
+    private final Consumer<String> errorHandler;
+    private final String initialText;
+    private final Runnable closeMark;
+    private final Consumer<String> saveHandler;
+
+    /**
+     * Create an Edit Pad minimal editor.
+     *
+     * @param windowLabel the label string for the Edit Pad window
+     * @param errorHandler a handler for unexpected errors
+     * @param initialText the source to load in the Edit Pad
+     * @param closeMark a Runnable that is run when Edit Pad closes
+     * @param saveHandler a handler for changed source (sent the full source)
+     */
+    EditPad(String windowLabel, Consumer<String> errorHandler, String initialText,
+            Runnable closeMark, Consumer<String> saveHandler) {
+        this.windowLabel = windowLabel;
+        this.errorHandler = errorHandler;
+        this.initialText = initialText;
+        this.closeMark = closeMark;
+        this.saveHandler = saveHandler;
+    }
+
+    @Override
+    public void run() {
+        JFrame jframe = new JFrame(windowLabel == null
+                ? getResourceString("editpad.name")
+                : windowLabel);
+        Runnable closer = () -> {
+            jframe.setVisible(false);
+            jframe.dispose();
+            closeMark.run();
+        };
+        jframe.addWindowListener(new WindowAdapter() {
+            @Override
+            public void windowClosing(WindowEvent e) {
+                closer.run();
+            }
+        });
+        jframe.setLocationRelativeTo(null);
+        jframe.setLayout(new BorderLayout());
+        JTextArea textArea = new JTextArea(initialText);
+        textArea.setFont(new Font("monospaced", Font.PLAIN, 13));
+        jframe.add(new JScrollPane(textArea), BorderLayout.CENTER);
+        jframe.add(buttons(closer, textArea), BorderLayout.SOUTH);
+
+        jframe.setSize(800, 600);
+        jframe.setVisible(true);
+    }
+
+    private JPanel buttons(Runnable closer, JTextArea textArea) {
+        FlowLayout flow = new FlowLayout();
+        flow.setHgap(35);
+        JPanel buttons = new JPanel(flow);
+        addButton(buttons, "editpad.cancel", KeyEvent.VK_C, e -> {
+            closer.run();
+        });
+        addButton(buttons, "editpad.accept", KeyEvent.VK_A, e -> {
+            saveHandler.accept(textArea.getText());
+        });
+        addButton(buttons, "editpad.exit",   KeyEvent.VK_X, e -> {
+            saveHandler.accept(textArea.getText());
+            closer.run();
+        });
+        return buttons;
+    }
+
+    private void addButton(JPanel buttons, String rkey, int mnemonic, ActionListener action) {
+        JButton but = new JButton(getResourceString(rkey));
+        but.setMnemonic(mnemonic);
+        buttons.add(but);
+        but.addActionListener(action);
+    }
+
+    private String getResourceString(String key) {
+        if (rb == null) {
+            try {
+                rb = ResourceBundle.getBundle(L10N_RB_NAME);
+            } catch (MissingResourceException mre) {
+                error("Cannot find ResourceBundle: %s", L10N_RB_NAME);
+                return "";
+            }
+        }
+        String s;
+        try {
+            s = rb.getString(key);
+        } catch (MissingResourceException mre) {
+            error("Missing resource: %s in %s", key, L10N_RB_NAME);
+            return "";
+        }
+        return s;
+    }
+
+    private void error(String fmt, Object... args) {
+        errorHandler.accept(String.format(fmt, args));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/EditPadProvider.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.editpad;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.function.Consumer;
+import javax.swing.SwingUtilities;
+import jdk.internal.editor.spi.BuildInEditorProvider;
+
+/**
+ * Defines the provider of an Edit Pad implementation.
+ *
+ * @author Robert Field
+ */
+public class EditPadProvider implements BuildInEditorProvider {
+
+    /**
+     * @return the rank of a provider, greater is better.
+     */
+    @Override
+    public int rank() {
+        return 5;
+    }
+
+    /**
+     * Create an Edit Pad minimal editor.
+     *
+     * @param windowLabel the label string for the Edit Pad window, or null,
+     * for default window label
+     * @param initialText the source to load in the Edit Pad
+     * @param saveHandler a handler for changed source (can be sent the full source)
+     * @param errorHandler a handler for unexpected errors
+     */
+    @Override
+    public void edit(String windowLabel, String initialText,
+            Consumer<String> saveHandler, Consumer<String> errorHandler) {
+        CountDownLatch closeLock = new CountDownLatch(1);
+        SwingUtilities.invokeLater(
+                new EditPad(windowLabel, errorHandler, initialText, closeLock::countDown, saveHandler));
+        do {
+            try {
+                closeLock.await();
+                break;
+            } catch (InterruptedException ex) {
+                // ignore and loop
+            }
+        } while (true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.editpad/share/classes/jdk/editpad/resources/l10n.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+editpad.name = Edit Pad
+editpad.cancel = Cancel
+editpad.accept = Accept
+editpad.exit = Exit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.editpad/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Implementation of the edit pad service.
+ */
+module jdk.editpad {
+    requires jdk.internal.ed;
+    requires java.desktop;
+    provides jdk.internal.editor.spi.BuildInEditorProvider
+              with jdk.editpad.EditPadProvider;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/external/ExternalEditor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,192 @@
+/*
+ * 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.editor.external;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.ClosedWatchServiceException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.Arrays;
+import java.util.Scanner;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+
+/**
+ * Wrapper for controlling an external editor.
+ */
+public class ExternalEditor {
+    private final Consumer<String> errorHandler;
+    private final Consumer<String> saveHandler;
+    private final boolean wait;
+
+    private final Runnable suspendInteractiveInput;
+    private final Runnable resumeInteractiveInput;
+    private final Runnable promptForNewLineToEndWait;
+
+    private WatchService watcher;
+    private Thread watchedThread;
+    private Path dir;
+    private Path tmpfile;
+
+    /**
+     * Launch an external editor.
+     *
+     * @param cmd the command to launch (with parameters)
+     * @param initialText initial text in the editor buffer
+     * @param errorHandler handler for error messages
+     * @param saveHandler handler sent the buffer contents on save
+     * @param suspendInteractiveInput a callback to suspend caller (shell) input
+     * @param resumeInteractiveInput a callback to resume caller input
+     * @param wait true, if editor process termination cannot be used to
+     * determine when done
+     * @param promptForNewLineToEndWait a callback to prompt for newline if
+     * wait==true
+     */
+    public static void edit(String[] cmd, String initialText,
+            Consumer<String> errorHandler,
+            Consumer<String> saveHandler,
+            Runnable suspendInteractiveInput,
+            Runnable resumeInteractiveInput,
+            boolean wait,
+            Runnable promptForNewLineToEndWait) {
+        ExternalEditor ed = new ExternalEditor(errorHandler, saveHandler, suspendInteractiveInput,
+             resumeInteractiveInput, wait, promptForNewLineToEndWait);
+        ed.edit(cmd, initialText);
+    }
+
+    ExternalEditor(Consumer<String> errorHandler,
+            Consumer<String> saveHandler,
+            Runnable suspendInteractiveInput,
+            Runnable resumeInteractiveInput,
+            boolean wait,
+            Runnable promptForNewLineToEndWait) {
+        this.errorHandler = errorHandler;
+        this.saveHandler = saveHandler;
+        this.wait = wait;
+        this.suspendInteractiveInput = suspendInteractiveInput;
+        this.resumeInteractiveInput = resumeInteractiveInput;
+        this.promptForNewLineToEndWait = promptForNewLineToEndWait;
+    }
+
+    private void edit(String[] cmd, String initialText) {
+        try {
+            setupWatch(initialText);
+            launch(cmd);
+        } catch (IOException ex) {
+            errorHandler.accept(ex.getMessage());
+        }
+    }
+
+    /**
+     * Creates a WatchService and registers the given directory
+     */
+    private void setupWatch(String initialText) throws IOException {
+        this.watcher = FileSystems.getDefault().newWatchService();
+        this.dir = Files.createTempDirectory("extedit");
+        this.tmpfile = Files.createTempFile(dir, null, ".java");
+        Files.write(tmpfile, initialText.getBytes(Charset.forName("UTF-8")));
+        dir.register(watcher,
+                ENTRY_CREATE,
+                ENTRY_DELETE,
+                ENTRY_MODIFY);
+        watchedThread = new Thread(() -> {
+            for (;;) {
+                WatchKey key;
+                try {
+                    key = watcher.take();
+                } catch (ClosedWatchServiceException ex) {
+                    // The watch service has been closed, we are done
+                    break;
+                } catch (InterruptedException ex) {
+                    // tolerate an interrupt
+                    continue;
+                }
+
+                if (!key.pollEvents().isEmpty()) {
+                    saveFile();
+                }
+
+                boolean valid = key.reset();
+                if (!valid) {
+                    // The watch service has been closed, we are done
+                    break;
+                }
+            }
+        });
+        watchedThread.start();
+    }
+
+    private void launch(String[] cmd) throws IOException {
+        String[] params = Arrays.copyOf(cmd, cmd.length + 1);
+        params[cmd.length] = tmpfile.toString();
+        ProcessBuilder pb = new ProcessBuilder(params);
+        pb = pb.inheritIO();
+
+        try {
+            suspendInteractiveInput.run();
+            Process process = pb.start();
+            // wait to exit edit mode in one of these ways...
+            if (wait) {
+                // -wait option -- ignore process exit, wait for carriage-return
+                Scanner scanner = new Scanner(System.in);
+                promptForNewLineToEndWait.run();
+                scanner.nextLine();
+            } else {
+                // wait for process to exit
+                process.waitFor();
+            }
+        } catch (IOException ex) {
+            errorHandler.accept("process IO failure: " + ex.getMessage());
+        } catch (InterruptedException ex) {
+            errorHandler.accept("process interrupt: " + ex.getMessage());
+        } finally {
+            try {
+                watcher.close();
+                watchedThread.join(); //so that saveFile() is finished.
+                saveFile();
+            } catch (InterruptedException ex) {
+                errorHandler.accept("process interrupt: " + ex.getMessage());
+            } finally {
+                resumeInteractiveInput.run();
+            }
+        }
+    }
+
+    private void saveFile() {
+        try {
+            saveHandler.accept(Files.lines(tmpfile).collect(Collectors.joining("\n", "", "\n")));
+        } catch (IOException ex) {
+            errorHandler.accept("Failure in read edit file: " + ex.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.ed/share/classes/jdk/internal/editor/spi/BuildInEditorProvider.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.editor.spi;
+
+import java.util.function.Consumer;
+
+/**
+ * Defines the provider of a built-in editor.
+ */
+public interface BuildInEditorProvider {
+
+    /**
+     * @return the rank of a provider, greater is better.
+     */
+    int rank();
+
+    /**
+     * Create a simple built-in editor.
+     *
+     * @param windowLabel the label string for the Edit Pad window, or null,
+     * for default window label
+     * @param initialText the source to load in the Edit Pad
+     * @param saveHandler a handler for changed source (can be sent the full source)
+     * @param errorHandler a handler for unexpected errors
+     */
+    void edit(String windowLabel, String initialText,
+            Consumer<String> saveHandler, Consumer<String> errorHandler);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.internal.ed/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Internal editor support for JDK tools.  Includes the Service Provider
+ * Interface to built-in editors.
+ */
+module jdk.internal.ed {
+
+    exports jdk.internal.editor.spi to jdk.editpad, jdk.jshell, jdk.scripting.nashorn.shell;
+    exports jdk.internal.editor.external to jdk.jshell, jdk.scripting.nashorn.shell;
+}
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -80,6 +80,7 @@
     String fname, mname, ename;
     String zname = "";
     String rootjar = null;
+    Set<String> concealedPackages = new HashSet<>();
 
     private static final int BASE_VERSION = 0;
 
@@ -821,22 +822,21 @@
         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('/');
+        int index;
+        if (path.startsWith(VERSIONS_DIR)) {
+            index = path.indexOf('/', VERSIONS_DIR.length());
+            if (index <= 0) {
+                return "";
+            }
+            path = path.substring(index + 1);
+        }
+        index = path.lastIndexOf('/');
         if (index != -1) {
             return path.substring(0, index).replace('/', '.');
         } else {
@@ -875,7 +875,7 @@
                         entryMap.put(entryName, entry);
                 } else if (entries.add(entry)) {
                     jarEntries.add(entryName);
-                    if (entry.basename.endsWith(".class") && !entryName.startsWith(VERSIONS_DIR))
+                    if (entry.basename.endsWith(".class"))
                         packages.add(toPackageName(entry.basename));
                     if (isUpdate)
                         entryMap.put(entryName, entry);
@@ -1068,7 +1068,7 @@
                 }
 
                 jarEntries.add(name);
-                if (name.endsWith(".class") && !(name.startsWith(VERSIONS_DIR)))
+                if (name.endsWith(".class"))
                     packages.add(toPackageName(name));
             }
         }
@@ -1762,6 +1762,13 @@
     }
 
     /**
+     * Print a warning message
+     */
+    void warn(String s) {
+        err.println(s);
+    }
+
+    /**
      * Main routine to start program.
      */
     public static void main(String args[]) {
@@ -1975,24 +1982,30 @@
         ByteBuffer bb = ByteBuffer.wrap(moduleInfos.get(MODULE_INFO));
         ModuleDescriptor rd = ModuleDescriptor.read(bb);
 
-        Set<String> exports = rd.exports()
-                                .stream()
-                                .map(Exports::source)
-                                .collect(toSet());
-
-        Set<String> conceals = packages.stream()
-                                       .filter(p -> !exports.contains(p))
-                                       .collect(toSet());
+        concealedPackages = findConcealedPackages(rd);
 
         for (Map.Entry<String,byte[]> e: moduleInfos.entrySet()) {
             ModuleDescriptor vd = ModuleDescriptor.read(ByteBuffer.wrap(e.getValue()));
             if (!(isValidVersionedDescriptor(vd, rd)))
                 return false;
-            e.setValue(extendedInfoBytes(rd, vd, e.getValue(), conceals));
+            e.setValue(extendedInfoBytes(rd, vd, e.getValue(), concealedPackages));
         }
         return true;
     }
 
+    private Set<String> findConcealedPackages(ModuleDescriptor md){
+        Objects.requireNonNull(md);
+
+        Set<String> exports = md.exports()
+                .stream()
+                .map(Exports::source)
+                .collect(toSet());
+
+        return packages.stream()
+                .filter(p -> !exports.contains(p))
+                .collect(toSet());
+    }
+
     private static boolean isPlatformModule(String name) {
         return name.startsWith("java.") || name.startsWith("jdk.");
     }
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/Validator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -152,9 +152,13 @@
                     return;
                 }
                 if (fp.isPublicClass()) {
-                    main.error(Main.formatMsg("error.validator.new.public.class", entryName));
-                    isValid = false;
-                    return;
+                    if (!isConcealed(internalName)) {
+                        main.error(Main.formatMsg("error.validator.new.public.class", entryName));
+                        isValid = false;
+                        return;
+                    }
+                    main.warn(Main.formatMsg("warn.validator.concealed.public.class", entryName));
+                    debug("%s is a public class entry in a concealed package", entryName);
                 }
                 debug("%s is a non-public class entry", entryName);
                 fps.put(internalName, fp);
@@ -169,7 +173,7 @@
 
         // are the two classes/resources identical?
         if (fp.isIdentical(matchFp)) {
-            main.error(Main.formatMsg("error.validator.identical.entry", entryName));
+            main.warn(Main.formatMsg("warn.validator.identical.entry", entryName));
             return;  // it's okay, just takes up room
         }
         debug("sha1 not equal -- different bytes");
@@ -204,7 +208,7 @@
         }
         debug("%s is a resource", entryName);
 
-        main.error(Main.formatMsg("error.validator.resources.with.same.name", entryName));
+        main.warn(Main.formatMsg("warn.validator.resources.with.same.name", entryName));
         fps.put(internalName, fp);
         return;
     }
@@ -235,6 +239,15 @@
         return entryName.endsWith(".class") ? entryName.substring(0, entryName.length() - 6) : null;
     }
 
+    private boolean isConcealed(String internalName) {
+        if (main.concealedPackages.isEmpty()) {
+            return false;
+        }
+        int idx = internalName.lastIndexOf('/');
+        String pkgName = idx != -1 ? internalName.substring(0, idx).replace('/', '.') : "";
+        return main.concealedPackages.contains(pkgName);
+    }
+
     private void debug(String fmt, Object... args) {
         if (DEBUG) System.err.format(fmt, args);
     }
--- a/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -99,16 +99,19 @@
         entry: {0}, is an isolated nested class
 error.validator.new.public.class=\
         entry: {0}, contains a new public class not found in base entries
-error.validator.identical.entry=\
-        warning - entry: {0} contains a class that is identical to an entry already in the jar
 error.validator.incompatible.class.version=\
         entry: {0}, has a class version incompatible with an earlier version
 error.validator.different.api=\
         entry: {0}, contains a class with different api from earlier version
-error.validator.resources.with.same.name=\
-         warning - entry: {0}, multiple resources with same name
 error.validator.names.mismatch=\
          entry: {0}, contains a class with internal name {1}, names do not match
+warn.validator.identical.entry=\
+        warning - entry: {0} contains a class that is identical to an entry already in the jar
+warn.validator.resources.with.same.name=\
+         warning - entry: {0}, multiple resources with same name
+warn.validator.concealed.public.class=\
+         warning - entry {0} is a public class in a concealed package, \n\
+         placing this jar on the class path will result in incompatible public interfaces
 out.added.manifest=\
         added manifest
 out.added.module-info=\
--- a/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -246,9 +246,9 @@
      * @throws java.lang.IllegalArgumentException if the method is not
      * a member of this object's class, if the size of the argument list
      * does not match the number of declared arguments for the method,
-     * if the method is a constructor or static intializer, or
+     * if the method is a constructor or static initializer, or
      * if {@link #INVOKE_NONVIRTUAL} is specified and the method is
-     * either abstract or a non-default interface member.
+     * abstract.
      * @throws {@link InvalidTypeException} if any argument in the
      * argument list is not assignable to the corresponding method argument
      * type.
--- a/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jdi/share/classes/com/sun/tools/jdi/ObjectReferenceImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -347,10 +347,12 @@
                                          throws InvalidTypeException,
                                          InvocationException {
         /*
-         * Only default methods allowed for nonvirtual invokes
+         * For nonvirtual invokes, method must have a body
          */
-        if (isNonVirtual(options) && !method.isDefault()) {
-            throw new IllegalArgumentException("Not a default method");
+        if (isNonVirtual(options)) {
+            if (method.isAbstract()) {
+                throw new IllegalArgumentException("Abstract method");
+            }
         }
     }
 
--- a/jdk/src/jdk.jdi/share/classes/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jdi/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,7 +32,6 @@
     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;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jimage/JImageTask.java	Fri Nov 11 16:44:36 2016 +0100
@@ -359,9 +359,9 @@
         if (name.endsWith(".class") && !name.endsWith("module-info.class")) {
             try {
                 byte[] bytes = reader.getResource(location);
-                ClassReader cr =new ClassReader(bytes);
+                ClassReader cr = new ClassReader(bytes);
                 ClassNode cn = new ClassNode();
-                cr.accept(cn, ClassReader.EXPAND_FRAMES);
+                cr.accept(cn, 0);
             } catch (Exception ex) {
                 log.println("Error(s) in Class: " + name);
             }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JarArchive.java	Fri Nov 11 16:44:36 2016 +0100
@@ -30,9 +30,11 @@
 import java.io.UncheckedIOException;
 import java.nio.file.Path;
 import java.util.Objects;
+import java.util.jar.JarFile;
 import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
+import jdk.internal.util.jar.VersionedStream;
 import jdk.tools.jlink.internal.Archive.Entry.EntryType;
 
 /**
@@ -72,8 +74,8 @@
 
     private final Path file;
     private final String moduleName;
-    // currently processed ZipFile
-    protected ZipFile zipFile;
+    // currently processed JarFile
+    private JarFile jarFile;
 
     protected JarArchive(String mn, Path file) {
         Objects.requireNonNull(mn);
@@ -95,13 +97,15 @@
     @Override
     public Stream<Entry> entries() {
         try {
-            if (zipFile == null) {
+            if (jarFile == null) {
                 open();
             }
         } catch (IOException ioe) {
             throw new UncheckedIOException(ioe);
         }
-        return zipFile.stream().map(this::toEntry).filter(n -> n != null);
+        return VersionedStream.stream(jarFile)
+                .filter(je -> !je.isDirectory())
+                .map(this::toEntry);
     }
 
     abstract EntryType toEntryType(String entryName);
@@ -112,16 +116,20 @@
 
     @Override
     public void close() throws IOException {
-        if (zipFile != null) {
-            zipFile.close();
+        if (jarFile != null) {
+            jarFile.close();
         }
     }
 
     @Override
     public void open() throws IOException {
-        if (zipFile != null) {
-            zipFile.close();
+        if (jarFile != null) {
+            jarFile.close();
         }
-        zipFile = new ZipFile(file.toFile());
+        jarFile = new JarFile(file.toFile(), true, ZipFile.OPEN_READ, JarFile.runtimeVersion());
+    }
+
+    protected JarFile getJarFile() {
+        return jarFile;
     }
 }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/JlinkTask.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,6 @@
 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;
@@ -41,9 +40,8 @@
 import java.nio.file.Paths;
 import java.util.*;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-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.Jlink.JlinkConfiguration;
@@ -54,6 +52,7 @@
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.builder.DefaultImageBuilder;
 import jdk.tools.jlink.plugin.Plugin;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  * Implementation for the jlink tool.
@@ -63,20 +62,8 @@
 public class JlinkTask {
     static final boolean DEBUG = Boolean.getBoolean("jlink.debug");
 
-    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);
-        }
-    }
+    // jlink API ignores by default. Remove when signing is implemented.
+    static final boolean IGNORE_SIGNING_DEFAULT = true;
 
     private static final TaskHelper taskHelper
             = new TaskHelper(JLINK_BUNDLE);
@@ -144,7 +131,10 @@
         }, "--save-opts"),
         new Option<JlinkTask>(false, (task, opt, arg) -> {
             task.options.fullVersion = true;
-        }, true, "--full-version"),};
+        }, true, "--full-version"),
+        new Option<JlinkTask>(false, (task, opt, arg) -> {
+            task.options.ignoreSigning = true;
+        }, true, "--ignore-signing-information"),};
 
     private static final String PROGNAME = "jlink";
     private final OptionsValues options = new OptionsValues();
@@ -161,7 +151,8 @@
     /**
      * Result codes.
      */
-    static final int EXIT_OK = 0, // Completed with no errors.
+    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.
@@ -172,12 +163,13 @@
         String  saveoptsfile;
         boolean version;
         boolean fullVersion;
-        List<Path> modulePath = new ArrayList<>();
-        Set<String> limitMods = new HashSet<>();
-        Set<String> addMods = new HashSet<>();
+        final List<Path> modulePath = new ArrayList<>();
+        final Set<String> limitMods = new HashSet<>();
+        final Set<String> addMods = new HashSet<>();
         Path output;
         Path packagedModulesPath;
         ByteOrder endian = ByteOrder.nativeOrder();
+        boolean ignoreSigning = false;
     }
 
     int run(String[] args) {
@@ -186,7 +178,7 @@
                    new PrintWriter(System.err, true));
         }
         try {
-            optionsHelper.handleOptions(this, args);
+            optionsHelper.handleOptionsNoUnhandled(this, args);
             if (options.help) {
                 optionsHelper.showHelp(PROGNAME);
                 return EXIT_OK;
@@ -200,7 +192,7 @@
                 return EXIT_OK;
             }
             if (taskHelper.getExistingImage() == null) {
-                if (options.modulePath == null || options.modulePath.isEmpty()) {
+                if (options.modulePath.isEmpty()) {
                     throw taskHelper.newBadArgs("err.modulepath.must.be.specified").showUsage(true);
                 }
                 createImage();
@@ -249,19 +241,25 @@
         plugins = plugins == null ? new PluginsConfiguration() : plugins;
 
         if (config.getModulepaths().isEmpty()) {
-            throw new Exception("Empty module paths");
+            throw new IllegalArgumentException("Empty module paths");
         }
 
-        ModuleFinder finder
-                = newModuleFinder(config.getModulepaths(), config.getLimitmods(), config.getModules());
+        ModuleFinder finder = newModuleFinder(config.getModulepaths(),
+                                              config.getLimitmods(),
+                                              config.getModules());
+
+        if (config.getModules().isEmpty()) {
+            throw new IllegalArgumentException("No modules to add");
+        }
 
         // First create the image provider
-        ImageProvider imageProvider
-                = createImageProvider(finder,
-                                      checkAddMods(config.getModules()),
-                                      config.getLimitmods(),
-                                      config.getByteOrder(),
-                                      null);
+        ImageProvider imageProvider =
+                createImageProvider(finder,
+                                    config.getModules(),
+                                    config.getLimitmods(),
+                                    config.getByteOrder(),
+                                    null,
+                                    IGNORE_SIGNING_DEFAULT);
 
         // Then create the Plugin Stack
         ImagePluginStack stack = ImagePluginConfiguration.parseConfiguration(plugins);
@@ -299,19 +297,17 @@
         }
         ModuleFinder finder
                 = newModuleFinder(options.modulePath, options.limitMods, options.addMods);
-        try {
-            options.addMods = checkAddMods(options.addMods);
-        } catch (IllegalArgumentException ex) {
+        if (options.addMods.isEmpty()) {
             throw taskHelper.newBadArgs("err.mods.must.be.specified", "--add-modules")
                     .showUsage(true);
         }
         // First create the image provider
-        ImageProvider imageProvider
-                = createImageProvider(finder,
+        ImageProvider imageProvider = createImageProvider(finder,
                         options.addMods,
                         options.limitMods,
                         options.endian,
-                        options.packagedModulesPath);
+                        options.packagedModulesPath,
+                        options.ignoreSigning);
 
         // Then create the Plugin Stack
         ImagePluginStack stack = ImagePluginConfiguration.
@@ -321,31 +317,41 @@
         stack.operate(imageProvider);
     }
 
-    private static Set<String> checkAddMods(Set<String> addMods) {
-        if (addMods.isEmpty()) {
-            throw new IllegalArgumentException("no modules to add");
-        }
-        return addMods;
-    }
+    /**
+     * Returns a module finder to find the observable modules specified in
+     * the --module-path and --limit-modules options
+     */
+    private ModuleFinder modulePathFinder() {
+        Path[] entries = options.modulePath.toArray(new Path[0]);
+        ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess()
+            .newModulePath(Runtime.version(), true, entries);
 
-    public static ModuleFinder newModuleFinder(List<Path> paths,
-                                               Set<String> limitMods,
-                                               Set<String> addMods)
-    {
-        ModuleFinder finder = ModuleFinder.of(paths.toArray(new Path[0]));
-
-        // 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);
+        if (!options.limitMods.isEmpty()) {
+            finder = limitFinder(finder, options.limitMods, Collections.emptySet());
         }
         return finder;
     }
 
+    /*
+     * Returns a module finder of the given module path that limits
+     * the observable modules to those in the transitive closure of
+     * the modules specified in {@code limitMods} plus other modules
+     * specified in the {@code roots} set.
+     */
+    public static ModuleFinder newModuleFinder(List<Path> paths,
+                                               Set<String> limitMods,
+                                               Set<String> roots)
+    {
+        Path[] entries = paths.toArray(new Path[0]);
+        ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess()
+            .newModulePath(Runtime.version(), true, entries);
+
+        // if limitmods is specified then limit the universe
+        if (!limitMods.isEmpty()) {
+            finder = limitFinder(finder, limitMods, roots);
+        }
+        return finder;
+    }
 
     private static Path toPathLocation(ResolvedModule m) {
         Optional<URI> ouri = m.reference().location();
@@ -359,7 +365,8 @@
                                                      Set<String> addMods,
                                                      Set<String> limitMods,
                                                      ByteOrder order,
-                                                     Path retainModulesPath)
+                                                     Path retainModulesPath,
+                                                     boolean ignoreSigning)
             throws IOException
     {
         if (addMods.isEmpty()) {
@@ -373,10 +380,10 @@
 
         Map<String, Path> mods = cf.modules().stream()
             .collect(Collectors.toMap(ResolvedModule::name, JlinkTask::toPathLocation));
-        return new ImageHelper(cf, mods, order, retainModulesPath);
+        return new ImageHelper(cf, mods, order, retainModulesPath, ignoreSigning);
     }
 
-    /**
+    /*
      * Returns a ModuleFinder that limits observability to the given root
      * modules, their transitive dependences, plus a set of other modules.
      */
@@ -460,36 +467,57 @@
     }
 
     private static class ImageHelper implements ImageProvider {
-
-        final Set<Archive> archives;
         final ByteOrder order;
         final Path packagedModulesPath;
+        final boolean ignoreSigning;
+        final Set<Archive> archives;
 
         ImageHelper(Configuration cf,
                     Map<String, Path> modsPaths,
                     ByteOrder order,
-                    Path packagedModulesPath) throws IOException {
-            archives = modsPaths.entrySet().stream()
+                    Path packagedModulesPath,
+                    boolean ignoreSigning) throws IOException {
+            this.order = order;
+            this.packagedModulesPath = packagedModulesPath;
+            this.ignoreSigning = ignoreSigning;
+            this.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);
+                ModularJarArchive modularJarArchive = new ModularJarArchive(module, path);
+
+                Stream<Archive.Entry> signatures = modularJarArchive.entries().filter((entry) -> {
+                    String name = entry.name().toUpperCase(Locale.ENGLISH);
+
+                    return name.startsWith("META-INF/") && name.indexOf('/', 9) == -1 && (
+                                name.endsWith(".SF") ||
+                                name.endsWith(".DSA") ||
+                                name.endsWith(".RSA") ||
+                                name.endsWith(".EC") ||
+                                name.startsWith("META-INF/SIG-")
+                            );
+                });
+
+                if (signatures.count() != 0) {
+                    if (ignoreSigning) {
+                        System.err.println(taskHelper.getMessage("warn.signing", path));
+                    } else {
+                        throw new IllegalArgumentException(taskHelper.getMessage("err.signing", path));
+                    }
+                }
+
+                return modularJarArchive;
             } 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);
+                throw new IllegalArgumentException(
+                    taskHelper.getMessage("err.not.modular.format", module, path));
             }
-            return null;
         }
 
         @Override
@@ -509,30 +537,16 @@
     }
 
     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";
-            }
-        }
+        NATIVE_LIBS("native"),
+        NATIVE_CMDS("bin"),
+        CLASSES("classes"),
+        CONFIG("conf"),
+        UNKNOWN("unknown");
 
         private final String jmodDir;
-        private final String imageDir;
 
-        Section(String jmodDir, String imageDir) {
+        Section(String jmodDir) {
             this.jmodDir = jmodDir;
-            this.imageDir = imageDir;
-        }
-
-        String imageDir() {
-            return imageDir;
         }
 
         String jmodDir() {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModularJarArchive.java	Fri Nov 11 16:44:36 2016 +0100
@@ -54,13 +54,9 @@
 
     @Override
     Entry toEntry(ZipEntry ze) {
-        if (ze.isDirectory()) {
-            return null;
-        }
-
         String name = ze.getName();
         EntryType type = toEntryType(name);
-        return new JarEntry(ze.getName(), getFileName(name), type, zipFile, ze);
+        return new JarEntry(ze.getName(), getFileName(name), type, getJarFile(), ze);
     }
 
     @Override
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/TaskHelper.java	Fri Nov 11 16:44:36 2016 +0100
@@ -47,8 +47,6 @@
 import java.util.ResourceBundle;
 import java.util.Set;
 
-import jdk.internal.module.ConfigurableModuleFinder;
-import jdk.internal.module.ConfigurableModuleFinder.Phase;
 import jdk.tools.jlink.internal.plugins.ExcludeFilesPlugin;
 import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
 import jdk.tools.jlink.plugin.Plugin;
@@ -60,6 +58,7 @@
 import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
 import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
 import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
+import jdk.internal.misc.SharedSecrets;
 
 /**
  *
@@ -162,6 +161,7 @@
         private static final String POST_PROCESS = "--post-process-path";
 
         private Layer pluginsLayer = Layer.boot();
+        private final List<Plugin> plugins;
         private String lastSorter;
         private boolean listPlugins;
         private Path existingImage;
@@ -185,9 +185,10 @@
                 pluginsLayer = createPluginsLayer(paths);
             }
 
+            plugins = PluginRepository.getPlugins(pluginsLayer);
+
             Set<String> optionsSeen = new HashSet<>();
-            for (Plugin plugin : PluginRepository.
-                    getPlugins(pluginsLayer)) {
+            for (Plugin plugin : plugins) {
                 if (!Utils.isDisabled(plugin)) {
                     addOrderedPluginOptions(plugin, optionsSeen);
                 }
@@ -199,9 +200,19 @@
                     },
                     "--plugin-module-path"));
             mainOptions.add(new PlugOption(true, (task, opt, arg) -> {
+                    for (Plugin plugin : plugins) {
+                        if (plugin.getName().equals(arg)) {
+                            pluginToMaps.remove(plugin);
+                            return;
+                        }
+                    }
+                    throw newBadArgs("err.no.such.plugin", arg);
+                },
+                "--disable-plugin"));
+            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");
+                    throw newBadArgs("err.image.must.exist");
                 }
                 existingImage = path.toAbsolutePath();
             }, true, POST_PROCESS));
@@ -466,7 +477,21 @@
             return pp;
         }
 
+        // used by jimage. Return unhandled arguments like "create", "describe".
         public List<String> handleOptions(T task, String[] args) throws BadArgs {
+            return handleOptions(task, args, true);
+        }
+
+        // used by jlink. No unhandled arguments like "create", "describe".
+        void handleOptionsNoUnhandled(T task, String[] args) throws BadArgs {
+            handleOptions(task, args, false);
+        }
+
+        // shared code that handles options for both jlink and jimage. jimage uses arguments like
+        // "create", "describe" etc. as "task names". Those arguments are unhandled here and returned
+        // as "unhandled arguments list". jlink does not want such arguments. "collectUnhandled" flag
+        // tells whether to allow for unhandled arguments or not.
+        private List<String> handleOptions(T task, String[] args, boolean collectUnhandled) throws BadArgs {
             // findbugs warning, copy instead of keeping a reference.
             command = Arrays.copyOf(args, args.length);
 
@@ -499,10 +524,10 @@
             String[] arr = new String[filteredArgs.size()];
             args = filteredArgs.toArray(arr);
 
-            List<String> rest = new ArrayList<>();
+            List<String> rest = collectUnhandled? new ArrayList<>() : null;
             // process options
             for (int i = 0; i < args.length; i++) {
-                if (!args[i].isEmpty() && args[i].charAt(0) == '-') {
+                if (args[i].charAt(0) == '-') {
                     String name = args[i];
                     PlugOption pluginOption = null;
                     Option<T> option = getOption(name);
@@ -539,7 +564,12 @@
                         i = args.length;
                     }
                 } else {
-                    rest.add(args[i]);
+                    if (collectUnhandled) {
+                        rest.add(args[i]);
+                    } else {
+                        throw new BadArgs("err.orphan.argument", args[i]).
+                            showUsage(true);
+                    }
                 }
             }
             return rest;
@@ -707,14 +737,10 @@
     }
 
     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);
-        }
+        Path[] dirs = paths.toArray(new Path[0]);
+        ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess()
+            .newModulePath(Runtime.version(), true, dirs);
 
         Configuration bootConfiguration = Layer.boot().configuration();
         try {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Fri Nov 11 16:44:36 2016 +0100
@@ -159,13 +159,6 @@
     public void configure(Map<String, String> config) {
         String mainArgument = config.get(NAME);
 
-        if ("none".equals(mainArgument)) {
-            speciesTypes = Set.of();
-            invokerTypes = Set.of();
-            dmhMethods = Map.of();
-            return;
-        }
-
         // Start with the default configuration
         Set<String> defaultBMHSpecies = defaultSpecies();
         // Expand BMH species signatures
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -62,6 +62,9 @@
 main.opt.save-opts=\
 \  --save-opts <filename>            Save jlink options in the given file
 
+main.opt.ignore-signing-information=\
+\  --ignore-signing-information      Ignore signing information in modular JARs
+
 main.msg.bug=\
 An exception has occurred in jlink. \
 Please file a bug at the Java Bug Database (http://bugreport.java.com/bugreport/) \
@@ -88,13 +91,14 @@
 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.image.must.exist=image does not exist 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.orphan.argument=orphan argument: {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}
@@ -103,5 +107,9 @@
 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}
+err.not.modular.format=selected module {0} ({1}) not in jmod or modular JAR format
+err.signing=signed modular JAR {0} is currently not supported,\
+\ use --ignore-signing-information to suppress error
+warn.signing=signed modular JAR {0} is currently not supported
+warn.invalid.arg=invalid classname or pathname not exist: {0}
 warn.split.package=package {0} defined in {1} {2}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -74,12 +74,11 @@
 exclude-jmod-section.description=\
 Specify a JMOD section to exclude
 
-generate-jli-classes.argument=<none|@filename>
+generate-jli-classes.argument=@filename
 
 generate-jli-classes.description=\
 Takes a file hinting to jlink what java.lang.invoke classes to pre-generate. If\n\
-this flag is not specified a default set of classes will be generated. To \n\
-disable pre-generation specify none as the argument
+this flag is not specified a default set of classes will be generated.
 
 installed-modules.description=Fast loading of module descriptors (always enabled)
 
@@ -144,6 +143,9 @@
 plugin.opt.plugin-module-path=\
 \  --plugin-module-path <modulepath> Custom plugin module path
 
+plugin.opt.disable-plugin=\
+\  --disable-plugin <pluginname>     Disable the plugin mentioned
+
 plugin.opt.c=\
 \  -c, --compress=<0|1|2>            Enable compression of resources\
 \n                                    More details in --list-plugins option
@@ -193,6 +195,8 @@
 main.plugin.state=\
 Functional state
 
+err.no.such.plugin=No such plugin: {0}
+
 err.provider.not.functional=The provider {0} is not functional.
 
 err.plugin.mutiple.options=More than one plugin enabled by {0} option
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Fri Nov 11 16:44:36 2016 +0100
@@ -47,6 +47,7 @@
 import java.lang.module.ResolvedModule;
 import java.net.URI;
 import java.nio.file.FileSystems;
+import java.nio.file.FileVisitOption;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
@@ -98,8 +99,6 @@
 import jdk.internal.joptsimple.ValueConverter;
 import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.misc.SharedSecrets;
-import jdk.internal.module.ConfigurableModuleFinder;
-import jdk.internal.module.ConfigurableModuleFinder.Phase;
 import jdk.internal.module.ModuleHashes;
 import jdk.internal.module.ModuleInfoExtender;
 import jdk.tools.jlink.internal.Utils;
@@ -635,7 +634,8 @@
         void processSection(JmodOutputStream out, Section section, Path top)
             throws IOException
         {
-            Files.walkFileTree(top, new SimpleFileVisitor<Path>() {
+            Files.walkFileTree(top, Set.of(FileVisitOption.FOLLOW_LINKS),
+                    Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
                 @Override
                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                     throws IOException
@@ -1298,9 +1298,7 @@
                 options.manPages = opts.valuesOf(manPages);
             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);
+                options.moduleFinder = JLMA.newModulePath(Runtime.version(), true, dirs);
             }
             if (opts.has(moduleVersion))
                 options.moduleVersion = opts.valueOf(moduleVersion);
--- a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java	Fri Nov 11 16:44:36 2016 +0100
@@ -156,6 +156,7 @@
      */
 
     @Deprecated(since = "9")
+    @SuppressWarnings("exports")
     public static JSObject getWindow(Applet applet) throws JSException {
         return ProviderLoader.callGetWindow(applet);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.localedata/share/classes/sun/text/resources/ext/BreakIteratorResources_th.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.ext;
+
+import java.util.ResourceBundle;
+import sun.util.resources.BreakIteratorResourceBundle;
+
+public class BreakIteratorResources_th extends BreakIteratorResourceBundle {
+    @Override
+    protected ResourceBundle getBreakIteratorInfo() {
+        return new BreakIteratorInfo_th();
+    }
+}
--- a/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/src/jdk.unsupported/share/classes/sun/reflect/ReflectionFactory.java	Fri Nov 11 16:44:36 2016 +0100
@@ -85,6 +85,21 @@
     }
 
     /**
+     * Returns an accessible constructor capable of creating instances
+     * of the given class, initialized by the given constructor.
+     *
+     * @param cl the class to instantiate
+     * @param constructorToCall the constructor to call
+     * @return an accessible constructor
+     */
+    public Constructor<?> newConstructorForSerialization(Class<?> cl,
+                                                         Constructor<?> constructorToCall)
+    {
+        return delegate.newConstructorForSerialization(cl,
+                                                       constructorToCall);
+    }
+
+    /**
      * Returns an accessible no-arg constructor for a class.
      * The no-arg constructor is found searching the class and its supertypes.
      *
--- a/jdk/test/ProblemList.txt	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/ProblemList.txt	Fri Nov 11 16:44:36 2016 +0100
@@ -134,8 +134,6 @@
 
 java/lang/instrument/BootClassPath/BootClassPathTest.sh         8072130 macosx-all
 
-java/lang/instrument/DaemonThread/TestDaemonThread.java         8167001 generic-all
-
 java/lang/management/MemoryMXBean/Pending.java                  8158837 generic-all
 java/lang/management/MemoryMXBean/PendingAllGC.sh               8158760 generic-all
 
@@ -186,9 +184,7 @@
 java/nio/file/WatchService/MayFlies.java                        7158947 solaris-all Solaris 11
 java/nio/file/WatchService/LotsOfEvents.java                    7158947 solaris-all Solaris 11
 
-java/nio/charset/coders/BashStreams.java                        8149712 generic-all
-
-java/nio/file/WatchService/DeleteInterference.java              8156511 linux-all
+sun/nio/cs/OLD/TestIBMDB.java                                   8167525 generic-all
 
 ############################################################################
 
@@ -223,6 +219,15 @@
 ############################################################################
 
 # jdk_sound
+javax/sound/sampled/DirectAudio/bug6372428.java        8055097 generic-all
+javax/sound/sampled/Clip/bug5070081.java               8055097 generic-all
+javax/sound/sampled/DataLine/LongFramePosition.java    8055097 generic-all
+
+javax/sound/sampled/Clip/Drain/ClipDrain.java          7062792 generic-all
+
+javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all
+
+javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java 8168881 generic-all
 
 ############################################################################
 
--- a/jdk/test/TEST.groups	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/TEST.groups	Fri Nov 11 16:44:36 2016 +0100
@@ -158,6 +158,7 @@
 
 jdk_net = \
     java/net \
+    -java/net/httpclient \
     com/sun/net/httpserver \
     sun/net \
     jdk/net
--- a/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/com/sun/corba/serialization/ObjectStreamTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -42,13 +42,8 @@
 import java.util.Objects;
 import java.util.PropertyPermission;
 import java.util.Set;
-import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 
-import javax.naming.CommunicationException;
-import javax.naming.InitialContext;
-import javax.naming.Context;
-import javax.naming.NamingException;
 import javax.rmi.CORBA.Util;
 import javax.rmi.PortableRemoteObject;
 
@@ -56,11 +51,9 @@
 import org.omg.CORBA_2_3.portable.OutputStream;
 import org.omg.CORBA_2_3.portable.InputStream;
 
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.JDKToolLauncher;
-
 import org.testng.Assert;
-import org.testng.annotations.AfterSuite;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 import org.testng.annotations.DataProvider;
 import org.testng.TestNG;
@@ -69,15 +62,13 @@
  * @test
  * @library /test/lib
  * @build jdk.test.lib.*
- * @compile  ObjectStreamTest.java  ObjectStreamTest$_Echo_Stub.java  ObjectStreamTest$_Server_Tie.java
- * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io java.corba/com.sun.corba.se.impl.activation
+ * @compile  ObjectStreamTest.java  ObjectStreamTest$_Echo_Stub.java
+ *           ObjectStreamTest$_Server_Tie.java
+ * @modules java.corba/com.sun.corba.se.impl.io java.base/java.io
+ *          java.corba/com.sun.corba.se.impl.activation
  * @summary Tests of ReflectionFactory use in IIOP Serialization
- * @run testng/othervm
- *       -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
- *       -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
- * @run testng/othervm/policy=security.policy
- *       -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
- *       -Djava.naming.provider.url=iiop://localhost:1050 ObjectStreamTest
+ * @run testng/othervm ObjectStreamTest
+ * @run testng/othervm/policy=security.policy ObjectStreamTest
  */
 
 @Test
@@ -92,12 +83,6 @@
         colorSet.add(Colors.GREEN);
     }
 
-    /**
-     * The process spawned to run orbd.
-     */
-    static Process orbdProcess;
-    static Thread orbThread;
-
     @DataProvider(name = "Objects")
     static Object[][] patterns() {
         BigInteger bigInteger = new BigInteger("8943892002309239");
@@ -141,7 +126,7 @@
      * @param value
      */
     @Test(dataProvider = "Objects")
-    static void factCheck(Serializable value) {
+    void factCheck(Serializable value) {
         Class<?> clazz = value.getClass();
         java.io.ObjectStreamClass sOSC = java.io.ObjectStreamClass.lookup(clazz);
         java.io.ObjectStreamField[] sFields = sOSC.getFields();
@@ -150,25 +135,33 @@
 
         Assert.assertEquals(sFields.length, cFields.length, "Different number of fields");
         for (int i = 0; i < sFields.length; i++) {
-            Assert.assertEquals(sFields[i].getName(), cFields[i].getName(), "different field names " + cFields[i].getName());
-            Assert.assertEquals(sFields[i].getType(), cFields[i].getType(), "different field types " + cFields[i].getName());
-            Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(), "different field typestrings " + cFields[i].getName());
+            Assert.assertEquals(sFields[i].getName(), cFields[i].getName(),
+                    "different field names " + cFields[i].getName());
+            Assert.assertEquals(sFields[i].getType(), cFields[i].getType(),
+                    "different field types " + cFields[i].getName());
+            Assert.assertEquals(sFields[i].getTypeString(), cFields[i].getTypeString(),
+                    "different field typestrings " + cFields[i].getName());
         }
 
         Assert.assertEquals(baseMethod("hasReadObjectMethod", sOSC, (Class<?>[]) null),
-                corbaMethod("hasReadObject", cOSC, (Class<?>[]) null), "hasReadObject: " + value.getClass());
+                corbaMethod("hasReadObject", cOSC, (Class<?>[]) null),
+                "hasReadObject: " + value.getClass());
 
         Assert.assertEquals(baseMethod("hasWriteObjectMethod", sOSC, (Class<?>[]) null),
-                corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null), "hasWriteObject: " + value.getClass());
+                corbaMethod("hasWriteObject", cOSC, (Class<?>[]) null),
+                "hasWriteObject: " + value.getClass());
 
         Assert.assertEquals(baseMethod("hasWriteReplaceMethod", sOSC, (Class<?>[]) null),
-                corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null), "hasWriteReplace: " + value.getClass());
+                corbaMethod("hasWriteReplaceMethod", cOSC, (Class<?>[]) null),
+                "hasWriteReplace: " + value.getClass());
 
         Assert.assertEquals(baseMethod("hasReadResolveMethod", sOSC, (Class<?>[]) null),
-                corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null), "hasReadResolve: " + value.getClass());
+                corbaMethod("hasReadResolveMethod", cOSC, (Class<?>[]) null),
+                "hasReadResolve: " + value.getClass());
 
         Assert.assertEquals(baseMethod("getSerialVersionUID", sOSC, (Class<?>[]) null),
-                corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null), "getSerialVersionUID: " + value.getClass());
+                corbaMethod("getSerialVersionUID", cOSC, (Class<?>[]) null),
+                "getSerialVersionUID: " + value.getClass());
 
     }
 
@@ -178,7 +171,7 @@
      * and deserialized using Util.readAny to equivalent objects.
      */
     @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
-    static void WriteValueObjectStreamTest01(Serializable value) throws Exception {
+    void WriteValueObjectStreamTest01(Serializable value) throws Exception {
         ORB orb = (ORB) ORB.init(new String[0], null);
 
         OutputStream out = (OutputStream) orb.create_output_stream();
@@ -193,15 +186,43 @@
     /**
      * Test that objects can be echoed to a server and come back equivalent.
      */
-    @Test(dataProvider = "Objects", enabled = false, dependsOnMethods = {"factCheck"})
-    static void echoObjects(Serializable value) throws Exception {
-        Context initialNamingContext = Server.init();
-        Echo echo = (Echo) PortableRemoteObject.narrow(
-                initialNamingContext.lookup(Server.serverID), Echo.class);
+    @Test(dataProvider = "Objects", enabled = true, dependsOnMethods = {"factCheck"})
+    void echoObjects(Serializable value) throws Exception {
+        Echo echo = getEchoStub();
         Object actual = echo.echo(value);
         checkEquals(actual, value);
     }
 
+
+    /**
+     * Initialize the ORB and the singleton Echo server stub.
+     * @return the stub for the Echo server.
+     * @throws RemoteException if an error occurs
+     */
+    synchronized Echo getEchoStub() throws RemoteException {
+        if (echoStub == null) {
+            ORB orb = (ORB) ORB.init(new String[0], null);
+            Echo server = new Server();
+            echoStub = (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(server);
+            echoStub.connect(orb);
+        }
+        return (Echo)echoStub;
+    }
+
+    /**
+     * The stub for the Echo Server class. Initialized on first use.
+     */
+    private javax.rmi.CORBA.Stub echoStub;
+
+    /**
+     * After all the tests run shutdown the orb.
+     */
+    @AfterClass
+    void shutdownOrb() {
+        ORB orb = (ORB) ORB.init(new String[0], null);
+        orb.shutdown(true);
+    }
+
     /**
      * Check if the value and result are equals, with some tests depending on the type.
      * @param expected the expected value
@@ -209,15 +230,18 @@
      */
     static void checkEquals(Object actual, Object expected) {
         Class<?> cl = expected.getClass();
-        Assert.assertEquals(actual.getClass(), cl, "type of value not equal to class of result");
+        Assert.assertEquals(actual.getClass(), cl,
+                "type of value not equal to class of result");
         try {
             if (cl.isArray() || !(cl.getDeclaredMethod("equals", cl) == null)) {
                 Assert.assertEquals(actual, expected, "echo'd object not equal");
             } else {
-                Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+                Assert.assertEquals(toString(actual), toString(expected),
+                        "toString values not equal");
             }
         } catch (NoSuchMethodException ex) {
-            Assert.assertEquals(toString(actual), toString(expected), "toString values not equal");
+            Assert.assertEquals(toString(actual), toString(expected),
+                    "toString values not equal");
         }
     }
 
@@ -301,7 +325,9 @@
      * @param argClasses method arguments
      * @return the value returned from invoking the method
      */
-    static Object corbaMethod(String methodName, com.sun.corba.se.impl.io.ObjectStreamClass osc, Class<?>... argClasses) {
+    static Object corbaMethod(String methodName,
+                              com.sun.corba.se.impl.io.ObjectStreamClass osc,
+                              Class<?>... argClasses) {
         Class<?> oscClass = com.sun.corba.se.impl.io.ObjectStreamClass.class;
 
         try {
@@ -325,7 +351,8 @@
      * @param argClasses method arguments
      * @return the value returned from invoking the method
      */
-    static Object baseMethod(String methodName, java.io.ObjectStreamClass osc, Class<?>... argClasses) {
+    static Object baseMethod(String methodName, java.io.ObjectStreamClass osc,
+                             Class<?>... argClasses) {
         Class<?> oscClass = java.io.ObjectStreamClass.class;
 
         try {
@@ -342,7 +369,7 @@
     }
 
     /**
-     * Simple echo interface to check serialization/deserialization.
+     * Simple echo interface to check IIOP serialization/deserialization.
      */
     interface Echo extends Remote {
         Object echo(Object obj) throws RemoteException;
@@ -350,12 +377,6 @@
 
     static class Server extends PortableRemoteObject implements Echo {
 
-        public static final String serverID = "ObjectStreamTestServer";
-
-        private static Context initialNamingContext;
-
-        private static Server server;
-
         public Server() throws RemoteException {
             super();
         }
@@ -363,63 +384,8 @@
         public Object echo(Object obj) {
             return obj;
         }
-
-
-        public static Context init() {
-            if (initialNamingContext == null) {
-                try {
-                    startOrbd();
-                    Thread.sleep(5000L);        // Give it 5 seconds
-                } catch (Exception eex) {
-                    throw new RuntimeException("Orbd", eex);
-                }
-                for (int i = 0; i < 1; i++) {
-                    try {
-                        Thread.sleep(1L);
-                        initialNamingContext = new InitialContext();
-                        server = new Server();
-                        initialNamingContext.rebind(serverID, server);
-                    } catch (CommunicationException | InterruptedException cex) {
-                        System.out.printf("retry #%d sec: ex: %s%n", i, cex);
-                    } catch (NamingException ex) {
-                        throw new RuntimeException("can't initialize naming context", ex);
-                    } catch (RemoteException rex) {
-                        throw new RuntimeException("can't initialize server", rex);
-                    }
-                }
-            }
-            if (initialNamingContext == null) {
-                Assert.fail("Can't initialize the Orb, no naming context");
-            }
-            return initialNamingContext;
-        }
     }
 
-    static void startOrbd() throws Exception {
-        System.out.println("\nStarting orbd with NS port 1050 ");
-        JDKToolLauncher orbdLauncher = JDKToolLauncher.create("orbd")
-                        .addToolArg("-ORBInitialHost").addToolArg("localhost")
-                        .addToolArg("-ORBInitialPort").addToolArg("1050");
-
-        System.out.println("ObjectStreamTest: Executing: " + Arrays.asList(orbdLauncher.getCommand()));
-        ProcessBuilder pb = new ProcessBuilder(orbdLauncher.getCommand());
-
-        pb.redirectError(ProcessBuilder.Redirect.INHERIT);
-        orbdProcess = pb.start();
-    }
-
-    @AfterSuite
-    static void killOrbd() throws Exception {
-        if (orbdProcess != null) {
-            orbdProcess.destroyForcibly();
-            orbdProcess.waitFor();
-            System.out.printf("destroyed orbd, pid: %d, exitValue: %d%n",
-                    orbdProcess.getPid(), orbdProcess.exitValue());
-        }
-    }
-
-
-
     // Main can be used to run the tests from the command line with only testng.jar.
     @SuppressWarnings("raw_types")
     @Test(enabled = false)
--- a/jdk/test/com/sun/jdi/InterfaceMethodsTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/com/sun/jdi/InterfaceMethodsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,7 +25,8 @@
  *  @test
  *  @bug 8031195
  *  @bug 8071657
- *  @summary  JDI: Add support for static and default methods in interfaces
+ *  @bug 8165827
+ *  @summary  JDI: Add support for static, private and default methods in interfaces
  *
  *  @modules jdk.jdi
  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
@@ -35,11 +36,13 @@
 import com.sun.jdi.*;
 import com.sun.jdi.event.*;
 import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
 
 public class InterfaceMethodsTest extends TestScaffold {
     private static final int RESULT_A = 1;
-    private static final int RESULT_B = 1;
-    private static final int RESULT_TARGET = 1;
+    private static final int RESULT_B = 2;
+    private static final int RESULT_TARGET = 3;
 
     static interface InterfaceA {
         static int staticMethodA() {
@@ -62,7 +65,10 @@
             System.out.println("-InterfaceA: default interface method C-");
             return RESULT_A;
         }
-
+        private int privateMethodA() {
+            System.out.println("-InterfaceA: private interface method A-");
+            return RESULT_A;
+        }
         int implementedMethod();
     }
 
@@ -76,16 +82,18 @@
             System.out.println("-InterfaceB: default interface method D-");
             return RESULT_B;
         }
-
         static int staticMethodB() {
             System.out.println("-InterfaceB: overridden static interface method B-");
             return RESULT_B;
         }
-
         static int staticMethodC() {
             System.out.println("-InterfaceB: static interface method C-");
             return RESULT_B;
         }
+        private int privateMethodB() {
+            System.out.println("-InterfaceB: private interface method B-");
+            return RESULT_B;
+        }
     }
 
     final static class TargetClass implements InterfaceB {
@@ -102,7 +110,7 @@
 
         @Override
         public int defaultMethodB() {
-            System.out.println("-TargetClass: overridden default interface method D");
+            System.out.println("-TargetClass: overridden default interface method B");
 
             return RESULT_TARGET;
         }
@@ -169,9 +177,18 @@
     }
 
     private void testInterfaceA(ObjectReference ref) {
+
+        ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
+
+        /* Private method calls */
+
+        Method m = testLookup(ifaceClass, "privateMethodA", "()I", true, null); // should succeed
+
+        testInvokePos(m, ref, vm().mirrorOf(RESULT_A), false);
+        testInvokePos(m, ref, vm().mirrorOf(RESULT_A), true);
+
         // Test non-virtual calls on InterfaceA
 
-        ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEA_NAME).get(0);
         /* Default method calls */
 
         // invoke the InterfaceA's "defaultMethodA"
@@ -185,39 +202,48 @@
 
         // "defaultMethodD" from InterfaceB is not accessible from here
         testInvokeNeg(ifaceClass, ref, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B),
-                "Attempted to invoke non-existing method");
+                      "Attempted to invoke non-existing method");
 
-        // trying to invoke the asbtract method "implementedMethod"
+        // non-virtual invoke of the abstract method "implementedMethod" fails
         testInvokeNeg(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(TARGET_CLASS_NAME),
-                "Invocation of non-default methods is not supported");
-
+                      "Invocation of abstract methods is not supported");
 
         /* Static method calls */
 
-        // invoke interface static method A
+        // invoke static interface method A
         testInvokePos(ifaceClass, null, "staticMethodA", "()I", vm().mirrorOf(RESULT_A));
 
         // invoking static method A on the instance fails because static method A is
         // not inherited by TargetClass.
         testInvokeNeg(ifaceClass, ref, "staticMethodA", "()I", vm().mirrorOf(RESULT_A),
-                "Invalid MethodID");
+                      "Invalid MethodID");
 
-        // invoke interface static method B
+        // invoke static interface method B
         testInvokePos(ifaceClass, null, "staticMethodB", "()I", vm().mirrorOf(RESULT_A));
 
         // invoking static method B on the instance fails because static method B is
         // not inherited by TargetClass.
         testInvokeNeg(ifaceClass, ref, "staticMethodB", "()I", vm().mirrorOf(RESULT_A),
-                "Invalid MethodID");
+                      "Invalid MethodID");
 
         // try to invoke a virtual method
-        testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_A), true);
+        testInvokePos(ifaceClass, ref, "implementedMethod", "()I", vm().mirrorOf(RESULT_TARGET), true);
     }
 
     private void testInterfaceB(ObjectReference ref) {
         // Test non-virtual calls on InterfaceB
         ReferenceType ifaceClass = (ReferenceType)vm().classesByName(INTERFACEB_NAME).get(0);
 
+        /* private method calls */
+
+        /* These should fail but won't because of JDK-8167416
+        testLookup(ifaceClass, "privateMethodA", "()I", true, NoSuchMethodError.class); // should fail
+        testLookup(ifaceClass, "privateMethodA", "()I", false, NoSuchMethodError.class); // should fail
+        */
+        Method m = testLookup(ifaceClass, "privateMethodB", "()I", true, null); // should succeed
+        testInvokePos(m, ref, vm().mirrorOf(RESULT_B), false);
+        testInvokePos(m, ref, vm().mirrorOf(RESULT_B), true);
+
         /* Default method calls */
 
         // invoke the inherited "defaultMethodA"
@@ -267,19 +293,21 @@
     private void testImplementationClass(ReferenceType targetClass, ObjectReference thisObject) {
         // Test invocations on the implementation object
 
+        // Note: private interface calls have already been tested
+
         /* Default method calls */
 
         // "defaultMethodA" is accessible and not overridden
-        testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_TARGET));
+        testInvokePos(targetClass, thisObject, "defaultMethodA", "()I", vm().mirrorOf(RESULT_A));
 
         // "defaultMethodB" is accessible and overridden in TargetClass
         testInvokePos(targetClass, thisObject, "defaultMethodB", "()I", vm().mirrorOf(RESULT_TARGET));
 
         // "defaultMethodC" is accessible and overridden in InterfaceB
-        testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_TARGET));
+        testInvokePos(targetClass, thisObject, "defaultMethodC", "()I", vm().mirrorOf(RESULT_B));
 
         // "defaultMethodD" is accessible
-        testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_TARGET));
+        testInvokePos(targetClass, thisObject, "defaultMethodD", "()I", vm().mirrorOf(RESULT_B));
 
 
         /* Non-default instance method calls */
@@ -314,11 +342,16 @@
                 "Static interface methods are not inheritable");
     }
 
+    // Non-virtual invocation
     private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
                                String methodSig, Value value) {
         testInvokePos(targetClass, ref, methodName, methodSig, value, false);
     }
 
+    // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+    // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+    // expected return value.
+    // Should succeed.
     private void testInvokePos(ReferenceType targetClass, ObjectReference ref, String methodName,
                                String methodSig, Value value, boolean virtual) {
         logInvocation(ref, methodName, methodSig, targetClass);
@@ -331,11 +364,31 @@
         }
     }
 
+    // Invoke the given Method on the given object (for instance methods)
+    // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+    // expected return value.
+    // Should succeed.
+    private void testInvokePos(Method method, ObjectReference ref, Value value, boolean virtual) {
+        logInvocation(ref, method.name(), method.signature(), method.declaringType());
+        try {
+            invoke(method.declaringType(), ref, method, value, virtual);
+            System.err.println("--- PASSED");
+        } catch (Exception e) {
+            System.err.println("--- FAILED");
+            failure("FAILED: Invocation failed with error message " + e.getLocalizedMessage());
+        }
+    }
+
+    // Non-virtual invocation - with lookup in targetClass
     private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
                                String methodSig, Value value, String msg) {
         testInvokeNeg(targetClass, ref, methodName, methodSig, value, msg, false);
     }
 
+    // Lookup the named method in the targetClass and invoke on the given object (for instance methods)
+    // using virtual, or non-virtual, invocation mode as specified, for instance methods. Verify the
+    // expected return value.
+    // Should fail - with msg decribing why failure was expected
     private void testInvokeNeg(ReferenceType targetClass, ObjectReference ref, String methodName,
                                String methodSig, Value value, String msg, boolean virtual) {
         logInvocation(ref, methodName, methodSig, targetClass);
@@ -350,12 +403,17 @@
     }
 
     private void invoke(ReferenceType targetClass, ObjectReference ref, String methodName,
-                        String methodSig, Value value, boolean virtual)
-    throws Exception {
+                        String methodSig, Value value, boolean virtual) throws Exception {
+
         Method method = getMethod(targetClass, methodName, methodSig);
         if (method == null) {
             throw new Exception("Can't find method: " + methodName  + " for class = " + targetClass);
         }
+        invoke(targetClass, ref, method, value, virtual);
+    }
+
+    private void invoke(ReferenceType targetClass, ObjectReference ref, Method method,
+                        Value value, boolean virtual) throws Exception {
 
         println("Invoking " + (method.isAbstract() ? "abstract " : " ") + "method: " + method);
         println(method.declaringType().toString());
@@ -365,7 +423,7 @@
             if (virtual) {
                 returnValue = invokeVirtual(ref, method);
             } else {
-                returnValue = invokeInstance(ref, method);
+                returnValue = invokeNonVirtual(ref, method);
             }
         } else {
             returnValue = invokeStatic(targetClass, method);
@@ -387,7 +445,7 @@
         }
     }
 
-    private Value invokeInstance(ObjectReference ref, Method method) throws Exception {
+    private Value invokeNonVirtual(ObjectReference ref, Method method) throws Exception {
         return ref.invokeMethod(mainThread, method, Collections.emptyList(), ObjectReference.INVOKE_NONVIRTUAL);
     }
 
@@ -449,4 +507,58 @@
                     methodName + methodSig);
         }
     }
+
+    private Method testLookup(ReferenceType targetClass, String methodName, String methodSig,
+                              boolean declaredOnly, Class<?> expectedException) {
+
+        System.err.println("Looking up " + targetClass.name() + "." + methodName + methodSig);
+        try {
+            Method m = declaredOnly ?
+                lookupDeclaredMethod(targetClass, methodName, methodSig) :
+                lookupMethod(targetClass, methodName, methodSig);
+
+            if (expectedException == null) {
+                System.err.println("--- PASSED");
+                return m;
+            }
+            else {
+                System.err.println("--- FAILED");
+                failure("FAILED: lookup succeeded but expected exception "
+                        + expectedException.getSimpleName());
+                return null;
+            }
+        }
+        catch (Throwable t) {
+            if (t.getClass() != expectedException) {
+                System.err.println("--- FAILED");
+                failure("FAILED: got exception " + t + " but expected exception "
+                        + expectedException.getSimpleName());
+                return null;
+            }
+            else {
+                System.err.println("--- PASSED");
+                return null;
+            }
+        }
+    }
+
+    private Method lookupMethod(ReferenceType targetClass, String methodName, String methodSig) {
+        List methods = targetClass.allMethods();
+        Iterator iter = methods.iterator();
+        while (iter.hasNext()) {
+            Method method = (Method)iter.next();
+            if (method.name().equals(methodName) &&
+                method.signature().equals(methodSig)) {
+                return method;
+            }
+        }
+        throw new NoSuchMethodError();
+    }
+
+    private Method lookupDeclaredMethod(ReferenceType targetClass, String methodName, String methodSig) {
+        Method m = findMethod(targetClass, methodName, methodSig);
+        if (m == null)
+            throw new NoSuchMethodError();
+        return m;
+    }
 }
--- a/jdk/test/com/sun/jndi/dns/Parser.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/com/sun/jndi/dns/Parser.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,6 +26,7 @@
  * @bug 8035105
  * @summary DNS resource record parsing
  * @modules jdk.naming.dns/com.sun.jndi.dns
+ * @compile --add-modules jdk.naming.dns Parser.java
  */
 
 import com.sun.jndi.dns.ResourceRecord;
--- a/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/com/sun/jndi/rmi/registry/RegistryContext/ContextWithNullProperties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,7 +28,7 @@
  * @modules jdk.naming.rmi/com.sun.jndi.rmi.registry java.rmi/sun.rmi.registry
  *     java.rmi/sun.rmi.server java.rmi/sun.rmi.transport java.rmi/sun.rmi.transport.tcp
  * @library ../../../../../../java/rmi/testlibrary
- * @build TestLibrary
+ * @compile --add-modules jdk.naming.rmi ContextWithNullProperties.java
  * @run main ContextWithNullProperties
  */
 
--- a/jdk/test/java/awt/FileDialog/8017487/bug8017487.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/FileDialog/8017487/bug8017487.java	Fri Nov 11 16:44:36 2016 +0100
@@ -22,7 +22,7 @@
  */
 
 /* @test
-   @bug 8017487
+   @bug 8017487 8167988
    @summary filechooser in Windows-Libraries folder: columns are mixed up
    @author Semyon Sadetsky
    @modules java.desktop/sun.awt.shell
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/RequestFocusByCause/RequestFocusByCauseTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/*
+  @test
+  @bug 8154434
+  @summary Open the request focus methods of the java.awt.Component which accept
+           FocusEvent.Cause
+  @run main RequestFocusByCauseTest
+*/
+
+import java.awt.*;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+
+public class RequestFocusByCauseTest {
+    static boolean success;
+
+    public static void main(String[] args) throws Exception {
+        testRequestFocusCause();
+        testRequestFocusTemporaryCause();
+        testRequestFocusInWindowCause();
+        System.out.println("ok");
+    }
+
+    private static void testRequestFocusCause() throws AWTException {
+        Frame frame = new Frame();
+        Component c = new Button();
+        frame.add(new Button());
+        frame.add(c);
+        c.addFocusListener(new FocusListener() {
+            @Override
+            public void focusGained(FocusEvent e) {
+                success = e.getCause() == FocusEvent.Cause.UNEXPECTED;
+            }
+
+            @Override
+            public void focusLost(FocusEvent e) {}
+        });
+        Robot robot = new Robot();
+
+        try {
+            frame.setVisible(true);
+            robot.waitForIdle();
+            robot.delay(200);
+            success = false;
+
+            c.requestFocus(FocusEvent.Cause.UNEXPECTED);
+            robot.waitForIdle();
+            robot.delay(200);
+            if(!success) {
+                throw new RuntimeException("request failed");
+            }
+        } finally {
+            frame.dispose();
+        }
+    }
+
+    private static void testRequestFocusTemporaryCause() throws AWTException {
+        Frame frame = new Frame();
+        frame.add(new Button() {
+            @Override
+            protected boolean requestFocus(boolean temporary,
+                                                       FocusEvent.Cause cause) {
+                success = cause == FocusEvent.Cause.ROLLBACK;
+                return super.requestFocus(temporary, cause);
+            }
+        });
+        Component c = new Button() {
+            @Override
+            public void requestFocus() {
+                super.requestFocus();
+                setFocusable(false);
+            }
+        };
+        frame.add(c);
+        Robot robot = new Robot();
+
+        try {
+            frame.setVisible(true);
+            robot.waitForIdle();
+            robot.delay(200);
+
+            success = false;
+            c.requestFocus();
+            robot.waitForIdle();
+            robot.delay(200);
+
+
+            if(!success) {
+                throw new RuntimeException("rollback request is not triggered");
+            }
+        } finally {
+            frame.dispose();
+        }
+    }
+
+    private static void testRequestFocusInWindowCause() throws AWTException {
+        Frame frame = new Frame();
+        Component c = new Button();
+        frame.add(new Button());
+        frame.add(c);
+        c.addFocusListener(new FocusListener() {
+            @Override
+            public void focusGained(FocusEvent e) {
+                success = e.getCause() == FocusEvent.Cause.UNEXPECTED;
+            }
+
+            @Override
+            public void focusLost(FocusEvent e) {
+            }
+        });
+        Robot robot = new Robot();
+
+        try {
+            frame.setVisible(true);
+            robot.waitForIdle();
+            robot.delay(200);
+            success = false;
+
+            c.requestFocusInWindow(FocusEvent.Cause.UNEXPECTED);
+            robot.waitForIdle();
+            robot.delay(200);
+            if (!success) {
+                throw new RuntimeException("request in window failed");
+            }
+        } finally {
+            frame.dispose();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Frame/SetIconImagesCrashTest/SetIconImagesCrashTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
+ * @key headful
+ * @bug 8166980
+ * @summary Test to check Window.setIconImages() does not result in crash when
+ * a frame is shown
+ * @run main/othervm SetIconImagesCrashTest
+ * @run main/othervm -Dsun.java2d.uiScale=2 SetIconImagesCrashTest
+ */
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Window;
+import java.awt.Frame;
+import java.util.List;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import javax.swing.SwingUtilities;
+
+public class SetIconImagesCrashTest {
+
+    public static void main(String[] args) throws Exception {
+
+        List<BufferedImage> imageList = new ArrayList<BufferedImage>();
+        imageList.add(new BufferedImage(200, 200,
+                                BufferedImage.TYPE_BYTE_BINARY));
+
+        for (int i = 0; i < 10; i++) {
+            Frame f = new Frame();
+            test(f, imageList);
+        }
+    }
+
+    public static void test(final Window window,
+            final List<BufferedImage> imageList) throws Exception {
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                for (BufferedImage image : imageList) {
+                    Graphics graphics = image.getGraphics();
+                    graphics.setColor(Color.RED);
+                    graphics.fillRect(
+                            0, 0, image.getWidth(), image.getHeight());
+                    graphics.dispose();
+                }
+
+                window.setIconImages(imageList);
+                window.setSize(200, 200);
+                window.setVisible(true);
+            }
+        });
+
+        while (!window.isVisible()) {
+            Thread.sleep((long) (20));
+        }
+
+        Thread.sleep((long) (50));
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                window.setVisible(false);
+                window.dispose();
+            }
+        });
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/FullScreen/CurrentDisplayModeTest/CurrentDisplayModeTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8022810
+ * @summary Device.getDisplayMode() doesn't report refresh rate on Linux in case
+ *          of dual screen
+ * @run main CurrentDisplayModeTest
+ */
+
+import java.awt.*;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class CurrentDisplayModeTest {
+    public static void main(String[] args) {
+        GraphicsDevice[] screenDevices = GraphicsEnvironment.
+                               getLocalGraphicsEnvironment().getScreenDevices();
+        for (GraphicsDevice screenDevice : screenDevices) {
+            DisplayMode currentMode = screenDevice.getDisplayMode();
+            System.out.println("current mode " + currentMode);
+            Set<DisplayMode> set = new HashSet<>(
+                                 Arrays.asList(screenDevice.getDisplayModes()));
+            if (!set.contains(currentMode)) {
+                throw new RuntimeException("Mode " + currentMode +
+                        " is not found in the modes list " + set);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Graphics/IncorrectFractionalClip/IncorrectFractionalClip.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.geom.Area;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+import javax.imageio.ImageIO;
+
+import static java.awt.RenderingHints.KEY_STROKE_CONTROL;
+import static java.awt.RenderingHints.VALUE_STROKE_PURE;
+import static java.awt.image.BufferedImage.TYPE_INT_ARGB;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8167310
+ * @summary The clip should be correct if the scale is fractional
+ */
+public final class IncorrectFractionalClip {
+
+    private static final int SIZE = 128;
+
+    public static final Color RED = new Color(255, 0, 0, 100);
+
+    public static final Color GREEN = new Color(0, 255, 0, 100);
+
+    public static final Color WHITE = new Color(0, 0, 0, 0);
+
+    public static final BasicStroke STROKE = new BasicStroke(2.01f);
+
+    private static final double[] SCALES = {
+            0.1, 0.25, 0.4, 0.5, 0.6, 1, 1.4, 1.5, 1.6, 2.0, 2.4, 2.5, 2.6, 4
+    };
+
+    static BufferedImage bi;
+
+    static BufferedImage gold;
+
+    static BufferedImage redI;
+
+    static BufferedImage greenI;
+
+    public static void main(final String[] args) throws Exception {
+        bi = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+        gold = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+        redI = createImage(RED);
+        greenI = createImage(GREEN);
+
+        System.out.println("Will test fillRect");
+        test(0, true);
+        test(0, false);
+        System.out.println("Will test DrawImage");
+        test(1, true);
+        test(1, false);
+        System.out.println("Will test drawLine");
+        test(2, true);
+        test(2, false);
+    }
+
+    /**
+     * This method draws/fills a number of rectangle, images and lines. Each
+     * time the clip is set as one vertical/horizontal line. The resulted image
+     * should not have any overlapping of different colors. The clip is set via
+     * rectangle(test) and via shape(gold). Both images should be identical.
+     */
+    private static void test(final int testId, final boolean horiz)
+            throws Exception {
+        for (final double scale : SCALES) {
+            // Initialize the test and gold images
+            drawToImage(testId, horiz, scale, bi, /* Rectangle */ false);
+            drawToImage(testId, horiz, scale, gold, /* Shape */ true);
+            validate(bi, gold, testId);
+        }
+    }
+
+    private static void drawToImage(int testId, boolean horiz, double scale,
+                                    BufferedImage image, boolean shape) {
+        Graphics2D g = image.createGraphics();
+        g.setComposite(AlphaComposite.Src);
+        g.setColor(WHITE);
+        g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
+        g.setComposite(AlphaComposite.SrcOver);
+        g.setRenderingHint(KEY_STROKE_CONTROL, VALUE_STROKE_PURE);
+
+        // set the scale in one direction
+        if (horiz) {
+            g.scale(scale, 1);
+        } else {
+            g.scale(1, scale);
+        }
+        // cover all units in the user space to touch all pixels in the
+        // image after transform
+        final int destSize = (int) Math.ceil(SIZE / scale);
+        final int destW;
+        final int destH;
+        if (horiz) {
+            destW = destSize;
+            destH = SIZE;
+        } else {
+            destW = SIZE;
+            destH = destSize;
+        }
+        for (int step = 0; step < destSize; ++step) {
+            if (horiz) {
+                if (!shape) {
+                    g.setClip(step, 0, 1, SIZE);
+                } else{
+                    g.setClip(new Area(new Rectangle(step, 0, 1, SIZE)));
+                }
+            } else {
+                if (!shape) {
+                    g.setClip(0, step, SIZE, 1);
+                }else{
+                    g.setClip(new Area(new Rectangle(0, step, SIZE, 1)));
+                }
+            }
+            switch (testId) {
+                case 0:
+                    g.setColor(step % 2 == 0 ? RED : GREEN);
+                    g.fillRect(0, 0, destW, destH);
+                    break;
+                case 1:
+                    g.drawImage(step % 2 == 0 ? redI : greenI, 0, 0,
+                                destW, destH, null);
+                    break;
+                case 2:
+                    g.setColor(step % 2 == 0 ? RED : GREEN);
+                    g.setStroke(STROKE);
+                    if (horiz) {
+                        g.drawLine(step, 0, step, SIZE);
+                    } else {
+                        g.drawLine(0, step, SIZE, step);
+                    }
+                    break;
+                default:
+                    throw new RuntimeException();
+            }
+        }
+        g.dispose();
+    }
+
+    private static void validate(final BufferedImage bi, BufferedImage gold,
+                                 final int testID) throws Exception {
+        for (int x = 0; x < SIZE; ++x) {
+            for (int y = 0; y < SIZE; ++y) {
+                int rgb = bi.getRGB(x, y);
+                int goldRGB = gold.getRGB(x, y);
+                if ((rgb != GREEN.getRGB() && rgb != RED.getRGB())
+                        || rgb != goldRGB) {
+                    ImageIO.write(bi, "png", new File("image.png"));
+                    ImageIO.write(gold, "png", new File("gold.png"));
+                    throw new RuntimeException("Test failed.");
+                }
+            }
+        }
+    }
+
+    private static BufferedImage createImage(final Color color) {
+        BufferedImage bi = new BufferedImage(SIZE, SIZE, TYPE_INT_ARGB);
+        Graphics2D g = bi.createGraphics();
+        g.setComposite(AlphaComposite.Src);
+        g.setColor(color);
+        g.fillRect(0, 0, bi.getWidth(), bi.getHeight());
+        g.dispose();
+        return bi;
+    }
+}
--- a/jdk/test/java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/KeyboardFocusmanager/TypeAhead/SubMenuShowTest/SubMenuShowTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013, 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
@@ -23,7 +23,7 @@
 
 /*
   test
-  @bug       6380743
+  @bug       6380743 8158380
   @summary   Submenu should be shown by mnemonic key press.
   @author    anton.tarasov@...: area=awt.focus
   @run       applet SubMenuShowTest.html
@@ -55,6 +55,8 @@
 
     public void init() {
         robot = Util.createRobot();
+        robot.setAutoDelay(200);
+        robot.setAutoWaitForIdle(true);
 
         // Create instructions for the user here, as well as set up
         // the environment -- set the layout manager, add buttons,
@@ -85,35 +87,24 @@
             });
 
         frame.setVisible(true);
-        Util.waitForIdle(robot);
 
         boolean isMacOSX = (OSInfo.getOSType() == OSInfo.OSType.MACOSX);
         if (isMacOSX) {
             robot.keyPress(KeyEvent.VK_CONTROL);
-            robot.delay(20);
         }
         robot.keyPress(KeyEvent.VK_ALT);
-        robot.delay(20);
         robot.keyPress(KeyEvent.VK_F);
-        robot.delay(20);
         robot.keyRelease(KeyEvent.VK_F);
-        robot.delay(20);
         robot.keyRelease(KeyEvent.VK_ALT);
+
         if (isMacOSX) {
             robot.keyRelease(KeyEvent.VK_CONTROL);
-            robot.delay(20);
         }
-        Util.waitForIdle(robot);
 
         robot.keyPress(KeyEvent.VK_M);
-        robot.delay(20);
         robot.keyRelease(KeyEvent.VK_M);
-        Util.waitForIdle(robot);
-
         robot.keyPress(KeyEvent.VK_SPACE);
-        robot.delay(20);
         robot.keyRelease(KeyEvent.VK_SPACE);
-        Util.waitForIdle(robot);
 
         if (!Util.waitForCondition(activated, 2000)) {
             throw new TestFailedException("a submenu wasn't activated by mnemonic key press");
--- a/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/List/ActionEventTest/ActionEventTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
 /*
  * @test
  * @key headful
- * @bug 6191390
+ * @bug 6191390 8158380
  * @summary Verify that ActionEvent is received with correct modifiers set.
  * @run main ActionEventTest
  */
@@ -45,6 +45,8 @@
     public ActionEventTest() {
         try {
             robot = new Robot();
+            robot.setAutoDelay(100);
+            robot.setAutoWaitForIdle(true);
         } catch(AWTException e) {
             throw new RuntimeException(e.getMessage());
         }
@@ -56,7 +58,6 @@
         setLayout(new FlowLayout());
         pack();
         setVisible(true);
-        robot.waitForIdle();
     }
 
     void performTest() {
@@ -86,11 +87,9 @@
         // Press Enter on list item, to generate action event.
         robot.keyPress(KeyEvent.VK_ENTER);
         robot.keyRelease(KeyEvent.VK_ENTER);
-        robot.waitForIdle();
         robot.keyRelease(KeyEvent.VK_ALT);
         robot.keyRelease(KeyEvent.VK_SHIFT);
         robot.keyRelease(KeyEvent.VK_CONTROL);
-        robot.waitForIdle();
     }
 
     public static void main(String args[]) {
--- a/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.html	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +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.
--->
-
-<html>
-<!--  
-  @test
-  @bug 6401700 6412803
-  @requires (os.family != "windows")
-  @summary Tests that modal dialog is shown on the screen and 
-iconified/restored correctly if its parent window is invisible
-  @author artem.ananiev: area=awt.modal
-  @run applet/manual=yesno InvisibleParentTest.html
-  -->
-<head>
-<title> InvisibleParentTest </title>
-</head>
-<body>
-
-<h1>InvisibleParentTest<br>Bug ID: 6401700, 6412803</h1>
-
-<p> See the dialog box (usually in upper left corner) for instructions</p>
-
-<APPLET CODE="InvisibleParentTest.class" WIDTH=200 HEIGHT=200></APPLET>
-</body>
-</html>
--- a/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,214 +22,187 @@
  */
 
 /*
-  test
-  @bug 6401700 6412803
-  @summary Tests that modal dialog is shown on the screen and
-iconified/restored correctly if some of its blocked windows are invisible
-  @author artem.ananiev: area=awt.modal
-  @run applet/manual=yesno InvisibleParentTest.html
-*/
-
-import java.applet.Applet;
-import java.awt.BorderLayout;
-import java.awt.Button;
-import java.awt.Component;
+ * @test
+ * @key headful
+ * @bug 6401700 6412803 8058950
+ * @summary  Tests that modal dialog is shown on the screen and
+ * iconified/restored correctly if some of its blocked windows are invisible
+ * @requires (os.family == "linux" | os.family == "solaris")
+ * @run main/manual InvisibleParentTest
+ */
 import java.awt.Dialog;
 import java.awt.Frame;
-import java.awt.TextArea;
-import java.awt.Window;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+public class InvisibleParentTest {
 
-public class InvisibleParentTest extends Applet
-{
-    public void init()
-    {
-        setLayout(new BorderLayout());
+    public static void main(String args[]) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+        TestUI test = new TestUI(latch);
+
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    test.createUI();
+                } catch (Exception ex) {
+                    throw new RuntimeException("Exception while creating test UI");
+                }
+            }
+        });
+
+        boolean status = latch.await(5, TimeUnit.MINUTES);
 
-        String[] instructions =
-        {
-            "If your system is Windows, press PASS button.",
-            "When the test starts two windows should appear: frame G1 and",
-            "    dialog D1. Another one frame F1 should be minimized.",
-            "    If the dialog is not shown (minimizied), press FAIL button.",
-            "Then minimize frame G1 and restore F1. If the dialog D1 is not",
-            "    restored together with F1, press FAIL, else PASS"
-        };
-        Sysout.createDialogWithInstructions( instructions );
+        if (!status) {
+            System.out.println("Test timed out.");
+        }
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    test.disposeUI();
+                } catch (Exception ex) {
+                    throw new RuntimeException("Exception while disposing test UI");
+                }
+            }
+        });
+
+        if (test.testResult == false) {
+            throw new RuntimeException("Test Failed.");
+        }
+    }
+}
+
+class TestUI {
+
+    private static JFrame mainFrame;
+    private static JPanel mainControlPanel;
+
+    private static JTextArea instructionTextArea;
+
+    private static JPanel resultButtonPanel;
+    private static JButton passButton;
+    private static JButton failButton;
+
+    private static GridBagLayout layout;
+    private final CountDownLatch latch;
+    public boolean testResult = false;
+
+    public TestUI(CountDownLatch latch) throws Exception {
+        this.latch = latch;
     }
 
-    public void start ()
-    {
-        Button b;
+    public final void createUI() throws Exception {
+
+        mainFrame = new JFrame("InvisibleParentTest");
+        mainFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
+
+        layout = new GridBagLayout();
+        mainControlPanel = new JPanel(layout);
+        resultButtonPanel = new JPanel(layout);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        // Create Test instructions
+        String instructions
+                = "When the test starts two windows should appear: frame G1 and\n"
+                + "    dialog D1. Another one frame F1 should be minimized.\n"
+                + "    If the dialog is not shown (minimizied), press FAIL button.\n"
+                + "Then minimize frame G1 and restore F1. If the dialog D1 is not\n"
+                + "    restored together with F1, press FAIL, else PASS";
 
-        setSize (200,200);
-        setVisible(true);
-        validate();
+        instructionTextArea = new JTextArea();
+        instructionTextArea.setText(instructions);
+        instructionTextArea.setEditable(false);
+        instructionTextArea.setBorder(BorderFactory.
+                createTitledBorder("Test Instructions"));
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(instructionTextArea, gbc);
+
+        // Create resultButtonPanel with Pass, Fail buttons
+        passButton = new JButton("Pass");
+        passButton.setActionCommand("Pass");
+        passButton.addActionListener((ActionEvent e) -> {
+            System.out.println("Pass Button pressed!");
+            testResult = true;
+            latch.countDown();
 
-        Component c = this;
-        while ((c != null) && !(c instanceof Window))
-        {
-            c = c.getParent();
-        }
-        if (c != null)
-        {
-            ((Window)c).setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
-        }
+        });
+
+        failButton = new JButton("Fail");
+        failButton.setActionCommand("Fail");
+        failButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                System.out.println("Fail Button pressed!");
+                testResult = false;
+                latch.countDown();
+            }
+        });
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        resultButtonPanel.add(passButton, gbc);
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        resultButtonPanel.add(failButton, gbc);
 
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        mainControlPanel.add(resultButtonPanel, gbc);
+
+        mainFrame.add(mainControlPanel);
+
+        mainFrame.pack();
+        mainFrame.setVisible(true);
+
+        // Create AWT frames and modal dialog
+        createAWTComponents();
+    }
+
+    public void disposeUI() {
+        mainFrame.setVisible(false);
+        mainFrame.dispose();
+    }
+
+    private void createAWTComponents() {
         Frame f1 = new Frame("F1");
         f1.setBounds(100, 300, 100, 100);
         f1.setVisible(true);
+
+        try {
+            Thread.sleep(500);
+        } catch (Exception ex) {
+        }
+
         f1.setExtendedState(Frame.ICONIFIED);
 
         Frame g1 = new Frame("G1");
         g1.setBounds(150, 350, 100, 100);
         g1.setVisible(true);
 
-        final Dialog d1 = new Dialog((Frame)null, "D1", Dialog.ModalityType.APPLICATION_MODAL);
+        final Dialog d1 = new Dialog((Frame) null, "D1", Dialog.ModalityType.APPLICATION_MODAL);
         d1.setBounds(200, 400, 100, 100);
-        new Thread(new Runnable()
-        {
-            public void run()
-            {
+        new Thread(new Runnable() {
+            public void run() {
                 d1.setVisible(true);
             }
         }).start();
     }
 }
 
-/****************************************************
- Standard Test Machinery
- DO NOT modify anything below -- it's a standard
-  chunk of code whose purpose is to make user
-  interaction uniform, and thereby make it simpler
-  to read and understand someone else's test.
- ****************************************************/
-
-/**
- This is part of the standard test machinery.
- It creates a dialog (with the instructions), and is the interface
-  for sending text messages to the user.
- To print the instructions, send an array of strings to Sysout.createDialog
-  WithInstructions method.  Put one line of instructions per array entry.
- To display a message for the tester to see, simply call Sysout.println
-  with the string to be displayed.
- This mimics System.out.println but works within the test harness as well
-  as standalone.
- */
-
-class Sysout
-{
-    private static TestDialog dialog;
-
-    public static void createDialogWithInstructions( String[] instructions )
-    {
-        dialog = new TestDialog( new Frame(), "Instructions" );
-        dialog.printInstructions( instructions );
-        dialog.setVisible(true);
-        println( "Any messages for the tester will display here." );
-    }
-
-    public static void createDialog( )
-    {
-        dialog = new TestDialog( new Frame(), "Instructions" );
-        String[] defInstr = { "Instructions will appear here. ", "" } ;
-        dialog.printInstructions( defInstr );
-        dialog.setVisible(true);
-        println( "Any messages for the tester will display here." );
-    }
-
-
-    public static void printInstructions( String[] instructions )
-    {
-        dialog.printInstructions( instructions );
-    }
-
-
-    public static void println( String messageIn )
-    {
-        dialog.displayMessage( messageIn );
-    }
-
-}// Sysout  class
-
-/**
-  This is part of the standard test machinery.  It provides a place for the
-   test instructions to be displayed, and a place for interactive messages
-   to the user to be displayed.
-  To have the test instructions displayed, see Sysout.
-  To have a message to the user be displayed, see Sysout.
-  Do not call anything in this dialog directly.
-  */
-class TestDialog extends Dialog
-{
-
-    TextArea instructionsText;
-    TextArea messageText;
-    int maxStringLength = 80;
-
-    //DO NOT call this directly, go through Sysout
-    public TestDialog( Frame frame, String name )
-    {
-        super( frame, name );
-        setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
-        int scrollBoth = TextArea.SCROLLBARS_BOTH;
-        instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
-        add( "North", instructionsText );
-
-        messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
-        add("Center", messageText);
-
-        pack();
-
-        setVisible(true);
-    }// TestDialog()
-
-    //DO NOT call this directly, go through Sysout
-    public void printInstructions( String[] instructions )
-    {
-        //Clear out any current instructions
-        instructionsText.setText( "" );
-
-        //Go down array of instruction strings
-
-        String printStr, remainingStr;
-        for( int i=0; i < instructions.length; i++ )
-        {
-            //chop up each into pieces maxSringLength long
-            remainingStr = instructions[ i ];
-            while( remainingStr.length() > 0 )
-            {
-                //if longer than max then chop off first max chars to print
-                if( remainingStr.length() >= maxStringLength )
-                {
-                    //Try to chop on a word boundary
-                    int posOfSpace = remainingStr.
-                        lastIndexOf( ' ', maxStringLength - 1 );
-
-                    if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
-
-                    printStr = remainingStr.substring( 0, posOfSpace + 1 );
-                    remainingStr = remainingStr.substring( posOfSpace + 1 );
-                }
-                //else just print
-                else
-                {
-                    printStr = remainingStr;
-                    remainingStr = "";
-                }
-
-                instructionsText.append( printStr + "\n" );
-
-            }// while
-
-        }// for
-
-    }//printInstructions()
-
-    //DO NOT call this directly, go through Sysout
-    public void displayMessage( String messageIn )
-    {
-        messageText.append( messageIn + "\n" );
-        System.out.println(messageIn);
-    }
-
-}// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Robot/WaitForIdleSyncroizedOnString/WaitForIdleSyncroizedOnString.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+import java.awt.Robot;
+import java.util.concurrent.CountDownLatch;
+
+import javax.swing.SwingUtilities;
+
+/**
+ * @test
+ * @key headful
+ * @bug 8166673
+ */
+public final class WaitForIdleSyncroizedOnString {
+
+    private static final String WAIT_LOCK = "Wait Lock";
+
+    private static volatile boolean passed = true;
+
+    public static void main(final String[] args) throws Exception {
+        CountDownLatch go = new CountDownLatch(1);
+        Robot r = new Robot();
+        SwingUtilities.invokeLater(() -> System.out.println("some work"));
+        Thread t = new Thread(() -> {
+            synchronized (WAIT_LOCK) {
+                go.countDown();
+                try {
+                    Thread.sleep(30000);
+                    passed = false;
+                } catch (InterruptedException e) {
+                    System.out.println("e = " + e);
+                }
+            }
+        });
+        t.start();
+        go.await();
+        r.waitForIdle();
+        t.interrupt();
+        if (!passed) {
+            throw new RuntimeException("Test failed");
+        }
+    }
+}
--- a/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -43,7 +43,7 @@
 /**
  * @test
  * @key headful
- * @bug 8043869 8075244 8078082 8145173
+ * @bug 8043869 8075244 8078082 8145173 8151787
  * @summary Tests the HiDPI splash screen support for windows and MAC
  * @modules java.desktop/sun.java2d
  * @run main MultiResolutionSplashTest GENERATE_IMAGES
@@ -56,27 +56,20 @@
 
     private static final int IMAGE_WIDTH = 300;
     private static final int IMAGE_HEIGHT = 200;
+    private static boolean isMac;
 
-    private static final ImageInfo[] macTests = {
+    static {
+        isMac = System.getProperty("os.name").contains("OS X");
+    }
+    private static final ImageInfo[] tests = {
         new ImageInfo("splash1.png", "splash1@2x.png", Color.BLUE, Color.GREEN),
         new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK),
         new ImageInfo("splash3.", "splash3@2x.", Color.YELLOW, Color.RED)
     };
-    private static final ImageInfo[] windowsTests = {
-        new ImageInfo("splash1.png", "splash1.scale-120.png", Color.BLUE, Color.GREEN),
-        new ImageInfo("splash2", "splash2.scale-120", Color.WHITE, Color.BLACK),
-        new ImageInfo("splash3.", "splash3.scale-120.", Color.YELLOW, Color.RED)
-    };
-    private static ImageInfo[] tests;
 
     public static void main(String[] args) throws Exception {
 
         String test = args[0];
-        tests = windowsTests;
-        String osName = System.getProperty("os.name");
-        if (osName.contains("OS X")) {
-            tests = macTests;
-        }
         switch (test) {
             case "GENERATE_IMAGES":
                 generateImages();
@@ -104,12 +97,10 @@
         Rectangle splashBounds = splashScreen.getBounds();
         int screenX = (int) splashBounds.getCenterX();
         int screenY = (int) splashBounds.getCenterY();
-
         if (splashBounds.width != IMAGE_WIDTH) {
             throw new RuntimeException(
                     "SplashScreen#getBounds has wrong width");
         }
-
         if (splashBounds.height != IMAGE_HEIGHT) {
             throw new RuntimeException(
                     "SplashScreen#getBounds has wrong height");
@@ -117,7 +108,6 @@
 
         Robot robot = new Robot();
         Color splashScreenColor = robot.getPixelColor(screenX, screenY);
-
         float scaleFactor = getScaleFactor();
         Color testColor = (1 < scaleFactor) ? test.color2x : test.color1x;
 
@@ -129,7 +119,6 @@
 
     static void testFocus() throws Exception {
 
-        System.out.println("Focus Test!");
         Robot robot = new Robot();
         robot.setAutoDelay(50);
 
@@ -150,18 +139,18 @@
 
         frame.dispose();
 
-        if(!textField.getText().equals("ab")){
+        if (!textField.getText().equals("ab")) {
             throw new RuntimeException("Focus is lost!");
         }
     }
 
-    static boolean compare(Color c1, Color c2){
+    static boolean compare(Color c1, Color c2) {
         return compare(c1.getRed(), c2.getRed())
                 && compare(c1.getGreen(), c2.getGreen())
                 && compare(c1.getBlue(), c2.getBlue());
     }
 
-    static boolean compare(int n, int m){
+    static boolean compare(int n, int m) {
         return Math.abs(n - m) <= 50;
     }
 
@@ -177,10 +166,7 @@
             public void paint(Graphics g) {
                 float scaleFactor = 1;
                 if (g instanceof SunGraphics2D) {
-                    scaleFactor = (float)GraphicsEnvironment.
-                            getLocalGraphicsEnvironment().
-                            getDefaultScreenDevice().getDefaultConfiguration().
-                            getDefaultTransform().getScaleX();
+                    scaleFactor = getScreenScaleFactor();
                 }
                 scaleFactors[0] = scaleFactor;
                 dialog.setVisible(false);
@@ -197,23 +183,30 @@
     static void generateImages() throws Exception {
         for (ImageInfo test : tests) {
             generateImage(test.name1x, test.color1x, 1);
-            generateImage(test.name2x, test.color2x, 2);
+            generateImage(test.name2x, test.color2x, getScreenScaleFactor());
         }
     }
 
-    static void generateImage(String name, Color color, int scale) throws Exception {
+    static void generateImage(String name, Color color, float scale) throws Exception {
         File file = new File(name);
         if (file.exists()) {
             return;
         }
-        BufferedImage image = new BufferedImage(scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT,
-                BufferedImage.TYPE_INT_RGB);
+        BufferedImage image = new BufferedImage((int) (scale * IMAGE_WIDTH),
+                (int) (scale * IMAGE_HEIGHT), BufferedImage.TYPE_INT_RGB);
         Graphics g = image.getGraphics();
         g.setColor(color);
-        g.fillRect(0, 0, scale * IMAGE_WIDTH, scale * IMAGE_HEIGHT);
+        g.fillRect(0, 0, (int) (scale * IMAGE_WIDTH), (int) (scale * IMAGE_HEIGHT));
         ImageIO.write(image, "png", file);
     }
 
+    static float getScreenScaleFactor() {
+        return (float) GraphicsEnvironment.
+                getLocalGraphicsEnvironment().
+                getDefaultScreenDevice().getDefaultConfiguration().
+                getDefaultTransform().getScaleX();
+    }
+
     static class ImageInfo {
 
         final String name1x;
@@ -223,9 +216,32 @@
 
         public ImageInfo(String name1x, String name2x, Color color1x, Color color2x) {
             this.name1x = name1x;
-            this.name2x = name2x;
+            if (!isMac) {
+                float scale = getScreenScaleFactor();
+                StringBuffer buff = new StringBuffer();
+                if (scale - (int) scale > 0) {
+                    buff.append("@").append((int) (scale * 100)).append("pct");
+                } else {
+                    buff.append("@").append((int) scale).append("x");
+                }
+                StringBuffer buffer = new StringBuffer();
+                String[] splitStr = name1x.split("\\.");
+                if (splitStr.length == 2) {
+                    this.name2x = buffer.append(splitStr[0]).append(buff)
+                            .append(".").append(splitStr[1]).toString();
+                } else {
+                    if (name1x.indexOf(".") > 0) {
+                        this.name2x = buffer.append(splitStr[0]).append(buff).append(".").toString();
+                    } else {
+                        this.name2x = buffer.append(splitStr[0]).append(buff).toString();
+                    }
+                }
+            } else {
+                this.name2x = name2x;
+            }
             this.color1x = color1x;
             this.color2x = color2x;
         }
     }
 }
+
--- a/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -44,7 +44,7 @@
 import javax.imageio.ImageIO;
 
 /**
- * @test @bug 8145174
+ * @test @bug 8145174 8151787
  * @summary HiDPI splash screen support on Linux
  * @modules java.desktop/sun.java2d
  * @run main UnixMultiResolutionSplashTest
@@ -55,9 +55,9 @@
     private static final int IMAGE_HEIGHT = 200;
     private static int inx = 0;
     private static final ImageInfo[] tests = {
-        new ImageInfo("splash1.png", "splash1.java-scale2x.png", Color.BLUE, Color.GREEN),
-        new ImageInfo("splash2", "splash2.java-scale2x", Color.WHITE, Color.BLACK),
-        new ImageInfo("splash3.", "splash3.java-scale2x.", Color.YELLOW, Color.RED)
+        new ImageInfo("splash1.png", "splash1@200pct.png", Color.BLUE, Color.GREEN),
+        new ImageInfo("splash2", "splash2@2x", Color.WHITE, Color.BLACK),
+        new ImageInfo("splash3.", "splash3@200pct.", Color.YELLOW, Color.RED)
     };
 
     public static void main(String[] args) throws Exception {
@@ -96,8 +96,6 @@
         Rectangle splashBounds = splashScreen.getBounds();
         int screenX = (int) splashBounds.getCenterX();
         int screenY = (int) splashBounds.getCenterY();
-        System.out.println(screenX);
-        System.out.println(screenY);
         Robot robot = new Robot();
         Color splashScreenColor = robot.getPixelColor(screenX, screenY);
 
--- a/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/TrayIcon/DragEventSource/DragEventSource.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, 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
@@ -23,8 +23,8 @@
 
 /*
   @test
-  @bug 6565779
-  @library ../../../regtesthelpers
+  @bug 6565779 8168292
+  @library ../../regtesthelpers
   @compile DragEventSource.java
   @summary Exception if source of some event is TrayIcon
   @author Andrei Dmitriev: area=awt.tray
@@ -38,9 +38,19 @@
  * instance as source.
  */
 
-import java.awt.*;
-import java.awt.event.*;
-import java.awt.image.*;
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.FileDialog;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.Image;
+import java.awt.Panel;
+import java.awt.SystemTray;
+import java.awt.TextArea;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
 
 public class DragEventSource
 {
@@ -81,11 +91,10 @@
 
         String[] instructions =
         {
-            "Use see a Frame with a button in it.",
-            "Press the button. FileDialog should appear.",
-            "Drag the mouse from the Tray icon to FileDialog ",
-            "using left mouse button.",
-            "If exception happens, the test fails.",
+            "Click 'Open file dialog' button. FileDialog should appear.",
+            "Using left mouse button,",
+            "Drag the mouse from the Tray icon to FileDialog.",
+            "If exception is thrown, the test fails.",
             "Otherwise, pass."
         };
 
--- a/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/TrayIcon/TrayIconEventModifiers/TrayIconEventModifiersTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -21,7 +21,11 @@
  * questions.
  */
 
-import java.awt.*;
+import java.awt.EventQueue;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
@@ -31,9 +35,10 @@
 
 /*
  * @test
+ * @bug 8161473
+ * @key headful
  * @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
@@ -213,6 +218,7 @@
                 mousePressed = false;
 
                 robot.keyPress(keyTypes[j]);
+                robot.waitForIdle();
                 robot.mousePress(buttonTypes[i]);
 
                 if (! mousePressed) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Window/ChangeWindowResizabilty/ChangeWindowResizabiltyTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @key headful
+   @bug      8166897
+   @summary  Some font overlap in the Optionpane dialog.
+   @run      main ChangeWindowResizabiltyTest
+*/
+
+import java.awt.Component;
+import java.awt.Dialog;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.Robot;
+
+public class ChangeWindowResizabiltyTest {
+    public static void main(String[] args) throws Exception {
+        Robot robot = new Robot();
+        for(int i = 0; i < 10; i++) {
+            Dialog dialog = new Dialog((Frame) null);
+            Component panel = new Panel();
+            panel.setPreferredSize(new Dimension(200, 100));
+            dialog.add(panel);
+            dialog.pack();
+            dialog.setVisible(true);
+
+            dialog.setResizable(false);
+            robot.waitForIdle();
+            robot.delay(200);
+
+            System.out.println(panel.getLocationOnScreen());
+            System.out.println(dialog.getLocationOnScreen());
+            if (panel.getLocationOnScreen().y <
+                       dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+                dialog.dispose();
+                throw new RuntimeException(
+                        "Wrong content position after setResizable(false)");
+            }
+
+            dialog.setResizable(true);
+            robot.waitForIdle();
+            robot.delay(200);
+            System.out.println(panel.getLocationOnScreen());
+            System.out.println(dialog.getLocationOnScreen());
+            if (panel.getLocationOnScreen().y <
+                    dialog.getLocationOnScreen().y + dialog.getInsets().top) {
+                dialog.dispose();
+                throw new RuntimeException(
+                        "Wrong content position after setResizable(true)");
+            }
+
+            dialog.dispose();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/KeyEvent/RobotCrash/RobotCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
+ * @key headful
+ * @bug 8165555
+ * @summary VM crash after creating Robot second time and accessing key codes in
+ *          single JVM mode.
+ * @run main RobotCrash
+ */
+import java.awt.Frame;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import javax.swing.SwingUtilities;
+
+public class RobotCrash implements Runnable {
+
+    private Frame frame;
+
+    public void robotKeyPressTest() throws Exception {
+
+        SwingUtilities.invokeAndWait(() -> {
+            frame = new Frame();
+            frame.setSize(300, 300);
+            frame.setVisible(true);
+        });
+
+        Robot robot = new Robot();
+        robot.waitForIdle();
+        Point pt = frame.getLocationOnScreen();
+        robot.mouseMove(((int) pt.getX() + frame.getWidth()) / 2,
+                ((int) pt.getY() + frame.getHeight()) / 2);
+        robot.waitForIdle();
+        robot.mousePress(InputEvent.BUTTON1_MASK);
+        robot.waitForIdle();
+        robot.mouseRelease(InputEvent.BUTTON1_MASK);
+        robot.waitForIdle();
+        robot.keyPress(KeyEvent.VK_ENTER);
+        robot.waitForIdle();
+        robot.keyRelease(KeyEvent.VK_ENTER);
+        robot.waitForIdle();
+
+        SwingUtilities.invokeAndWait(() -> {
+            frame.dispose();
+        });
+    }
+
+    @Override
+    public void run() {
+        try {
+            robotKeyPressTest();
+        } catch (Exception e) {
+            throw new RuntimeException("Test Failed" + e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        for (int i = 0; i < 10; i++) {
+            Thread t1 = new Thread(new RobotCrash());
+            t1.start();
+            t1.join();
+            Thread t2 = new Thread(new RobotCrash());
+            t2.start();
+            t2.join();
+            Thread.sleep(1000);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/jdk/TestJDKAWTUtils.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8167126
+ */
+import java.awt.BorderLayout;
+import java.awt.Font;
+import java.awt.Rectangle;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
+
+public class TestJDKAWTUtils {
+
+    static JFrame f;
+    public static void main(String[] args) throws Exception {
+
+        SwingUtilities.invokeAndWait(() -> {
+            f = new JFrame("test");
+            JPanel p = new JPanel();
+            JButton b = new JButton("Hello");
+            b.setFont(new Font(Font.DIALOG, Font.PLAIN, 80));
+            p.setLayout(new BorderLayout());
+            p.add("Center", b);
+            f.getContentPane().add(p);
+            f.pack();
+            f.setVisible(true);
+            Rectangle r = new Rectangle(0, 0, 50, 50);
+            jdk.awt.AWTUtils.setComponentMixingCutoutShape(b, r);
+        });
+        Thread.sleep(2000);
+        SwingUtilities.invokeAndWait(() -> f.dispose());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/LinearGradientPrintingTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
+ * @bug 8162796
+ * @summary  Verifies if LinearGradientPaint is printed in osx
+ * @run main/manual LinearGradientPrintingTest
+ */
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.LinearGradientPaint;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class LinearGradientPrintingTest extends Component implements Printable {
+    private static Thread mainThread;
+    private static boolean testPassed;
+    private static boolean testGeneratedInterrupt;
+    private static JFrame f = null;
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                //createUI();
+                doTest(LinearGradientPrintingTest::createUI);
+            }
+        });
+        mainThread = Thread.currentThread();
+        try {
+            Thread.sleep(120000);
+        } catch (InterruptedException e) {
+            if (!testPassed && testGeneratedInterrupt) {
+                throw new RuntimeException("LinearGradientPaint did not print");
+            }
+        }
+        if (!testGeneratedInterrupt) {
+            throw new RuntimeException("user has not executed the test");
+        }
+    }
+
+    public static void createUI() {
+        f = new JFrame("LinearGradient Printing Test");
+        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        final LinearGradientPrintingTest gpt = new LinearGradientPrintingTest();
+        Container c = f.getContentPane();
+        c.add(BorderLayout.CENTER, gpt);
+
+        final JButton print = new JButton("Print");
+        print.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                PrinterJob job = PrinterJob.getPrinterJob();
+                job.setPrintable(gpt);
+                final boolean doPrint = job.printDialog();
+                if (doPrint) {
+                    try {
+                        job.print();
+                    } catch (PrinterException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        });
+        c.add(print, BorderLayout.SOUTH);
+
+        f.pack();
+        f.setVisible(true);
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(500,500);
+    }
+
+    public void paint(Graphics g) {
+        doPaint((Graphics2D)g);
+    }
+
+    public int print( Graphics graphics, PageFormat format, int index ) {
+        Graphics2D g2d = (Graphics2D)graphics;
+        g2d.translate(format.getImageableX(), format.getImageableY());
+        doPaint(g2d);
+        return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
+    }
+
+    static final float DIM = 100;
+    public void doPaint(Graphics2D g2d) {
+
+        g2d.translate(DIM*0.2, DIM*0.2);
+        Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2);
+        Point2D.Double p1 = new Point2D.Double(0.0, 0.0);
+        Point2D.Double p2 = new Point2D.Double(DIM/2.0, DIM/2.0);
+
+        // LinearGradientPaint
+        //g2d.translate(DIM*2.2, 0);
+        Color colors[] =  { Color.red, Color.blue} ;
+        float fractions[]  = { 0.0f, 1.0f };
+
+        LinearGradientPaint lgp =
+           new LinearGradientPaint(p1, p2, fractions, colors,
+              LinearGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(lgp);
+        g2d.fill(s);
+
+        g2d.translate(DIM*2.2, 0);
+        Color colors1[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float fractions1[]  = { 0.0f, 0.3f, 0.6f, 1.0f };
+
+        LinearGradientPaint lgp1 =
+           new LinearGradientPaint(p1, p2, fractions1, colors1,
+              LinearGradientPaint.CycleMethod.REFLECT);
+        g2d.setPaint(lgp1);
+        g2d.fill(s);
+
+        g2d.translate(-DIM*2.2, DIM*2.2);
+        Color colors2[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float fractions2[]  = { 0.0f, 0.3f, 0.6f, 1.0f };
+
+        LinearGradientPaint lgp2 =
+           new LinearGradientPaint(p1, p2, fractions2, colors2,
+              LinearGradientPaint.CycleMethod.REPEAT);
+        g2d.setPaint(lgp2);
+        g2d.fill(s);
+    }
+
+    public static synchronized void pass() {
+        testPassed = true;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    public static synchronized void fail() {
+        testPassed = false;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    private static void doTest(Runnable action) {
+        String description
+                = " A LinearGradientPaint graphics will be shown on console.\n"
+                + " The same graphics is sent to printer.\n"
+                + " Please verify if LinearGradientPaint shading is printed.\n"
+                + " If none is printed, press FAIL else press PASS";
+
+        final JDialog dialog = new JDialog();
+        dialog.setTitle("printSelectionTest");
+        JTextArea textArea = new JTextArea(description);
+        textArea.setEditable(false);
+        final JButton testButton = new JButton("Start Test");
+        final JButton passButton = new JButton("PASS");
+        passButton.setEnabled(false);
+        passButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            pass();
+        });
+        final JButton failButton = new JButton("FAIL");
+        failButton.setEnabled(false);
+        failButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            fail();
+        });
+        testButton.addActionListener((e) -> {
+            testButton.setEnabled(false);
+            action.run();
+            passButton.setEnabled(true);
+            failButton.setEnabled(true);
+        });
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(textArea, BorderLayout.CENTER);
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(testButton);
+        buttonPanel.add(passButton);
+        buttonPanel.add(failButton);
+        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+        dialog.add(mainPanel);
+
+        dialog.pack();
+        dialog.setVisible(true);
+        dialog.addWindowListener(new WindowAdapter() {
+           @Override
+            public void windowClosing(WindowEvent e) {
+                System.out.println("main dialog closing");
+                testGeneratedInterrupt = false;
+                mainThread.interrupt();
+            }
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/RadialGradientPrintingTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8162796
+ * @summary  Verifies if RadialGradientPaint is printed in osx
+ * @run main/manual RadialGradientPrintingTest
+ */
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.RadialGradientPaint;
+import java.awt.Shape;
+import java.awt.event.ActionEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import static java.awt.print.Printable.NO_SUCH_PAGE;
+import static java.awt.print.Printable.PAGE_EXISTS;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+public class RadialGradientPrintingTest extends Component implements Printable {
+    private static Thread mainThread;
+    private static boolean testPassed;
+    private static boolean testGeneratedInterrupt;
+    private static JFrame f = null;
+
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                //createUI();
+                doTest(RadialGradientPrintingTest::createUI);
+            }
+        });
+        mainThread = Thread.currentThread();
+        try {
+            Thread.sleep(120000);
+        } catch (InterruptedException e) {
+            if (!testPassed && testGeneratedInterrupt) {
+                throw new RuntimeException("LinearGradientPaint did not print");
+            }
+        }
+        if (!testGeneratedInterrupt) {
+            throw new RuntimeException("user has not executed the test");
+        }
+    }
+
+    public static void createUI() {
+        f = new JFrame("RadialGradient Printing Test");
+        f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+        final RadialGradientPrintingTest gpt = new RadialGradientPrintingTest();
+        Container c = f.getContentPane();
+        c.add(BorderLayout.CENTER, gpt);
+
+        final JButton print = new JButton("Print");
+        print.addActionListener(new AbstractAction() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                PrinterJob job = PrinterJob.getPrinterJob();
+                job.setPrintable(gpt);
+                final boolean doPrint = job.printDialog();
+                if (doPrint) {
+                    try {
+                        job.print();
+                    } catch (PrinterException ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            }
+        });
+        c.add(print, BorderLayout.SOUTH);
+
+        f.pack();
+        f.setVisible(true);
+    }
+
+    public Dimension getPreferredSize() {
+        return new Dimension(500,500);
+    }
+
+    public void paint(Graphics g) {
+        doPaint((Graphics2D)g);
+    }
+
+    public int print( Graphics graphics, PageFormat format, int index ) {
+        Graphics2D g2d = (Graphics2D)graphics;
+        g2d.translate(format.getImageableX(), format.getImageableY());
+        doPaint(g2d);
+        return index == 0 ? PAGE_EXISTS : NO_SUCH_PAGE;
+    }
+
+    static final float DIM = 100;
+    public void doPaint(Graphics2D g2d) {
+
+        g2d.translate(DIM*0.2, DIM*0.2);
+        Shape s = new Rectangle2D.Float(0, 0, DIM*2, DIM*2);
+
+        // RadialGradientPaint
+        Point2D centre = new Point2D.Float(DIM/2.0f, DIM/2.0f);
+        float radius = DIM/2.0f;
+        Point2D focus = new Point2D.Float(DIM/3.0f, DIM/3.0f);
+        float stops[] = {0.0f, 1.0f};
+        Color colors[] =  { Color.red, Color.white} ;
+
+        RadialGradientPaint rgp =
+           new RadialGradientPaint(centre, radius, focus, stops, colors,
+              RadialGradientPaint.CycleMethod.NO_CYCLE);
+        g2d.setPaint(rgp);
+        g2d.fill(s);
+
+        g2d.translate(DIM*2.2, 0);
+        Color colors1[] =  { Color.red, Color.blue, Color.green} ;
+        float stops1[] = {0.0f, 0.5f, 1.0f};
+        RadialGradientPaint rgp1 =
+           new RadialGradientPaint(centre, radius, focus, stops1, colors1,
+              RadialGradientPaint.CycleMethod.REFLECT);
+        g2d.setPaint(rgp1);
+        g2d.fill(s);
+
+        g2d.translate(-DIM*2.2, DIM*2.2);
+        Color colors2[] =  { Color.red, Color.blue, Color.green, Color.white} ;
+        float stops2[] = {0.0f, 0.3f, 0.6f, 1.0f};
+        RadialGradientPaint rgp2 =
+           new RadialGradientPaint(centre, radius, focus, stops2, colors2,
+              RadialGradientPaint.CycleMethod.REPEAT);
+        g2d.setPaint(rgp2);
+        g2d.fill(s);
+
+    }
+
+    public static synchronized void pass() {
+        testPassed = true;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    public static synchronized void fail() {
+        testPassed = false;
+        testGeneratedInterrupt = true;
+        mainThread.interrupt();
+    }
+
+    private static void doTest(Runnable action) {
+        String description
+                = " A RadialGradientPaint graphics will be shown on console.\n"
+                + " The same graphics is sent to printer.\n"
+                + " Please verify if RadialGradientPaint shading is printed.\n"
+                + " If none is printed, press FAIL else press PASS";
+
+        final JDialog dialog = new JDialog();
+        dialog.setTitle("printSelectionTest");
+        JTextArea textArea = new JTextArea(description);
+        textArea.setEditable(false);
+        final JButton testButton = new JButton("Start Test");
+        final JButton passButton = new JButton("PASS");
+        passButton.setEnabled(false);
+        passButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            pass();
+        });
+        final JButton failButton = new JButton("FAIL");
+        failButton.setEnabled(false);
+        failButton.addActionListener((e) -> {
+            f.dispose();
+            dialog.dispose();
+            fail();
+        });
+        testButton.addActionListener((e) -> {
+            testButton.setEnabled(false);
+            action.run();
+            passButton.setEnabled(true);
+            failButton.setEnabled(true);
+        });
+        JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(textArea, BorderLayout.CENTER);
+        JPanel buttonPanel = new JPanel(new FlowLayout());
+        buttonPanel.add(testButton);
+        buttonPanel.add(passButton);
+        buttonPanel.add(failButton);
+        mainPanel.add(buttonPanel, BorderLayout.SOUTH);
+        dialog.add(mainPanel);
+
+        dialog.pack();
+        dialog.setVisible(true);
+        dialog.addWindowListener(new WindowAdapter() {
+           @Override
+            public void windowClosing(WindowEvent e) {
+                System.out.println("main dialog closing");
+                testGeneratedInterrupt = false;
+                mainThread.interrupt();
+            }
+        });
+    }
+
+}
--- a/jdk/test/java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/awt/security/WarningWindowDisposeTest/WarningWindowDisposeTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,9 +23,9 @@
 
 /*
   @test
-  @bug 8037776
+  @key headful
+  @bug 8037776 8167288
   @summary tests that the WarningWindow is properly disposed
-  @author Petr Pchelko
   @library ../../regtesthelpers/process
   @build ProcessResults ProcessCommunicator
   @run main WarningWindowDisposeTest
@@ -45,13 +45,17 @@
     public static void main(String[] args) {
         final AtomicBoolean passed = new AtomicBoolean(false);
         new Thread(() -> {
-            try {
-                Thread.sleep(5000);
-            } catch (InterruptedException e) {
-                throw new RuntimeException("Test FAILED!", e);
-            }
-            if (!passed.get()) {
-                throw new RuntimeException("Test FAILED! The child process never exits");
+            for (int trial = 0; trial < 5; ++trial) {
+                try {
+                    Thread.sleep(2000);
+                } catch (InterruptedException e) {
+                    throw new RuntimeException("Test FAILED!", e);
+                }
+                if (passed.get()) {
+                    break;
+                } else if (trial == 4) {
+                    throw new RuntimeException("Child process never exits");
+                }
             }
         }, "TimeoutThread").start();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/FilePermission/FilePermissionCollectionMerge.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8168127
+ * @summary FilePermissionCollection merges incorrectly
+ * @modules java.base/sun.security.util
+ * @library /test/lib
+ */
+
+import sun.security.util.FilePermCompat;
+import java.io.FilePermission;
+import java.security.Permissions;
+import jdk.test.lib.Asserts;
+
+public class FilePermissionCollectionMerge {
+
+    public static void main(String[] args) throws Exception {
+        test("x");
+        test("x/*");
+        test("x/-");
+        test("*");
+        test("-");
+        test("/x");
+        test("/x/*");
+        test("/x/-");
+    }
+
+    static void test(String arg) {
+
+        FilePermission fp1 = new FilePermission(arg, "read");
+        FilePermission fp2 = (FilePermission)
+                FilePermCompat.newPermUsingAltPath(fp1);
+        FilePermission fp3 = (FilePermission)
+                FilePermCompat.newPermPlusAltPath(fp1);
+
+        // All 3 are different
+        Asserts.assertNE(fp1, fp2);
+        Asserts.assertNE(fp1.hashCode(), fp2.hashCode());
+
+        Asserts.assertNE(fp1, fp3);
+        Asserts.assertNE(fp1.hashCode(), fp3.hashCode());
+
+        Asserts.assertNE(fp2, fp3);
+        Asserts.assertNE(fp2.hashCode(), fp3.hashCode());
+
+        // The plus one implies the other 2
+        Asserts.assertTrue(fp3.implies(fp1));
+        Asserts.assertTrue(fp3.implies(fp2));
+
+        // The using one different from original
+        Asserts.assertFalse(fp2.implies(fp1));
+        Asserts.assertFalse(fp1.implies(fp2));
+
+        // FilePermssionCollection::implies always works
+        testMerge(fp1);
+        testMerge(fp2);
+        testMerge(fp3);
+        testMerge(fp1, fp2);
+        testMerge(fp1, fp3);
+        testMerge(fp2, fp1);
+        testMerge(fp2, fp3);
+        testMerge(fp3, fp1);
+        testMerge(fp3, fp2);
+        testMerge(fp1, fp2, fp3);
+        testMerge(fp2, fp3, fp1);
+        testMerge(fp3, fp1, fp2);
+    }
+
+    // Add all into a collection, and check if it implies the last one.
+    static void testMerge(FilePermission... fps) {
+        java.security.Permissions perms = new Permissions();
+        FilePermission last = null;
+        for (FilePermission fp : fps) {
+            perms.add(fp);
+            last = fp;
+        }
+        Asserts.assertTrue(perms.implies(last));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/io/FilePermission/Invalid.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ *
+ * @test
+ * @bug 8167646
+ * @summary Better invalid FilePermission
+ * @library /test/lib
+ */
+
+import jdk.test.lib.Asserts;
+
+import java.io.FilePermission;
+
+public class Invalid {
+
+    public static void main(String args[]) throws Exception {
+
+        // Normal
+        FilePermission fp = new FilePermission("a", "read");
+
+        // Invalid
+        FilePermission fp1 = new FilePermission("a\000", "read");
+        FilePermission fp2 = new FilePermission("a\000", "read");
+        FilePermission fp3 = new FilePermission("b\000", "read");
+
+        // Invalid equals to itself
+        Asserts.assertEQ(fp1, fp1);
+
+        // and not equals to anything else, including other invalid ones
+        Asserts.assertNE(fp, fp1);
+        Asserts.assertNE(fp1, fp);
+        Asserts.assertNE(fp1, fp2);
+        Asserts.assertNE(fp1, fp3);
+
+        // Invalid implies itself
+        Asserts.assertTrue(fp1.implies(fp1));
+
+        // and not implies or implied by anything else, including other
+        // invalid ones
+        Asserts.assertFalse(fp.implies(fp1));
+        Asserts.assertFalse(fp1.implies(fp));
+        Asserts.assertFalse(fp1.implies(fp2));
+        Asserts.assertFalse(fp1.implies(fp3));
+    }
+}
--- a/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/io/Serializable/serialFilter/SerialFilterTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -40,7 +40,7 @@
 import java.util.Set;
 import java.util.concurrent.atomic.LongAdder;
 
-import javax.lang.model.SourceVersion;
+import javax.net.ssl.SSLEngineResult;
 
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -82,8 +82,8 @@
         Object[][] patterns = new Object[][]{
                 {"java.util.Hashtable"},
                 {"java.util.Hash*"},
-                {"javax.lang.model.*"},
-                {"javax.lang.**"},
+                {"javax.net.ssl.*"},
+                {"javax.net.**"},
                 {"*"},
                 {"maxarray=47"},
                 {"maxdepth=5"},
@@ -543,20 +543,20 @@
     static Object genTestObjectWildcard(String pattern, boolean allowed) {
         if (pattern.endsWith(".**")) {
             // package hierarchy wildcard
-            if (pattern.startsWith("javax.lang.")) {
-                return SourceVersion.RELEASE_5;
+            if (pattern.startsWith("javax.net.")) {
+                return SSLEngineResult.Status.BUFFER_OVERFLOW;
             }
             if (pattern.startsWith("java.")) {
                 return 4;
             }
             if (pattern.startsWith("javax.")) {
-                return SourceVersion.RELEASE_6;
+                return SSLEngineResult.Status.BUFFER_UNDERFLOW;
             }
             return otherObject;
         } else if (pattern.endsWith(".*")) {
             // package wildcard
-            if (pattern.startsWith("javax.lang.model")) {
-                return SourceVersion.RELEASE_6;
+            if (pattern.startsWith("javax.net.ssl")) {
+                return SSLEngineResult.Status.BUFFER_UNDERFLOW;
             }
         } else {
             // class wildcard
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/ClassLoader/IsParallelCapable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8165793
+ * @summary Test ClassLoader.isParallelCapable() method
+ * @run main IsParallelCapable
+ */
+
+import java.util.stream.Stream;
+
+public class IsParallelCapable {
+    public abstract static class TestCL extends ClassLoader {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        public abstract boolean expectCapable();
+        public Class findClass(String name) throws ClassNotFoundException {
+            throw new ClassNotFoundException("Why are you using this?");
+        }
+    }
+
+    public static class ParaCL extends TestCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() { return true; }
+    }
+
+    public static class NonParaCL extends TestCL {
+        @Override
+        public boolean expectCapable() {
+            // Doesn't call registerAsParallelCapable()
+            return false;
+        }
+    }
+
+    public static class NonParaSubCL1 extends ParaCL {
+        @Override
+        public boolean expectCapable() {
+            // Doesn't call registerAsParallelCapable()
+            return false;
+        }
+    }
+
+    public static class NonParaSubCL2 extends NonParaCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() {
+            // Superclass is not parallel capable
+            return false;
+        }
+    }
+
+    public static class ParaSubCL extends ParaCL {
+        static {
+            ClassLoader.registerAsParallelCapable();
+        }
+        @Override
+        public boolean expectCapable() { return true; }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!ClassLoader.getSystemClassLoader().isParallelCapable()) {
+            throw new RuntimeException("System classloader not parallel capable!?");
+        }
+
+        Stream.of(ParaCL.class,
+                  NonParaCL.class,
+                  NonParaSubCL1.class,
+                  NonParaSubCL2.class,
+                  ParaSubCL.class)
+                .forEach(IsParallelCapable::testClassLoaderClass);
+    }
+
+    private static void testClassLoaderClass(Class<? extends TestCL> klazz) {
+        try {
+            TestCL cl = (TestCL)klazz.newInstance();
+            if (cl.expectCapable() != cl.isParallelCapable()) {
+                throw new RuntimeException(klazz + " expectCapable: " +
+                        cl.expectCapable() + ", isParallelCapable: " +
+                        cl.isParallelCapable());
+            } else {
+                System.out.println(klazz + " passed");
+            }
+        } catch (InstantiationException |  IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
--- a/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/ClassLoader/platformClassLoader/DefinePlatformClass.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,8 +24,9 @@
 /*
  * @test
  * @summary Test java.* class defined by the platform class loader
- * @build jdk.zipfs/java.fake.Fake
  * @modules jdk.zipfs/java.fake
+ * @build   jdk.zipfs/java.fake.Fake
+ * @compile --add-modules jdk.zipfs DefinePlatformClass.java
  * @run main DefinePlatformClass
  */
 
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Fri Nov 11 16:44:36 2016 +0100
@@ -2404,16 +2404,6 @@
                 fail("Test failed: waitFor didn't take long enough (" + (end - start) + "ns)");
 
             p.destroy();
-
-            start = System.nanoTime();
-            p.waitFor(8, TimeUnit.SECONDS);
-            end = System.nanoTime();
-
-            int exitValue = p.exitValue();
-
-            if ((end - start) > TimeUnit.SECONDS.toNanos(7))
-                fail("Test failed: waitFor took too long on a dead process. (" + (end - start) + "ns)"
-                + ", exitValue: " + exitValue);
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
--- a/jdk/test/java/lang/StackTraceElement/PublicConstructor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/StackTraceElement/PublicConstructor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,43 +23,74 @@
 
 /*
  * @test
- * @bug     4712607
+ * @bug     4712607 6479237
  * @summary Basic test for StackTraceElementPublic constructor
  * @author  Josh Bloch
  */
 
-import java.util.*;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Module;
 
 public class PublicConstructor {
-    public static void main(String args[]) {
+    public static void main(String... args) {
+        testConstructor();
+        testConstructorWithModule();
+    }
+
+    static void testConstructor() {
         StackTraceElement ste = new StackTraceElement("com.acme.Widget",
-            "frobnicate", "Widget.java", 42);
+                                                      "frobnicate",
+                                                      "Widget.java", 42);
         if (!(ste.getClassName().equals("com.acme.Widget")  &&
-              ste.getFileName().equals("Widget.java") &&
-              ste.getMethodName().equals("frobnicate") &&
-              ste.getLineNumber() == 42))
+                ste.getFileName().equals("Widget.java") &&
+                ste.getMethodName().equals("frobnicate") &&
+                ste.getLineNumber() == 42))
             throw new RuntimeException("1");
+
         if (ste.isNativeMethod())
             throw new RuntimeException("2");
-        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))
+
+        assertEquals(ste.toString(),
+                     "com.acme.Widget.frobnicate(Widget.java:42)");
+
+        StackTraceElement ste1 = new StackTraceElement("com.acme.Widget",
+                                                       "frobnicate",
+                                                       "Widget.java",
+                                                       -2);
+        if (!ste1.isNativeMethod())
             throw new RuntimeException("3");
-        if (ste2.isNativeMethod())
+
+        assertEquals(ste1.toString(),
+                     "com.acme.Widget.frobnicate(Native Method)");
+    }
+
+    static void testConstructorWithModule() {
+        StackTraceElement ste = new StackTraceElement("app",
+                                                      "jdk.module",
+                                                      "9.0",
+                                                      "com.acme.Widget",
+                                                      "frobnicate",
+                                                      "Widget.java",
+                                                      42);
+        if (!(ste.getClassName().equals("com.acme.Widget")  &&
+                ste.getModuleName().equals("jdk.module") &&
+                ste.getModuleVersion().equals("9.0") &&
+                ste.getClassLoaderName().equals("app") &&
+                ste.getFileName().equals("Widget.java") &&
+                ste.getMethodName().equals("frobnicate") &&
+                ste.getLineNumber() == 42))
+            throw new RuntimeException("3");
+
+        if (ste.isNativeMethod())
             throw new RuntimeException("4");
-        StackTraceElement ste3 = new StackTraceElement("com.acme.Widget",
-            "frobnicate", "Widget.java", -2);
-        if (!ste3.isNativeMethod())
-            throw new RuntimeException("5");
+
+        assertEquals(ste.toString(),
+                     "app/jdk.module@9.0/com.acme.Widget.frobnicate(Widget.java:42)");
+    }
+
+    static void assertEquals(String s, String expected) {
+        if (!s.equals(expected)) {
+            throw new RuntimeException("Expected: " + expected + " but found: " + s);
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/SerialTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6479237
+ * @summary Test the format of StackTraceElement::toString and its serial form
+ * @modules java.logging
+ *          java.xml.bind
+ * @run main SerialTest
+ */
+
+import javax.xml.bind.JAXBElement;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+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.Arrays;
+import java.util.logging.Logger;
+
+public class SerialTest {
+    private static final Path SER_DIR = Paths.get("sers");
+    private static final String JAVA_BASE = "java.base";
+    private static final String JAVA_LOGGING = "java.logging";
+    private static final String JAVA_XML_BIND = "java.xml.bind";
+
+    private static boolean isImage;
+
+    public static void main(String... args) throws Exception {
+        Files.createDirectories(SER_DIR);
+
+        // detect if exploded image build
+        Path home = Paths.get(System.getProperty("java.home"));
+        isImage = Files.exists(home.resolve("lib").resolve("modules"));
+
+        // test stack trace from built-in loaders
+        try {
+            Logger.getLogger(null);
+        } catch (NullPointerException e) {
+            Arrays.stream(e.getStackTrace())
+                  .filter(ste -> ste.getClassName().startsWith("java.util.logging.") ||
+                                 ste.getClassName().equals("SerialTest"))
+                  .forEach(SerialTest::test);
+        }
+
+        // test stack trace with upgradeable module
+        try {
+            new JAXBElement(null, null, null);
+        } catch (IllegalArgumentException e) {
+            Arrays.stream(e.getStackTrace())
+                  .filter(ste -> ste.getModuleName() != null)
+                  .forEach(SerialTest::test);
+        }
+
+        // test stack trace with class loader name from other class loader
+        Loader loader = new Loader("myloader");
+        Class<?> cls = Class.forName("SerialTest", true, loader);
+        Method method = cls.getMethod("throwException");
+        StackTraceElement ste = (StackTraceElement)method.invoke(null);
+        test(ste, loader);
+
+        // verify the class loader name and in the stack trace
+        if (!cls.getClassLoader().getName().equals("myloader.hacked")) {
+            throw new RuntimeException("Unexpected loader name: " +
+                cls.getClassLoader().getName());
+        }
+        if (!ste.getClassLoaderName().equals("myloader")) {
+            throw new RuntimeException("Unexpected loader name: " +
+                ste.getClassLoaderName());
+        }
+    }
+
+    private static void test(StackTraceElement ste) {
+        test(ste, null);
+    }
+
+    private static void test(StackTraceElement ste, ClassLoader loader) {
+        try {
+            SerialTest serialTest = new SerialTest(ste);
+            StackTraceElement ste2 = serialTest.serialize().deserialize();
+            System.out.println(ste2);
+            // verify StackTraceElement::toString returns the same string
+            if (!ste.equals(ste2) || !ste.toString().equals(ste2.toString())) {
+                throw new RuntimeException(ste + " != " + ste2);
+            }
+
+            String mn = ste.getModuleName();
+            if (mn != null) {
+                switch (mn) {
+                    case JAVA_BASE:
+                    case JAVA_LOGGING:
+                        checkNamedModule(ste, loader, false);
+                        break;
+                    case JAVA_XML_BIND:
+                        // for exploded build, no version is shown
+                        checkNamedModule(ste, loader, isImage);
+                        break;
+                    default:  // ignore
+                }
+            } else {
+                checkUnnamedModule(ste, loader);
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private static void checkUnnamedModule(StackTraceElement ste, ClassLoader loader) {
+        String mn = ste.getModuleName();
+        String s = ste.toString();
+        int i = s.indexOf('/');
+
+        if (mn != null) {
+            throw new RuntimeException("expected null but got " + mn);
+        }
+
+        if (loader != null) {
+            // Expect <loader>//<classname>.<method>(<src>:<ln>)
+            if (i <= 0) {
+                throw new RuntimeException("loader name missing: " + s);
+            }
+            if (!getLoaderName(loader).equals(s.substring(0, i))) {
+                throw new RuntimeException("unexpected loader name: " + s);
+            }
+            int j = s.substring(i+1).indexOf('/');
+            if (j != 0) {
+                throw new RuntimeException("unexpected element for unnamed module: " + s);
+            }
+        }
+    }
+
+    /*
+     * Loader::getName is overridden to return some other name
+     */
+    private static String getLoaderName(ClassLoader loader) {
+        if (loader == null)
+            return "";
+
+        if (loader instanceof Loader) {
+            return ((Loader) loader).name;
+        } else {
+            return loader.getName();
+        }
+    }
+
+    private static void checkNamedModule(StackTraceElement ste,
+                                         ClassLoader loader,
+                                         boolean showVersion) {
+        String loaderName = getLoaderName(loader);
+        String mn = ste.getModuleName();
+        String s = ste.toString();
+        int i = s.indexOf('/');
+
+        if (mn == null) {
+            throw new RuntimeException("expected module name: " + s);
+        }
+
+        if (i <= 0) {
+            throw new RuntimeException("module name missing: " + s);
+        }
+
+        // Expect <module>/<classname>.<method>(<src>:<ln>)
+        if (!loaderName.isEmpty()) {
+            throw new IllegalArgumentException(loaderName);
+        }
+
+        // <module>: name@version
+        int j = s.indexOf('@');
+        if ((showVersion && j <= 0) || (!showVersion && j >= 0)) {
+            throw new RuntimeException("unexpected version: " + s);
+        }
+
+        String name = j < 0 ? s.substring(0, i) : s.substring(0, j);
+        if (!name.equals(mn)) {
+            throw new RuntimeException("unexpected module name: " + s);
+        }
+    }
+
+    private final Path ser;
+    private final StackTraceElement ste;
+    SerialTest(StackTraceElement ste) throws IOException {
+        this.ser = Files.createTempFile(SER_DIR, "SerialTest", ".ser");
+        this.ste = ste;
+    }
+
+    private StackTraceElement deserialize() throws IOException {
+        try (InputStream in = Files.newInputStream(ser);
+             BufferedInputStream bis = new BufferedInputStream(in);
+             ObjectInputStream ois = new ObjectInputStream(bis)) {
+            return (StackTraceElement)ois.readObject();
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private SerialTest serialize() throws IOException {
+        try (OutputStream out = Files.newOutputStream(ser);
+             BufferedOutputStream bos = new BufferedOutputStream(out);
+            ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(ste);
+        }
+        return this;
+    }
+
+
+    public static StackTraceElement throwException() {
+        try {
+            Integer.parseInt(null);
+        } catch (NumberFormatException e) {
+            return Arrays.stream(e.getStackTrace())
+                .filter(ste -> ste.getMethodName().equals("throwException"))
+                .findFirst().get();
+        }
+        return null;
+    }
+
+    public static class Loader extends URLClassLoader {
+        final String name;
+        Loader(String name) throws MalformedURLException {
+            super(name, new URL[] { testClassesURL() } , null);
+            this.name = name;
+        }
+
+        private static URL testClassesURL() throws MalformedURLException {
+            Path path = Paths.get(System.getProperty("test.classes"));
+            return path.toUri().toURL();
+        }
+
+        public String getName() {
+            return name + ".hacked";
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/WithClassLoaderName.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 6479237
+ * @summary Basic test StackTraceElement with class loader names
+ * @library lib /lib/testlibrary
+ * @build m1/* WithClassLoaderName
+ * @run main/othervm m1/com.app.Main
+ * @run main/othervm WithClassLoaderName
+ */
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.app.Utils;
+
+public class WithClassLoaderName {
+    private static final String TEST_SRC = System.getProperty("test.src");
+    private static final String SRC_FILENAME = "WithClassLoaderName.java";
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path CLASSES_DIR = Paths.get("classes");
+    private static final String THROW_EXCEPTION_CLASS = "p.ThrowException";
+
+    public static void main(String... args) throws Exception {
+        /*
+         * Test the following frames both have the same class loader name "app"
+         *   com.app.Test::test
+         *   WithClassLoaderName::test
+         */
+        Utils.verify(WithClassLoaderName.class, "app", "main", SRC_FILENAME);
+
+        /*
+         * Test StackTraceElement for a class loaded by a named URLClassLoader
+         */
+        compile();
+        testURLClassLoader("myloader");
+
+        // loader name same as application class loader
+        testURLClassLoader("app");
+    }
+
+    private static void compile() throws Exception {
+        boolean rc = CompilerUtils.compile(SRC_DIR, CLASSES_DIR);
+        if (!rc) {
+            throw new RuntimeException("compilation fails");
+        }
+    }
+
+    public static void testURLClassLoader(String loaderName) throws Exception {
+        System.err.println("---- test URLClassLoader name: " + loaderName);
+
+        URL[] urls = new URL[] { CLASSES_DIR.toUri().toURL() };
+        ClassLoader parent = ClassLoader.getSystemClassLoader();
+        URLClassLoader loader = new URLClassLoader(loaderName, urls, parent);
+
+        Class<?> c = Class.forName(THROW_EXCEPTION_CLASS, true, loader);
+        Method method = c.getMethod("throwError");
+        try {
+            // invoke p.ThrowException::throwError
+            method.invoke(null);
+        } catch (InvocationTargetException x) {
+            Throwable e = x.getCause();
+            e.printStackTrace();
+
+            StackTraceElement[] stes = e.getStackTrace();
+            StackWalker.StackFrame[] frames = new StackWalker.StackFrame[] {
+                Utils.makeStackFrame(c, "throwError", "ThrowException.java"),
+                Utils.makeStackFrame(WithClassLoaderName.class, "testURLClassLoader",
+                                     SRC_FILENAME),
+                Utils.makeStackFrame(WithClassLoaderName.class, "main", SRC_FILENAME),
+            };
+
+            // p.ThrowException.throwError
+            Utils.checkFrame(loaderName, frames[0], stes[0]);
+            // skip reflection frames
+            int i = 1;
+            while (i < stes.length) {
+                String cn = stes[i].getClassName();
+                if (!cn.startsWith("java.lang.reflect.") &&
+                    !cn.startsWith("jdk.internal.reflect."))
+                    break;
+                i++;
+            }
+            // WithClassLoaderName.testURLClassLoader
+            Utils.checkFrame("app", frames[1], stes[i]);
+
+            // WithClassLoaderName.main
+            Utils.checkFrame("app", frames[2], stes[i+1]);
+
+        }
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.app;
+
+import java.lang.StackWalker.StackFrame;
+
+public class Main {
+    public static void main(String... args) throws Exception {
+        StackFrame frame = Utils.makeStackFrame(Main.class, "main", "Main.java");
+        Utils.checkFrame("app", frame, caller());
+    }
+
+    private static StackTraceElement caller() {
+        StackTraceElement[] stes = Thread.currentThread().getStackTrace();
+        return stes[2];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/lib/m1/com/app/Utils.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.app;
+
+import java.lang.StackWalker.StackFrame;
+import java.lang.module.ModuleDescriptor;
+import java.lang.reflect.Module;
+import java.util.Objects;
+
+public class Utils {
+    public static void verify(Class<?> caller, String loaderName,
+                              String methodname, String filename) {
+        StackTraceElement[] stes = Thread.currentThread().getStackTrace();
+        StackWalker.StackFrame[] frames = new StackFrame[] {
+            makeStackFrame(Utils.class, "verify", "Utils.java"),
+            makeStackFrame(caller, methodname, filename)
+        };
+
+        checkFrame("app", frames[0], stes[1]);
+        checkFrame(loaderName, frames[1], stes[2]);
+    }
+
+    public static StackFrame makeStackFrame(Class<?> c, String methodname, String filename) {
+        return new StackFrame() {
+            @Override
+            public String getClassName() {
+                return c.getName();
+            }
+            @Override
+            public String getMethodName() {
+                return methodname;
+            }
+            @Override
+            public Class<?> getDeclaringClass() {
+                return c;
+            }
+            @Override
+            public int getByteCodeIndex() {
+                return 0;
+            }
+            @Override
+            public String getFileName() {
+                return filename;
+            }
+
+            @Override
+            public int getLineNumber() {
+                return 0;
+            }
+            @Override
+            public boolean isNativeMethod() {
+                return false;
+            }
+            @Override
+            public StackTraceElement toStackTraceElement() {
+                return null;
+            }
+
+            private String getClassLoaderName(Class<?> c) {
+                ClassLoader loader = c.getClassLoader();
+                String name = "";
+                if (loader == null) {
+                    name = "boot";
+                } else if (loader.getName() != null) {
+                    name = loader.getName();
+                }
+                return name;
+            }
+
+            @Override
+            public String toString() {
+                String mid = getClassLoaderName(c);
+                Module module = c.getModule();
+                if (module.isNamed()) {
+                    ModuleDescriptor md = module.getDescriptor();
+                    mid = md.name();
+                    if (md.version().isPresent())
+                        mid += "@" + md.version().get().toString();
+                    mid += "/";
+                }
+                String fileName = getFileName();
+                int lineNumber = getLineNumber();
+                String sourceinfo = "Unknown Source";
+                if (isNativeMethod()) {
+                    sourceinfo = "Native Method";
+                } else if (fileName != null && lineNumber >= 0) {
+                    sourceinfo = fileName + ":" + lineNumber;
+                }
+                return String.format("%s/%s.%s(%s)", mid, getClassName(), getMethodName(),
+                                     sourceinfo);
+
+            }
+        };
+    }
+
+    public static void checkFrame(String loaderName, StackFrame frame,
+                                  StackTraceElement ste) {
+        System.err.println("checking " + ste.toString() + " expected: " + frame.toString());
+        Class<?> c = frame.getDeclaringClass();
+        Module module = c.getModule();
+        assertEquals(ste.getModuleName(), module.getName(), "module name");
+        assertEquals(ste.getClassLoaderName(), loaderName, "class loader name");
+        assertEquals(ste.getClassLoaderName(), c.getClassLoader().getName(),
+                     "class loader name");
+        assertEquals(ste.getClassName(), c.getName(), "class name");
+        assertEquals(ste.getMethodName(), frame.getMethodName(), "method name");
+        assertEquals(ste.getFileName(), frame.getFileName(), "file name");
+
+    }
+    private static void assertEquals(String actual, String expected, String msg) {
+        if (!Objects.equals(actual, expected))
+            throw new AssertionError("Actual: " + actual + " Excepted: " +
+                expected + " mismatched " + msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/lib/m1/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 com.app;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/StackTraceElement/src/p/ThrowException.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p;
+
+import java.lang.StackWalker.StackFrame;
+
+public class ThrowException {
+    public static void throwError() {
+        throw new Error("testing");
+    }
+}
--- a/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/StackWalker/VerifyStackTrace.java	Fri Nov 11 16:44:36 2016 +0100
@@ -71,7 +71,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(java.base/Native Method)\n" +
+            "6: java.base/java.security.AccessController.doPrivileged(Native Method)\n" +
             "7: VerifyStackTrace.test(VerifyStackTrace.java:227)\n" +
             "8: VerifyStackTrace.main(VerifyStackTrace.java:182)\n";
 
@@ -100,12 +100,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: jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" +
-            "6: jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" +
-            "7: jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" +
-            "8: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" +
+            "5: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
+            "6: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
+            "7: java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
+            "8: java.base/java.lang.reflect.Method.invoke(Method.java:520)\n" +
             "9: VerifyStackTrace$1.run(VerifyStackTrace.java:220)\n" +
-            "10: java.security.AccessController.doPrivileged(java.base/Native Method)\n" +
+            "10: java.base/java.security.AccessController.doPrivileged(Native Method)\n" +
             "11: VerifyStackTrace.test(VerifyStackTrace.java:229)\n" +
             "12: VerifyStackTrace.main(VerifyStackTrace.java:185)\n";
 
@@ -133,16 +133,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(java.base/LambdaForm$DMH)\n" +
-            "5: java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(java.base/LambdaForm$MH)\n" +
+            "4: java.base/java.lang.invoke.LambdaForm$DMH/2008017533.invokeVirtual_LL_V(LambdaForm$DMH)\n" +
+            "5: java.base/java.lang.invoke.LambdaForm$MH/1395089624.invoke_MT(LambdaForm$MH)\n" +
             "6: VerifyStackTrace$Handle.run(VerifyStackTrace.java:162)\n" +
             "7: VerifyStackTrace.invoke(VerifyStackTrace.java:192)\n" +
-            "8: jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(java.base/Native Method)\n" +
-            "9: jdk.internal.reflect.NativeMethodAccessorImpl.invoke(java.base/NativeMethodAccessorImpl.java:62)\n" +
-            "10: jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base/DelegatingMethodAccessorImpl.java:43)\n" +
-            "11: java.lang.reflect.Method.invoke(java.base/Method.java:520)\n" +
+            "8: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)\n" +
+            "9: java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)\n" +
+            "10: java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)\n" +
+            "11: java.base/java.lang.reflect.Method.invoke(Method.java:520)\n" +
             "12: VerifyStackTrace$1.run(VerifyStackTrace.java:222)\n" +
-            "13: java.security.AccessController.doPrivileged(java.base/Native Method)\n" +
+            "13: java.base/java.security.AccessController.doPrivileged(Native Method)\n" +
             "14: VerifyStackTrace.test(VerifyStackTrace.java:231)\n" +
             "15: VerifyStackTrace.main(VerifyStackTrace.java:188)\n";
 
@@ -201,8 +201,6 @@
             // 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@(\\d+\\.){0,3}(\\d+)/", "java.base/")
                     .replaceAll("/[0-9]+\\.run", "/xxxxxxxx.run")
                     .replaceAll("/[0-9]+\\.invoke", "/xxxxxxxx.invoke")
                     // LFs may or may not be pre-generated, making frames differ
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/SystemLoggerInPlatformLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * @test 8163162
+ * @summary Checks that LazyLoggers are returned for System.Logger instances
+ *          created by modules in the platform class loader.
+ * @build systempkg.log.SystemLoggerAccessor SystemLoggerInPlatformLoader
+ * @run main/othervm SystemLoggerInPlatformLoader
+ * @author danielfuchs
+ */
+public class SystemLoggerInPlatformLoader {
+
+    static final class PlatformClassLoaderChild extends ClassLoader {
+        private PlatformClassLoaderChild() {
+            super(ClassLoader.getPlatformClassLoader());
+        }
+        public Class<?> definePlatformClass(String name) throws IOException {
+            String testClasses = System.getProperty("test.classes", "./build/classes");
+            String fname = name.replace('.', '/').concat(".class");
+            try (InputStream is = new FileInputStream(new File(testClasses, fname))) {
+                byte[] b = is.readAllBytes();
+                ClassLoader parent = getParent();
+                try {
+                    Method m = ClassLoader.class.getDeclaredMethod("defineClass",
+                        String.class, byte[].class, int.class, int.class);
+                    m.setAccessible(true);
+                    return (Class<?>)m.invoke(parent, name, b, 0, b.length);
+                } catch (NoSuchMethodException
+                        | IllegalAccessException
+                        | InvocationTargetException ex) {
+                    throw new IOException(ex);
+                }
+            }
+        }
+        static final PlatformClassLoaderChild INSTANCE = new PlatformClassLoaderChild();
+        static Class<?> loadLoggerAccessor() throws IOException {
+            return INSTANCE.definePlatformClass("systempkg.log.SystemLoggerAccessor");
+        }
+    }
+
+    static final Class<?> LOGGER_ACCESSOR_CLASS;
+    static {
+        try {
+            LOGGER_ACCESSOR_CLASS = PlatformClassLoaderChild.loadLoggerAccessor();
+            ClassLoader platformCL = ClassLoader.getPlatformClassLoader();
+            if (LOGGER_ACCESSOR_CLASS.getClassLoader() != platformCL) {
+                throw new ExceptionInInitializerError(
+                    "Could not load accessor class in platform class loader: "
+                     + LOGGER_ACCESSOR_CLASS.getClassLoader());
+            }
+        } catch (IOException ex) {
+            throw new ExceptionInInitializerError(ex);
+        }
+    }
+
+    // Returns a system logger created on behalf of a class loaded by the
+    // Platform ClassLoader
+    static System.Logger getSystemLogger(String name) {
+        try {
+            return (System.Logger)LOGGER_ACCESSOR_CLASS.getMethod(
+                    "getSystemLogger", String.class).invoke(null, name);
+        } catch (NoSuchMethodException
+                | IllegalAccessException
+                | InvocationTargetException ex) {
+            throw new RuntimeException("Failed to invoke LoggerAccessor.getJULLogger", ex);
+        }
+    }
+
+    public static void main(String[] args) {
+        System.Logger splogger = getSystemLogger("bar"); // for a platform class
+        System.Logger slogger = System.getLogger("bar"); // for an application class
+        if (slogger == splogger) {
+            throw new RuntimeException("Same loggers");
+        }
+        Class sploggerType = splogger.getClass();
+        System.out.println("splogger: " + sploggerType);
+        if (!sploggerType.getSimpleName().equals("JdkLazyLogger")) {
+            throw new RuntimeException(sploggerType.getSimpleName()
+                      + ": unexpected class for splogger"
+                      + " (expected a lazy logger for a platform class)");
+        }
+        Class sloggerType = slogger.getClass();
+        System.out.println("slogger: " + sloggerType);
+        if (sloggerType.equals(sploggerType)) {
+            throw new RuntimeException(sloggerType
+                      + ": unexpected class for slogger"
+                      + " (a lazy logger was not expected"
+                      + " for a non platform class)");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/SystemLoggerInPlatformLoader/systempkg/log/SystemLoggerAccessor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package systempkg.log;
+
+
+/**
+ * Utility class that returns loggers created for classes in the
+ * systempkg.log package;
+ * This class should be loaded in the {@linkplain
+ * ClassLoader#getPlatformClassLoader() platform class loader}
+ * for the purpose of the test.
+ * @author danielfuchs
+ */
+public class SystemLoggerAccessor {
+    public static System.Logger getSystemLogger(String name) {
+        return System.getLogger(name);
+    }
+}
--- a/jdk/test/java/lang/annotation/AnnotationToStringTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/annotation/AnnotationToStringTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8162817
+ * @bug 8162817 8168921
  * @summary Test of toString on normal annotations
  */
 
@@ -70,6 +70,8 @@
         "d1=1.0/0.0, " +
         "l0=5, " +
         "l1=9223372036854775807L, " +
+        "l2=-9223372036854775808L, " +
+        "l3=-2147483648, " +
         "s0=\"Hello world.\", " +
         "s1=\"a\\\"b\", " +
         "class0=Obj[].class)")
@@ -84,6 +86,8 @@
         d1=2.0/0.0,
         l0=5,
         l1=Long.MAX_VALUE,
+        l2=Long.MIN_VALUE,
+        l3=Integer.MIN_VALUE,
         s0="Hello world.",
         s1="a\"b",
         class0=Obj[].class
@@ -185,8 +189,10 @@
         public int[]       f6;
 
         @ExpectedString(
-       "@LongArray(value={-2147483647, 2147483648L, 9223372036854775807L})")
-        @LongArray(value={-Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE})
+       "@LongArray(value={-9223372036854775808L, -2147483649L, -2147483648," +
+                " -2147483647, 2147483648L, 9223372036854775807L})")
+        @LongArray(value={Long.MIN_VALUE, Integer.MIN_VALUE-1L, Integer.MIN_VALUE,
+                -Integer.MAX_VALUE, Integer.MAX_VALUE+1L, Long.MAX_VALUE})
         public long[]      f7;
 
         @ExpectedString(
@@ -287,6 +293,8 @@
     double d1();
     long   l0();
     long   l1();
+    long   l2();
+    long   l3();
     String s0();
     String s1();
     Class<?> class0();
--- a/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/instrument/DaemonThread/TestDaemonThreadLauncher.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,7 +29,7 @@
 public class TestDaemonThreadLauncher {
     public static void main(String args[]) throws Exception {
         for(int i=0; i<50; i++) {
-            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
+            ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, "-javaagent:DummyAgent.jar", "TestDaemonThread", ".");
             OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
             analyzer.shouldNotContain("ASSERTION FAILED");
             analyzer.shouldHaveExitValue(0);
--- a/jdk/test/java/lang/invoke/LoopCombinatorTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,6 +33,7 @@
  * @bug 8153637
  * @bug 8154751
  * @bug 8154754
+ * @bug 8167974
  * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest
  */
 
@@ -800,7 +801,8 @@
                 {l_it, l_i, isl_i, ""},
                 {l_it, null, sl_v, ""},
                 {li_it, li_i, isli_i, ""},
-                {il_it, null, sil_v, "inferred first loop argument must inherit from Iterable: int"},
+                {null, null, sil_v, "inferred first loop argument must inherit from Iterable: int"},
+                {il_it, null, sil_v, ""},
                 {li_it, null, sli_v, ""},
                 {sl_v, null, sl_v, "iteratedLoop first argument must have Iterator return type"},
                 {li_it, l_it, sl_v,
--- a/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/management/CompositeData/ThreadInfoCompositeData.java	Fri Nov 11 16:44:36 2016 +0100
@@ -337,9 +337,10 @@
     };
 
     private static final String[] steItemNames = {
-        "className",
+        "classLoaderName",
         "moduleName",
         "moduleVersion",
+        "className",
         "methodName",
         "fileName",
         "lineNumber",
@@ -362,9 +363,10 @@
             validItemTypes[STACK_TRACE] = new ArrayType(1, steCType);
 
             final Object[] steValue = {
-                ste[0].getClassName(),
+                ste[0].getClassLoaderName(),
                 ste[0].getModuleName(),
                 ste[0].getModuleVersion(),
+                ste[0].getClassName(),
                 ste[0].getMethodName(),
                 ste[0].getFileName(),
                 new Integer(ste[0].getLineNumber()),
--- a/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/management/MemoryMXBean/LowMemoryTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -34,6 +34,7 @@
  * @modules java.management
  * @build jdk.testlibrary.* LowMemoryTest MemoryUtil RunUtil
  * @run main/timeout=600 LowMemoryTest
+ * @requires vm.gc == "null"
  * @requires vm.opt.ExplicitGCInvokesConcurrent != "true"
  * @requires vm.opt.ExplicitGCInvokesConcurrentAndUnloadsClasses != "true"
  * @requires vm.opt.DisableExplicitGC != "true"
--- a/jdk/test/java/lang/module/AutomaticModulesTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/module/AutomaticModulesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -158,40 +158,85 @@
      */
     public void testPackages() throws IOException {
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m1.jar"),
+        createDummyJarFile(dir.resolve("m.jar"),
                            "p/C1.class", "p/C2.class", "q/C1.class");
 
         ModuleFinder finder = ModuleFinder.of(dir);
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
 
-        Configuration parent = Layer.boot().configuration();
-        Configuration cf = resolve(parent, finder, "m1");
+        ModuleDescriptor descriptor = mref.get().descriptor();
 
-        ModuleDescriptor m1 = findDescriptor(cf, "m1");
+        assertTrue(descriptor.packages().size() == 2);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.packages().contains("q"));
 
-        Set<String> exports
-            = m1.exports().stream().map(Exports::source).collect(Collectors.toSet());
-
+        Set<String> exports = descriptor.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 class files in JAR file where the entry does not correspond to a
+     * legal package name.
+     */
+    public void testBadPackage() throws IOException {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p-/C2.class");
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
+
+        ModuleDescriptor descriptor = mref.get().descriptor();
+
+        assertTrue(descriptor.packages().size() == 1);
+        assertTrue(descriptor.packages().contains("p"));
+
+        Set<String> exports = descriptor.exports().stream()
+                .map(Exports::source)
+                .collect(Collectors.toSet());
+        assertTrue(exports.size() == 1);
+        assertTrue(exports.contains("p"));
     }
 
+    /**
+     * Test non-class resources in a JAR file.
+     */
+    public void testNonClassResources() throws IOException {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        createDummyJarFile(dir.resolve("m.jar"),
+                "LICENSE",
+                "README",
+                "WEB-INF/tags",
+                "p/Type.class",
+                "p/resources/m.properties");
+
+        ModuleFinder finder = ModuleFinder.of(dir);
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
+
+        ModuleDescriptor descriptor = mref.get().descriptor();
+
+        assertTrue(descriptor.packages().size() == 2);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.packages().contains("p.resources"));
+    }
 
     /**
-     * Test class file in JAR file where the entry does not correspond to a
-     * legal package name.
+     * Test .class file in unnamed package (top-level directory)
      */
     @Test(expectedExceptions = FindException.class)
-    public void testBadPackage() throws IOException {
+    public void testClassInUnnamedPackage() throws IOException {
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        createDummyJarFile(dir.resolve("m1.jar"), "p-/T.class");
-
-        // should throw FindException
-        ModuleFinder.of(dir).findAll();
+        createDummyJarFile(dir.resolve("m.jar"), "Mojo.class");
+        ModuleFinder finder = ModuleFinder.of(dir);
+        finder.findAll();
     }
 
-
     /**
      * Test JAR file with META-INF/services configuration file
      */
@@ -204,12 +249,12 @@
         Files.createDirectories(services);
         Files.write(services.resolve(service), Set.of(provider));
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        JarUtils.createJarFile(dir.resolve("m1.jar"), tmpdir);
+        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 
         ModuleFinder finder = ModuleFinder.of(dir);
 
-        Optional<ModuleReference> mref = finder.find("m1");
-        assertTrue(mref.isPresent(), "m1 not found");
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
 
         ModuleDescriptor descriptor = mref.get().descriptor();
         assertTrue(descriptor.provides().size() == 1);
@@ -220,17 +265,12 @@
     }
 
 
-    // META-INF/services configuration file/entries that are not legal
-    @DataProvider(name = "badproviders")
-    public Object[][] createProviders() {
+    // META-INF/services files that don't map to legal service names
+    @DataProvider(name = "badservices")
+    public Object[][] createBadServices() {
         return new Object[][] {
 
                 // service type         provider type
-
-                { "p.S",                "-" },
-                { "p.S",                ".S1" },
-                { "p.S",                "S1." },
-
                 { "-",                  "p.S1" },
                 { ".S",                 "p.S1" },
         };
@@ -240,8 +280,8 @@
      * Test JAR file with META-INF/services configuration file with bad
      * values or names.
      */
-    @Test(dataProvider = "badproviders", expectedExceptions = FindException.class)
-    public void testBadServicesConfiguration(String service, String provider)
+    @Test(dataProvider = "badservices")
+    public void testBadServicesNames(String service, String provider)
         throws IOException
     {
         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
@@ -249,7 +289,41 @@
         Files.createDirectories(services);
         Files.write(services.resolve(service), Set.of(provider));
         Path dir = Files.createTempDirectory(USER_DIR, "mods");
-        JarUtils.createJarFile(dir.resolve("m1.jar"), tmpdir);
+        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
+
+        Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
+        assertTrue(omref.isPresent());
+        ModuleDescriptor descriptor = omref.get().descriptor();
+        assertTrue(descriptor.provides().isEmpty());
+    }
+
+
+    // META-INF/services configuration file entries that are not legal
+    @DataProvider(name = "badproviders")
+    public Object[][] createBadProviders() {
+        return new Object[][] {
+
+                // service type         provider type
+                { "p.S",                "-" },
+                { "p.S",                ".S1" },
+                { "p.S",                "S1." },
+        };
+    }
+
+    /**
+     * Test JAR file with META-INF/services configuration file with bad
+     * values or names.
+     */
+    @Test(dataProvider = "badproviders", expectedExceptions = FindException.class)
+    public void testBadProvideNames(String service, String provider)
+        throws IOException
+    {
+        Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
+        Path services = tmpdir.resolve("META-INF").resolve("services");
+        Files.createDirectories(services);
+        Files.write(services.resolve(service), Set.of(provider));
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 
         // should throw FindException
         ModuleFinder.of(dir).findAll();
--- a/jdk/test/java/lang/module/ModuleFinderTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/module/ModuleFinderTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,6 +29,7 @@
  * @summary Basic tests for java.lang.module.ModuleFinder
  */
 
+import java.io.File;
 import java.io.OutputStream;
 import java.lang.module.FindException;
 import java.lang.module.InvalidModuleDescriptorException;
@@ -38,6 +39,7 @@
 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.JarEntry;
 import java.util.jar.JarOutputStream;
@@ -317,6 +319,111 @@
 
 
     /**
+     * Test ModuleFinder with a JAR file containing a mix of class and
+     * non-class resources.
+     */
+    public void testOfOneJarFileWithResources() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path jar = createModularJar(dir.resolve("m.jar"), "m",
+                "LICENSE",
+                "README",
+                "WEB-INF/tags",
+                "p/Type.class",
+                "p/resources/m.properties",
+                "q-/Type.class",                // not a legal package name
+                "q-/resources/m/properties");
+
+        ModuleFinder finder = ModuleFinder.of(jar);
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
+
+        ModuleDescriptor descriptor = mref.get().descriptor();
+
+        assertTrue(descriptor.packages().size() == 2);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.packages().contains("p.resources"));
+    }
+
+
+    /**
+     * Test ModuleFinder with an exploded module containing a mix of class
+     * and non-class resources
+     */
+    public void testOfOneExplodedModuleWithResources() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path m_dir = createExplodedModule(dir.resolve("m"), "m",
+                "LICENSE",
+                "README",
+                "WEB-INF/tags",
+                "p/Type.class",
+                "p/resources/m.properties",
+                "q-/Type.class",                 // not a legal package name
+                "q-/resources/m/properties");
+
+        ModuleFinder finder = ModuleFinder.of(m_dir);
+        Optional<ModuleReference> mref = finder.find("m");
+        assertTrue(mref.isPresent(), "m not found");
+
+        ModuleDescriptor descriptor = mref.get().descriptor();
+
+        assertTrue(descriptor.packages().size() == 2);
+        assertTrue(descriptor.packages().contains("p"));
+        assertTrue(descriptor.packages().contains("p.resources"));
+    }
+
+
+    /**
+     * Test ModuleModule with a JAR file containing a .class file in the top
+     * level directory.
+     */
+    public void testOfOneJarFileWithTopLevelClass() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path jar = createModularJar(dir.resolve("m.jar"), "m", "Mojo.class");
+
+        ModuleFinder finder = ModuleFinder.of(jar);
+        try {
+            finder.find("m");
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+
+        finder = ModuleFinder.of(jar);
+        try {
+            finder.findAll();
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+    }
+
+    /**
+     * Test ModuleModule with a JAR file containing a .class file in the top
+     * level directory.
+     */
+    public void testOfOneExplodedModuleWithTopLevelClass() throws Exception {
+        Path dir = Files.createTempDirectory(USER_DIR, "mods");
+        Path m_dir = createExplodedModule(dir.resolve("m"), "m", "Mojo.class");
+
+        ModuleFinder finder = ModuleFinder.of(m_dir);
+        try {
+            finder.find("m");
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+
+        finder = ModuleFinder.of(m_dir);
+        try {
+            finder.findAll();
+            assertTrue(false);
+        } catch (FindException e) {
+            assertTrue(e.getCause() instanceof InvalidModuleDescriptorException);
+        }
+    }
+
+
+    /**
      * Test ModuleFinder.of with a path to a file that does not exist.
      */
     public void testOfWithDoesNotExistEntry() throws Exception {
@@ -641,7 +748,7 @@
             vs = mid.substring(i+1);
         }
         ModuleDescriptor.Builder builder
-                = new ModuleDescriptor.Builder(mn).requires("java.base");
+            = new ModuleDescriptor.Builder(mn).requires("java.base");
         if (vs != null)
             builder.version(vs);
         return builder.build();
@@ -651,13 +758,22 @@
      * 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 {
+    static Path createExplodedModule(Path dir, String mid, String... entries)
+        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);
         }
+
+        for (String entry : entries) {
+            Path file = dir.resolve(entry.replace('/', File.separatorChar));
+            Files.createDirectories(file.getParent());
+            Files.createFile(file);
+        }
+
         return dir;
     }
 
--- a/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/lang/module/ModuleReader/ModuleReaderTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,9 +24,8 @@
 /**
  * @test
  * @library /lib/testlibrary
- * @modules java.base/jdk.internal.module
+ * @modules java.base/jdk.internal.misc
  *          jdk.compiler
- *          jdk.jlink
  * @build ModuleReaderTest CompilerUtils JarUtils
  * @run testng ModuleReaderTest
  * @summary Basic tests for java.lang.module.ModuleReader
@@ -47,11 +46,14 @@
 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.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
 import java.util.spi.ToolProvider;
 
-import jdk.internal.module.ConfigurableModuleFinder;
-import jdk.internal.module.ConfigurableModuleFinder.Phase;
+import jdk.internal.misc.SharedSecrets;
 
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
@@ -101,7 +103,7 @@
     /**
      * Test ModuleReader to module in runtime image
      */
-    public void testImage() throws Exception {
+    public void testImage() throws IOException {
 
         ModuleFinder finder = ModuleFinder.ofSystem();
         ModuleReference mref = finder.find(BASE_MODULE).get();
@@ -119,6 +121,7 @@
                 testFind(reader, name, expectedBytes);
                 testOpen(reader, name, expectedBytes);
                 testRead(reader, name, expectedBytes);
+                testList(reader, name);
 
             }
 
@@ -168,7 +171,7 @@
     /**
      * Test ModuleReader to exploded module
      */
-    public void testExplodedModule() throws Exception {
+    public void testExplodedModule() throws IOException {
         test(MODS_DIR);
     }
 
@@ -176,7 +179,7 @@
     /**
      * Test ModuleReader to modular JAR
      */
-    public void testModularJar() throws Exception {
+    public void testModularJar() throws IOException {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 
         // jar cf mlib/${TESTMODULE}.jar -C mods .
@@ -190,7 +193,7 @@
     /**
      * Test ModuleReader to JMOD
      */
-    public void testJMod() throws Exception {
+    public void testJMod() throws IOException {
         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 
         // jmod create --class-path mods/${TESTMODULE}  mlib/${TESTMODULE}.jmod
@@ -211,13 +214,10 @@
      * 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 {
+    void test(Path mp) throws IOException {
 
-        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);
-        }
+        ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess()
+            .newModulePath(Runtime.version(), true, mp);
 
         ModuleReference mref = finder.find(TEST_MODULE).get();
         ModuleReader reader = mref.open();
@@ -234,6 +234,7 @@
                 testFind(reader, name, expectedBytes);
                 testOpen(reader, name, expectedBytes);
                 testRead(reader, name, expectedBytes);
+                testList(reader, name);
             }
 
             // test "not found"
@@ -275,13 +276,18 @@
             reader.read(TEST_RESOURCES[0]);
             assertTrue(false);
         } catch (IOException expected) { }
+
+        try {
+            reader.list();
+            assertTrue(false);
+        } catch (IOException expected) { }
     }
 
     /**
      * Test ModuleReader#find
      */
     void testFind(ModuleReader reader, String name, byte[] expectedBytes)
-        throws Exception
+        throws IOException
     {
         Optional<URI> ouri = reader.find(name);
         assertTrue(ouri.isPresent());
@@ -301,7 +307,7 @@
      * Test ModuleReader#open
      */
     void testOpen(ModuleReader reader, String name, byte[] expectedBytes)
-        throws Exception
+        throws IOException
     {
         Optional<InputStream> oin = reader.open(name);
         assertTrue(oin.isPresent());
@@ -317,7 +323,7 @@
      * Test ModuleReader#read
      */
     void testRead(ModuleReader reader, String name, byte[] expectedBytes)
-        throws Exception
+        throws IOException
     {
         Optional<ByteBuffer> obb = reader.read(name);
         assertTrue(obb.isPresent());
@@ -334,4 +340,24 @@
         }
     }
 
+    /**
+     * Test ModuleReader#list
+     */
+    void testList(ModuleReader reader, String name) throws IOException {
+        List<String> list = reader.list().collect(Collectors.toList());
+        Set<String> names = new HashSet<>(list);
+        assertTrue(names.size() == list.size()); // no duplicates
+
+        assertTrue(names.contains("module-info.class"));
+        assertTrue(names.contains(name));
+
+        // all resources should be locatable via find
+        for (String e : names) {
+            assertTrue(reader.find(e).isPresent());
+        }
+
+        // should not contain directories
+        names.forEach(e -> assertFalse(e.endsWith("/")));
+    }
+
 }
--- a/jdk/test/java/lang/module/ModuleReader/MultiReleaseJarTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,216 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * @test
- * @library /lib/testlibrary
- * @modules java.base/jdk.internal.module
- * @build MultiReleaseJarTest JarUtils
- * @run testng MultiReleaseJarTest
- * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarTest
- * @summary Basic test of ModuleReader with a modular JAR that is also a
- *          multi-release JAR
- */
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-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.net.URLConnection;
-import java.nio.ByteBuffer;
-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.Manifest;
-import java.util.stream.Collectors;
-
-import jdk.internal.module.ModuleInfoWriter;
-
-import org.testng.annotations.Test;
-import static org.testng.Assert.*;
-
-/**
- * Exercises ModuleReader with a modular JAR containing the following files:
- *
- * <pre>{@code
- *     module-info.class
- *     META-INF/versions/<version>/module.class
- * }</pre>
- *
- * The module-info.class in the top-level directory is the binary form of:
- * <pre>{@code
- *     module jdk.test {
- *         requires java.base;
- *     }
- * }</pre>
- *
- * The module-info.class in the versioned section is the binary form of:
- * <pre>{@code
- *     module jdk.test {
- *         requires java.base;
- *         requires jdk.unsupported;
- *     }
- * }</pre>
- */
-
-@Test
-public class MultiReleaseJarTest {
-
-    // Java SE/JDK major release
-    private static final int RELEASE = Runtime.version().major();
-
-    // the name of the test module
-    private static final String MODULE_NAME = "jdk.test";
-
-    private static final String MODULE_INFO_CLASS = "module-info.class";
-
-    /**
-     * Uses the ModuleFinder API to locate the module packaged as a modular
-     * and mutli-release JAR and then creates a ModuleReader to access the
-     * contents of the module.
-     */
-    public void testMultiReleaseJar() throws IOException {
-
-        // are multi-release JARs enabled?
-        String s = System.getProperty("jdk.util.jar.enableMultiRelease");
-        boolean multiRelease = (s == null || Boolean.parseBoolean(s));
-
-        // create the multi-release modular JAR
-        Path jarfile = createJarFile();
-
-        // find the module
-        ModuleFinder finder = ModuleFinder.of(jarfile);
-        Optional<ModuleReference> omref = finder.find(MODULE_NAME);
-        assertTrue((omref.isPresent()));
-        ModuleReference mref = omref.get();
-
-        // test that correct module-info.class was read
-        checkDescriptor(mref.descriptor(), multiRelease);
-
-        // test ModuleReader
-        try (ModuleReader reader = mref.open()) {
-
-            // open resource
-            Optional<InputStream> oin = reader.open(MODULE_INFO_CLASS);
-            assertTrue(oin.isPresent());
-            try (InputStream in = oin.get()) {
-                checkDescriptor(ModuleDescriptor.read(in), multiRelease);
-            }
-
-            // read resource
-            Optional<ByteBuffer> obb = reader.read(MODULE_INFO_CLASS);
-            assertTrue(obb.isPresent());
-            ByteBuffer bb = obb.get();
-            try {
-                checkDescriptor(ModuleDescriptor.read(bb), multiRelease);
-            } finally {
-                reader.release(bb);
-            }
-
-            // find resource
-            Optional<URI> ouri = reader.find(MODULE_INFO_CLASS);
-            assertTrue(ouri.isPresent());
-            URI uri = ouri.get();
-
-            String expectedTail = "!/";
-            if (multiRelease)
-                expectedTail += "META-INF/versions/" + RELEASE + "/";
-            expectedTail += MODULE_INFO_CLASS;
-            assertTrue(uri.toString().endsWith(expectedTail));
-
-            URLConnection uc = uri.toURL().openConnection();
-            uc.setUseCaches(false);
-            try (InputStream in = uc.getInputStream()) {
-                checkDescriptor(ModuleDescriptor.read(in), multiRelease);
-            }
-
-        }
-
-    }
-
-    /**
-     * Checks that the module descriptor is the expected module descriptor.
-     * When the multi release JAR feature is enabled then the module
-     * descriptor is expected to have been read from the versioned section
-     * of the JAR file.
-     */
-    private void checkDescriptor(ModuleDescriptor descriptor, boolean multiRelease) {
-        Set<String> requires = descriptor.requires().stream()
-                .map(ModuleDescriptor.Requires::name)
-                .collect(Collectors.toSet());
-        assertTrue(requires.contains("java.base"));
-        assertTrue(requires.contains("jdk.unsupported") == multiRelease);
-    }
-
-    /**
-     * Creates the modular JAR for the test, returning the Path to the JAR file.
-     */
-    private Path createJarFile() throws IOException {
-
-        // module descriptor for top-level directory
-        ModuleDescriptor descriptor1
-            = new ModuleDescriptor.Builder(MODULE_NAME)
-                .requires("java.base")
-                .build();
-
-        // module descriptor for versioned section
-        ModuleDescriptor descriptor2
-            = new ModuleDescriptor.Builder(MODULE_NAME)
-                .requires("java.base")
-                .requires("jdk.unsupported")
-                .build();
-
-        Path top = Paths.get(MODULE_NAME);
-        Files.createDirectories(top);
-
-        Path mi1 = Paths.get(MODULE_INFO_CLASS);
-        try (OutputStream out = Files.newOutputStream(top.resolve(mi1))) {
-            ModuleInfoWriter.write(descriptor1, out);
-        }
-
-        Path vdir = Paths.get("META-INF", "versions", Integer.toString(RELEASE));
-        Files.createDirectories(top.resolve(vdir));
-
-        Path mi2 = vdir.resolve(MODULE_INFO_CLASS);
-        try (OutputStream out = Files.newOutputStream(top.resolve(mi2))) {
-            ModuleInfoWriter.write(descriptor2, out);
-        }
-
-        Manifest man = new Manifest();
-        Attributes attrs = man.getMainAttributes();
-        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
-        attrs.put(Attributes.Name.MULTI_RELEASE, "true");
-
-        Path jarfile = Paths.get(MODULE_NAME + ".jar");
-        JarUtils.createJarFile(jarfile, man, top, mi1, mi2);
-
-        return jarfile;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/module/MultiReleaseJarTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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
+ * @build MultiReleaseJarTest JarUtils
+ * @run testng MultiReleaseJarTest
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarTest
+ * @summary Basic test of modular JARs as multi-release JARs
+ */
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+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.net.URLConnection;
+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.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.Attributes;
+import java.util.jar.Manifest;
+
+import jdk.internal.module.ModuleInfoWriter;
+
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+
+@Test
+public class MultiReleaseJarTest {
+
+    private static final String MODULE_INFO = "module-info.class";
+
+    private static final int RELEASE = Runtime.version().major();
+
+    // are multi-release JARs enabled?
+    private static final boolean MULTI_RELEASE;
+    static {
+        String s = System.getProperty("jdk.util.jar.enableMultiRelease");
+        MULTI_RELEASE = (s == null || Boolean.parseBoolean(s));
+    }
+
+    /**
+     * Basic test of a multi-release JAR.
+     */
+    public void testBasic() throws Exception {
+        String name = "m1";
+
+        ModuleDescriptor descriptor = new ModuleDescriptor.Builder(name)
+                .requires("java.base")
+                .build();
+
+        Path jar = new JarBuilder(name)
+                .moduleInfo("module-info.class", descriptor)
+                .resource("p/Main.class")
+                .resource("p/Helper.class")
+                .resource("META-INF/versions/9/p/Helper.class")
+                .resource("META-INF/versions/9/p/internal/Helper9.class")
+                .build();
+
+        // find the module
+        ModuleFinder finder = ModuleFinder.of(jar);
+        Optional<ModuleReference> omref = finder.find(name);
+        assertTrue((omref.isPresent()));
+        ModuleReference mref = omref.get();
+
+        // check module packages
+        descriptor = mref.descriptor();
+        Set<String> packages = descriptor.packages();
+        assertTrue(packages.contains("p"));
+        if (MULTI_RELEASE) {
+            assertTrue(packages.size() == 2);
+            assertTrue(packages.contains("p.internal"));
+        } else {
+            assertTrue(packages.size() == 1);
+        }
+    }
+
+    /**
+     * Test a multi-release JAR with a module-info.class in the versioned
+     * section of the JAR.
+     */
+    public void testModuleInfoInVersionedSection() throws Exception {
+        String name = "m1";
+
+        ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder(name)
+                .requires("java.base")
+                .build();
+
+        // module descriptor for versioned section
+        ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder(name)
+                .requires("java.base")
+                .requires("jdk.unsupported")
+                .build();
+
+        Path jar = new JarBuilder(name)
+                .moduleInfo(MODULE_INFO, descriptor1)
+                .resource("p/Main.class")
+                .resource("p/Helper.class")
+                .moduleInfo("META-INF/versions/9/" + MODULE_INFO, descriptor2)
+                .resource("META-INF/versions/9/p/Helper.class")
+                .resource("META-INF/versions/9/p/internal/Helper9.class")
+                .build();
+
+        // find the module
+        ModuleFinder finder = ModuleFinder.of(jar);
+        Optional<ModuleReference> omref = finder.find(name);
+        assertTrue((omref.isPresent()));
+        ModuleReference mref = omref.get();
+
+        // ensure that the right module-info.class is loaded
+        ModuleDescriptor descriptor = mref.descriptor();
+        assertEquals(descriptor.name(), name);
+        if (MULTI_RELEASE) {
+            assertEquals(descriptor.requires(), descriptor2.requires());
+        } else {
+            assertEquals(descriptor.requires(), descriptor1.requires());
+        }
+    }
+
+    /**
+     * Test multi-release JAR as an automatic module.
+     */
+    public void testAutomaticModule() throws Exception {
+        String name = "m";
+
+        Path jar = new JarBuilder(name)
+                .resource("p/Main.class")
+                .resource("p/Helper.class")
+                .resource("META-INF/versions/9/p/Helper.class")
+                .resource("META-INF/versions/9/p/internal/Helper9.class")
+                .build();
+
+        // find the module
+        ModuleFinder finder = ModuleFinder.of(jar);
+        Optional<ModuleReference> omref = finder.find(name);
+        assertTrue((omref.isPresent()));
+        ModuleReference mref = omref.get();
+
+        // check module packages
+        ModuleDescriptor descriptor = mref.descriptor();
+        Set<String> packages = descriptor.packages();
+        if (MULTI_RELEASE) {
+            assertTrue(packages.size() == 2);
+            assertTrue(packages.contains("p.internal"));
+        } else {
+            assertTrue(packages.size() == 1);
+        }
+    }
+
+    /**
+     * Exercise ModuleReader on a multi-release JAR
+     */
+    public void testModuleReader() throws Exception {
+        String name = "m1";
+
+        ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder(name)
+                .requires("java.base")
+                .build();
+
+        // module descriptor for versioned section
+        ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder(name)
+                .requires("java.base")
+                .requires("jdk.unsupported")
+                .build();
+
+        Path jar = new JarBuilder(name)
+                .moduleInfo(MODULE_INFO, descriptor1)
+                .moduleInfo("META-INF/versions/9/" + MODULE_INFO, descriptor2)
+                .build();
+
+        // find the module
+        ModuleFinder finder = ModuleFinder.of(jar);
+        Optional<ModuleReference> omref = finder.find(name);
+        assertTrue((omref.isPresent()));
+        ModuleReference mref = omref.get();
+
+        ModuleDescriptor expected;
+        if (MULTI_RELEASE) {
+            expected = descriptor2;
+        } else {
+            expected = descriptor1;
+        }
+
+        // test ModuleReader by reading module-info.class resource
+        try (ModuleReader reader = mref.open()) {
+
+            // open resource
+            Optional<InputStream> oin = reader.open(MODULE_INFO);
+            assertTrue(oin.isPresent());
+            try (InputStream in = oin.get()) {
+                checkRequires(ModuleDescriptor.read(in), expected);
+            }
+
+            // read resource
+            Optional<ByteBuffer> obb = reader.read(MODULE_INFO);
+            assertTrue(obb.isPresent());
+            ByteBuffer bb = obb.get();
+            try {
+                checkRequires(ModuleDescriptor.read(bb), expected);
+            } finally {
+                reader.release(bb);
+            }
+
+            // find resource
+            Optional<URI> ouri = reader.find(MODULE_INFO);
+            assertTrue(ouri.isPresent());
+            URI uri = ouri.get();
+
+            String expectedTail = "!/";
+            if (MULTI_RELEASE)
+                expectedTail += "META-INF/versions/" + RELEASE + "/";
+            expectedTail += MODULE_INFO;
+            assertTrue(uri.toString().endsWith(expectedTail));
+
+            URLConnection uc = uri.toURL().openConnection();
+            uc.setUseCaches(false);
+            try (InputStream in = uc.getInputStream()) {
+                checkRequires(ModuleDescriptor.read(in), expected);
+            }
+
+        }
+    }
+
+    /**
+     * Check that two ModuleDescriptor have the same requires
+     */
+    static void checkRequires(ModuleDescriptor md1, ModuleDescriptor md2) {
+        assertEquals(md1.requires(), md2.requires());
+    }
+
+    /**
+     * A builder of multi-release JAR files.
+     */
+    static class JarBuilder {
+        private String name;
+        private Set<String> resources = new HashSet<>();
+        private Map<String, ModuleDescriptor> descriptors = new HashMap<>();
+
+        JarBuilder(String name) {
+            this.name = name;
+        }
+
+        /**
+         * Adds a module-info.class to the JAR file.
+         */
+        JarBuilder moduleInfo(String name, ModuleDescriptor descriptor) {
+            descriptors.put(name, descriptor);
+            return this;
+        }
+
+        /**
+         * Adds a dummy resource to the JAR file.
+         */
+        JarBuilder resource(String name) {
+            resources.add(name);
+            return this;
+        }
+
+        /**
+         * Create the multi-release JAR, returning its file path.
+         */
+        Path build() throws Exception {
+            Path dir = Files.createTempDirectory(Paths.get(""), "jar");
+            List<Path> files = new ArrayList<>();
+
+            // write the module-info.class
+            for (Map.Entry<String, ModuleDescriptor> e : descriptors.entrySet()) {
+                String name = e.getKey();
+                ModuleDescriptor descriptor = e.getValue();
+                Path mi = Paths.get(name.replace('/', File.separatorChar));
+                Path parent = dir.resolve(mi).getParent();
+                if (parent != null)
+                    Files.createDirectories(parent);
+                try (OutputStream out = Files.newOutputStream(dir.resolve(mi))) {
+                    ModuleInfoWriter.write(descriptor, out);
+                }
+                files.add(mi);
+            }
+
+            // write the dummy resources
+            for (String name : resources) {
+                Path file = Paths.get(name.replace('/', File.separatorChar));
+                // create dummy resource
+                Path parent = dir.resolve(file).getParent();
+                if (parent != null)
+                    Files.createDirectories(parent);
+                Files.createFile(dir.resolve(file));
+                files.add(file);
+            }
+
+            Manifest man = new Manifest();
+            Attributes attrs = man.getMainAttributes();
+            attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
+            attrs.put(Attributes.Name.MULTI_RELEASE, "true");
+
+            Path jarfile = Paths.get(name + ".jar");
+            JarUtils.createJarFile(jarfile, man, dir, files.toArray(new Path[0]));
+            return jarfile;
+        }
+    }
+}
--- a/jdk/test/java/net/URLClassLoader/NullURLTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/URLClassLoader/NullURLTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -109,7 +109,7 @@
             failures++;
         }
         try {
-            loader = new URLClassLoader(null, null, null);
+            loader = new URLClassLoader((URL[])null, null, null);
             System.err.println("URLClassLoader(null, null, null) did not throw NPE");
             failures++;
         } catch (NullPointerException e) {
--- a/jdk/test/java/net/URLPermission/nstest/LookupTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/URLPermission/nstest/LookupTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -22,124 +22,195 @@
  */
 
 /**
- * This is a simple smoke test of the HttpURLPermission mechanism, which
- * checks for either IOException (due to unknown host) or SecurityException
- * due to lack of permission to connect
+ * @test
+ * @summary A simple smoke test of the HttpURLPermission mechanism, which checks
+ *          for either IOException (due to unknown host) or SecurityException
+ *          due to lack of permission to connect
+ * @run main/othervm LookupTest
  */
 
-import java.net.*;
-import java.io.*;
-import jdk.testlibrary.Utils;
+import java.io.BufferedWriter;
+import java.io.FilePermission;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.NetPermission;
+import java.net.ProxySelector;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketPermission;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLPermission;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import static java.nio.charset.StandardCharsets.US_ASCII;
 
 public class LookupTest {
 
-    static void test(
-        String url, boolean throwsSecException, boolean throwsIOException)
-    {
+    static int port;
+    static volatile ServerSocket serverSocket;
+
+    static void test(String url,
+                     boolean throwsSecException,
+                     boolean throwsIOException) {
+        ProxySelector.setDefault(null);
+        URL u;
+        InputStream is = null;
         try {
-            ProxySelector.setDefault(null);
-            URL u = new URL(url);
-            System.err.println ("Connecting to " + u);
+            u = new URL(url);
+            System.err.println("Connecting to " + u);
             URLConnection urlc = u.openConnection();
-            InputStream is = urlc.getInputStream();
+            is = urlc.getInputStream();
         } catch (SecurityException e) {
             if (!throwsSecException) {
-                throw new RuntimeException ("(1) was not expecting ", e);
+                throw new RuntimeException("Unexpected SecurityException:", e);
+            }
+            return;
+        } catch (IOException e) {
+            if (!throwsIOException) {
+                System.err.println("Unexpected IOException:" + e.getMessage());
+                throw new RuntimeException(e);
             }
             return;
-        } catch (IOException ioe) {
-            if (!throwsIOException) {
-                throw new RuntimeException ("(2) was not expecting ", ioe);
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    System.err.println("Unexpected IOException:" + e.getMessage());
+                    throw new RuntimeException(e);
+                }
             }
-            return;
         }
+
         if (throwsSecException || throwsIOException) {
-            System.err.printf ("was expecting a %s\n", throwsSecException ?
-                "security exception" : "IOException");
+            System.err.printf("was expecting a %s\n", throwsSecException
+                    ? "security exception" : "IOException");
             throw new RuntimeException("was expecting an exception");
         }
     }
 
-    static int port;
-    static ServerSocket serverSocket;
+    static final String CWD = System.getProperty("user.dir", ".");
 
     public static void main(String args[]) throws Exception {
-
-
-        String cmd = args[0];
-        if (cmd.equals("-getport")) {
-            port = Utils.getFreePort();
-            System.out.print(port);
-        } else if (cmd.equals("-runtest")) {
-            port = Integer.parseInt(args[1]);
-            String hostsFileName = System.getProperty("user.dir", ".") + "/LookupTestHosts";
-            System.setProperty("jdk.net.hosts.file", hostsFileName);
-            addMappingToHostsFile("allowedAndFound.com", "127.0.0.1", hostsFileName, false);
-            addMappingToHostsFile("notAllowedButFound.com", "99.99.99.99", hostsFileName, true);
-            // name "notAllowedAndNotFound.com" is not in map
-            // name "allowedButNotfound.com" is not in map
-            try {
-                startServer();
-
-                System.setSecurityManager(new SecurityManager());
-
-                test("http://allowedAndFound.com:" + port + "/foo", false, false);
-
-                test("http://notAllowedButFound.com:" + port + "/foo", true, false);
-
-                test("http://allowedButNotfound.com:" + port + "/foo", false, true);
-
-                test("http://notAllowedAndNotFound.com:" + port + "/foo", true, false);
-            } finally {
-                serverSocket.close();
-            }
-        } else {
-            throw new RuntimeException("Bad invocation: " + cmd);
+        String hostsFileName = CWD + "/LookupTestHosts";
+        System.setProperty("jdk.net.hosts.file", hostsFileName);
+        addMappingToHostsFile("allowedAndFound.com",
+                              "127.0.0.1",
+                              hostsFileName,
+                              false);
+        addMappingToHostsFile("notAllowedButFound.com",
+                              "99.99.99.99",
+                              hostsFileName,
+                              true);
+        // name "notAllowedAndNotFound.com" is not in map
+        // name "allowedButNotfound.com" is not in map
+        Server server = new Server();
+        try {
+            Policy.setPolicy(new LookupTestPolicy());
+            System.setSecurityManager(new SecurityManager());
+            server.start();
+            test("http://allowedAndFound.com:"       + port + "/foo", false, false);
+            test("http://notAllowedButFound.com:"    + port + "/foo", true, false);
+            test("http://allowedButNotfound.com:"    + port + "/foo", false, true);
+            test("http://notAllowedAndNotFound.com:" + port + "/foo", true, false);
+        } finally {
+            server.terminate();
         }
     }
 
-    static Thread server;
+    static class Server extends Thread {
+        private volatile boolean done;
 
-    static class Server extends Thread {
+        public Server() throws IOException {
+            serverSocket = new ServerSocket(0);
+            port = serverSocket.getLocalPort();
+        }
+
         public void run() {
-            byte[] buf = new byte[1000];
             try {
-                while (true) {
-                    Socket s = serverSocket.accept();
-                    InputStream i = s.getInputStream();
-                    i.read(buf);
-                    OutputStream o = s.getOutputStream();
-                    String rsp = "HTTP/1.1 200 Ok\r\n" +
-                        "Connection: close\r\nContent-length: 0\r\n\r\n";
-                    o.write(rsp.getBytes());
-                    o.close();
+                while (!done) {
+                    try (Socket s = serverSocket.accept()) {
+                        readOneRequest(s.getInputStream());
+                        OutputStream o = s.getOutputStream();
+                        String rsp = "HTTP/1.1 200 Ok\r\n" +
+                                     "Connection: close\r\n" +
+                                     "Content-length: 0\r\n\r\n";
+                        o.write(rsp.getBytes(US_ASCII));
+                    }
                 }
             } catch (IOException e) {
-                return;
+                if (!done)
+                    e.printStackTrace();
             }
-            }
-    }
+        }
+
+        void terminate() {
+            done = true;
+            try { serverSocket.close(); }
+            catch (IOException unexpected) { unexpected.printStackTrace(); }
+        }
+
+        static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' };
 
-    static void startServer() {
-        try {
-            serverSocket = new ServerSocket(port);
-            server = new Server();
-            server.start();
-        } catch (Exception e) {
-            throw new RuntimeException ("Test failed to initialize", e);
+        // Read until the end of a HTTP request
+        void readOneRequest(InputStream is) throws IOException {
+            int requestEndCount = 0, r;
+            while ((r = is.read()) != -1) {
+                if (r == requestEnd[requestEndCount]) {
+                    requestEndCount++;
+                    if (requestEndCount == 4) {
+                        break;
+                    }
+                } else {
+                    requestEndCount = 0;
+                }
+            }
         }
     }
 
-    private static void addMappingToHostsFile (String host,
-                                               String addr,
-                                               String hostsFileName,
-                                               boolean append)
-                                             throws Exception {
+    private static void addMappingToHostsFile(String host,
+                                              String addr,
+                                              String hostsFileName,
+                                              boolean append)
+        throws IOException
+    {
         String mapping = addr + " " + host;
-        try (PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(
-                new FileWriter(hostsFileName, append)))) {
+        try (FileWriter fr = new FileWriter(hostsFileName, append);
+             PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(fr))) {
             hfPWriter.println(mapping);
-}
+        }
     }
 
+    static class LookupTestPolicy extends Policy {
+        final PermissionCollection perms = new Permissions();
+
+        LookupTestPolicy() throws Exception {
+            perms.add(new NetPermission("setProxySelector"));
+            perms.add(new SocketPermission("localhost:1024-", "resolve,accept"));
+            perms.add(new URLPermission("http://allowedAndFound.com:" + port + "/-", "*:*"));
+            perms.add(new URLPermission("http://allowedButNotfound.com:" + port + "/-", "*:*"));
+            perms.add(new FilePermission("<<ALL FILES>>", "read,write,delete"));
+            //perms.add(new PropertyPermission("java.io.tmpdir", "read"));
+        }
+
+        public PermissionCollection getPermissions(ProtectionDomain domain) {
+            return perms;
+        }
+
+        public PermissionCollection getPermissions(CodeSource codesource) {
+            return perms;
+        }
+
+        public boolean implies(ProtectionDomain domain, Permission perm) {
+            return perms.implies(perm);
+        }
+    }
 }
--- a/jdk/test/java/net/URLPermission/nstest/lookup.sh	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-#!/bin/sh
-#
-# 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
-# @library /lib/testlibrary
-# @build jdk.testlibrary.*
-# @compile -XDignore.symbol.file=true LookupTest.java
-# @run shell/timeout=50 lookup.sh
-# @key intermittent
-#
-
-OS=`uname -s`
-case ${OS} in
-Windows_* | CYGWIN*)
-    PS=";"
-    FS="\\"
-    ;;
-*)
-    PS=":"
-    FS="/"
-    ;;
-esac
-
-port=`${TESTJAVA}/bin/java -cp ${TESTCLASSPATH} LookupTest -getport`
-
-cat << POLICY > policy
-grant {
-    permission java.net.URLPermission "http://allowedAndFound.com:${port}/-", "*:*";
-    permission java.net.URLPermission "http://allowedButNotfound.com:${port}/-", "*:*";
-    permission java.net.NetPermission "setProxySelector";
-    permission java.io.FilePermission "<<ALL FILES>>", "read,write,delete";
-    permission java.util.PropertyPermission "java.io.tmpdir", "read";
-
-    // needed for HttpServer
-    permission "java.net.SocketPermission" "localhost:1024-", "resolve,accept";
-};
-POLICY
-
-${TESTJAVA}/bin/java ${TESTVMOPTS} \
-    -Djava.security.policy=file:./policy \
-    -Dtest.src=${TESTSRC} \
-    -cp ${TESTCLASSPATH}${PS}${TESTSRC} LookupTest -runtest ${port}
--- a/jdk/test/java/net/httpclient/APIErrors.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/APIErrors.java	Fri Nov 11 16:44:36 2016 +0100
@@ -21,10 +21,11 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8087112
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @library /lib/testlibrary/
  * @build jdk.testlibrary.SimpleSSLContext ProxyServer
@@ -35,13 +36,23 @@
  */
 //package javaapplication16;
 
-import com.sun.net.httpserver.*;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsServer;
 import java.io.IOException;
-import java.net.*;
-import java.net.http.*;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.*;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
 import java.util.function.Supplier;
 
 /**
--- a/jdk/test/java/net/httpclient/ManyRequests.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/ManyRequests.java	Fri Nov 11 16:44:36 2016 +0100
@@ -21,10 +21,11 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8087112
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @library /lib/testlibrary/ /
  * @build jdk.testlibrary.SimpleSSLContext EchoHandler
@@ -36,7 +37,9 @@
 
 //package javaapplication16;
 
-import com.sun.net.httpserver.*;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsParameters;
+import com.sun.net.httpserver.HttpsServer;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.net.http.HttpClient;
@@ -48,9 +51,10 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Random;
-import java.util.logging.*;
+import java.util.logging.Logger;
+import java.util.logging.Level;
 import java.util.concurrent.CompletableFuture;
-import javax.net.ssl.*;
+import javax.net.ssl.SSLContext;
 import jdk.testlibrary.SimpleSSLContext;
 
 public class ManyRequests {
--- a/jdk/test/java/net/httpclient/RequestBodyTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/RequestBodyTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -21,9 +21,10 @@
  * questions.
  */
 
-/**
+/*
  * @test @bug 8087112
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @library /lib/testlibrary/ /
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
--- a/jdk/test/java/net/httpclient/SmokeTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/SmokeTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -21,10 +21,11 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8087112
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @library /lib/testlibrary/ /
  * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
@@ -33,13 +34,40 @@
  * @run main/othervm SmokeTest
  */
 
-import com.sun.net.httpserver.*;
-import java.net.*;
-import java.net.http.*;
-import java.io.*;
-import java.util.concurrent.*;
-import javax.net.ssl.*;
-import java.nio.file.*;
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsConfigurator;
+import com.sun.net.httpserver.HttpsParameters;
+import com.sun.net.httpserver.HttpsServer;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
--- a/jdk/test/java/net/httpclient/security/Driver.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/security/Driver.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,7 @@
  * @bug 8087112
  * @library /lib/testlibrary/
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @build jdk.testlibrary.SimpleSSLContext jdk.testlibrary.Utils
  * @compile ../../../../com/sun/net/httpserver/LogFilter.java
--- a/jdk/test/java/net/httpclient/security/Security.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/httpclient/security/Security.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,10 +23,11 @@
  * questions.
  */
 
-/**
+/*
  * @test
  * @bug 8087112
  * @modules java.httpclient
+ *          java.logging
  *          jdk.httpserver
  * @library /lib/testlibrary/
  * @build jdk.testlibrary.SimpleSSLContext
@@ -50,14 +51,27 @@
 
 // Tests 1, 10, 11 and 12 executed from Driver
 
-import com.sun.net.httpserver.*;
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import com.sun.net.httpserver.HttpsServer;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.File;
 import java.io.OutputStream;
 import java.lang.reflect.Constructor;
-import java.net.*;
-import java.net.http.*;
+import java.net.BindException;
+import java.net.InetSocketAddress;
+import java.net.ProxySelector;
+import java.net.URI;
+import java.net.URLClassLoader;
+import java.net.URL;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -66,13 +80,15 @@
 import java.nio.file.StandardCopyOption;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.concurrent.*;
-import java.util.function.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ExecutorService;
+import java.util.function.LongConsumer;
 import java.util.logging.ConsoleHandler;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.lang.reflect.InvocationTargetException;
-import java.net.BindException;
 
 /**
  * Security checks test
--- a/jdk/test/java/net/ipv6tests/Tests.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/ipv6tests/Tests.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2010, 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
@@ -139,11 +139,17 @@
 
     /* check the time got is within 50% of the time expected */
     public static void checkTime (long got, long expected) {
-        dprintln ("checkTime: got " + got + " expected " + expected);
-        long upper = expected + (expected / 2);
-        long lower = expected - (expected / 2);
+        checkTime(got, expected, expected);
+    }
+
+    /* check the time got is between start and end, given 50% tolerance */
+    public static void checkTime(long got, long start, long end) {
+        dprintln("checkTime: got = " + got + " start = " + start + " end = " + end);
+        long upper = end + (end / 2);
+        long lower = start - (start / 2);
         if (got > upper || got < lower) {
-            throw new RuntimeException ("checkTime failed: got " + got + " expected " + expected);
+            throw new RuntimeException("checkTime failed: got " + got
+                    + ", expected between " + start + " and " + end);
         }
     }
 
--- a/jdk/test/java/net/ipv6tests/UdpTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/net/ipv6tests/UdpTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,7 +24,6 @@
 /*
  * @test
  * @bug 4868820
- * @key intermittent
  * @summary IPv6 support for Windows XP and 2003 server
  */
 
@@ -159,7 +158,7 @@
         });
         t1 = System.currentTimeMillis();
         s1.receive (new DatagramPacket (new byte [128], 128));
-        checkTime (System.currentTimeMillis() - t1, 4000);
+        checkTime (System.currentTimeMillis() - t1, 2000, 10000);
         s1.close ();
         s2.close ();
         System.out.println ("Test2: OK");
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java	Fri Nov 11 16:44:36 2016 +0100
@@ -40,7 +40,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe CheckActivateRef_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe CheckActivateRef_Stub
  * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=true CheckActivateRef
  * @run main/othervm/policy=security.policy/timeout=240 -Djava.rmi.server.ignoreStubClasses=false CheckActivateRef
  * @key intermittent
@@ -118,7 +119,7 @@
 
             // start an rmid.
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -2,4 +2,6 @@
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.rmi.server.useDynamicProxies=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkActivateRef/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -38,4 +38,6 @@
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
 
   permission java.lang.RuntimePermission "getClassLoader";
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID MyRMI CheckAnnotations_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider MyRMI CheckAnnotations_Stub
  * @run main/othervm/policy=security.policy/timeout=480 CheckAnnotations
  */
 
@@ -77,7 +78,7 @@
 
             // start an rmid.
             RMID.removeLog();
-            rmid = RMID.createRMID(rmidOut, rmidErr, false);
+            rmid = RMID.createRMIDOnEphemeralPort(rmidOut, rmidErr, false);
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
@@ -228,6 +229,7 @@
                 return false;
             }
 
+
             // just make sure that last two strings are what we expect.
             if (execOut.equals("ExecGroup-" + iteration)
                 && (new String(destOut.substring(0,4)).equals("out" +
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkAnnotations/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -28,4 +28,7 @@
 
   // test needs to export rmid and communicate with objects on arbitrary ports
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
  *     MyRMI ActivatableImpl ActivatableImpl ActivatableImpl_Stub
  * @run main/othervm/policy=security.policy/timeout=150 CheckImplClassLoader
  */
@@ -80,7 +81,7 @@
                 TestParams.defaultSecurityManager);
 
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             System.err.println("Create activation group in this VM");
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkImplClassLoader/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -39,4 +39,7 @@
 
   // test needs to export rmid and communicate with objects on arbitrary ports
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     ActivateMe CheckRegisterInLog_Stub
  * @run main/othervm/policy=security.policy/timeout=240 CheckRegisterInLog
  */
@@ -99,7 +100,7 @@
              * Start up activation system daemon "rmid".
              */
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/checkRegisterInLog/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -31,4 +31,7 @@
 
   // allow exporting object with non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe
  * @run main/othervm/policy=security.policy/timeout=240 CreatePrivateActivatable
  */
 
@@ -103,7 +104,7 @@
 
             // start an rmid.
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/createPrivateActivable/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -31,4 +31,7 @@
 
   // allow exporting object with non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,7 +35,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     Foo FooReceiverImpl FooReceiverImpl_Stub Bar
  * @run main/othervm/policy=security.policy/timeout=240 DownloadParameterClass
  */
@@ -90,7 +91,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/manual.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -34,4 +34,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/downloadParameterClass/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -35,4 +35,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe ElucidateNoSuchMethod_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe ElucidateNoSuchMethod_Stub
  * @run main/othervm/policy=security.policy/timeout=240 ElucidateNoSuchMethod
  */
 
@@ -91,7 +92,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,7 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/elucidateNoSuchMethod/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -37,4 +37,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ExtLoadedImplTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -37,7 +37,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
             Properties p = new Properties();
             p.put("java.security.policy",
--- a/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/extLoadedImpl/ext.sh	Fri Nov 11 16:44:36 2016 +0100
@@ -27,7 +27,7 @@
 # loader, the context class loader should remain unchanged (i.e., not be
 # set to the impl's class loader) when the impl is activated.
 # @library ../../../testlibrary
-# @build TestLibrary RMID ActivationLibrary
+# @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
 # @build ExtLoadedImplTest ExtLoadedImpl ExtLoadedImpl_Stub CheckLoader
 # @run shell ext.sh
 
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     ActivateMe ForceLogSnapshot_Stub
  * @run main/othervm/policy=security.policy/timeout=640 ForceLogSnapshot
  */
@@ -129,7 +130,7 @@
                 SNAPSHOT_INTERVAL;
 
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.addOptions(new String[] {option, "-Djava.compiler="});
             rmid.start();
 
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/forceLogSnapshot/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -31,4 +31,7 @@
 
   // allow exporting object with non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe InactiveGroup_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe InactiveGroup_Stub
  * @run main/othervm/policy=security.policy/timeout=240 InactiveGroup
  */
 
@@ -101,7 +102,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/inactiveGroup/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -31,4 +31,7 @@
 
   // allow exporting object with non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  * @run main/othervm/timeout=240 LookupActivationSystem
  */
 
@@ -55,7 +56,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             System.err.println("look up activation system");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/activation/Activatable/lookupActivationSystem/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,4 @@
+grant {
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
+};
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/NestedActivate.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe NestedActivate_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe NestedActivate_Stub
  * @run main/othervm/policy=security.policy/timeout=240 NestedActivate
  */
 
@@ -101,7 +102,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nestedActivate/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -31,4 +31,7 @@
 
   // allow exporting of non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/NonExistentActivatable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     ActivateMe NonExistentActivatable_Stub
  * @run main/othervm/policy=security.policy/timeout=240 NonExistentActivatable
  */
@@ -91,7 +92,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/nonExistentActivatable/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -32,4 +32,6 @@
   // allow exporting object with non-public remote interface
   permission java.rmi.RMIPermission "exportRemoteInterface.ActivateMe";
 
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivateMe RestartCrashedService_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivateMe RestartCrashedService_Stub
  * @run main/othervm/policy=security.policy/timeout=240 RestartCrashedService
  */
 
@@ -119,7 +120,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartCrashedService/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -28,4 +28,7 @@
 
   // test needs to export rmid and communicate with objects on arbitrary ports
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -31,7 +31,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     RestartLatecomer RestartLatecomer_Stub
  * @run main/othervm/policy=security.policy/timeout=240 RestartLatecomer
  */
@@ -166,7 +167,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartLatecomer/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -33,4 +33,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/RestartService.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe RestartService_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe RestartService_Stub
  * @run main/othervm/policy=security.policy/timeout=240 RestartService
  */
 
@@ -129,7 +130,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/restartService/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/restartService/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -33,4 +33,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider
  *     TestSecurityManager RegisteringActivatable ShutdownGracefully_Stub
  * @run main/othervm/policy=security.policy/timeout=700 ShutdownGracefully
  */
@@ -76,7 +77,7 @@
 
             // start an rmid.
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
 
             // rmid needs to run with a security manager that
             // simulates a log problem; rmid should also snapshot
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -2,4 +2,6 @@
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=java.lang.SecurityManager";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Ddummyname=dummyvalue";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/shutdownGracefully/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -25,4 +25,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary ActivateMe UnregisterInactive_Stub
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary ActivateMe UnregisterInactive_Stub
  * @run main/othervm/policy=security.policy/timeout=240 UnregisterInactive
  */
 
@@ -89,7 +90,7 @@
 
         try {
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
             System.err.println("Creating descriptor");
 
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/Activatable/unregisterInactive/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -28,4 +28,7 @@
 
   // allow exporting of remote objects on an arbitrary port.
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,7 +35,8 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary RMID ActivationLibrary
+ *          java.base/sun.nio.ch
+ * @build TestLibrary RMID RMIDSelectorProvider ActivationLibrary
  *     ActivateMe ActivateFails_Stub ShutdownThread
  * @run main/othervm/java.security.policy=security.policy/timeout=240 ActivateFails
  */
@@ -93,7 +94,7 @@
              * First run "rmid" and wait for it to start up.
              */
             RMID.removeLog();
-            rmid = RMID.createRMID();
+            rmid = RMID.createRMIDOnEphemeralPort();
             rmid.start();
 
             /* Cause activation groups to have a security policy that will
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/rmid.security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -1,4 +1,6 @@
 grant {
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.manager=default";
     permission com.sun.rmi.rmid.ExecOptionPermission "-Djava.security.policy=*";
+    permission java.lang.RuntimePermission "selectorProvider";
+    permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/ActivateFailedException/activateFails/security.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -28,4 +28,7 @@
 
   // test needs to export rmid and communicate with objects on arbitrary ports
   permission java.net.SocketPermission "*:1024-", "connect,accept,listen";
+
+  permission java.lang.RuntimePermission "selectorProvider";
+  permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
 };
--- a/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java	Fri Nov 11 16:44:36 2016 +0100
@@ -51,6 +51,8 @@
 import java.rmi.registry.LocateRegistry;
 import java.rmi.registry.Registry;
 import java.rmi.server.UnicastRemoteObject;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
 
 public class RmidViaInheritedChannel implements Callback {
     private static final Object lock = new Object();
@@ -185,6 +187,15 @@
                  */
                 channel = ServerSocketChannel.open();
                 ServerSocket serverSocket = channel.socket();
+
+                // Enable SO_REUSEADDR before binding
+                serverSocket.setOption(SO_REUSEADDR, true);
+
+                // Enable SO_REUSEPORT, if supported, before binding
+                if (serverSocket.supportedOptions().contains(SO_REUSEPORT)) {
+                    serverSocket.setOption(SO_REUSEPORT, true);
+                }
+
                 serverSocket.bind(
                      new InetSocketAddress(InetAddress.getLocalHost(),
                      TestLibrary.RMIDVIAINHERITEDCHANNEL_ACTIVATION_PORT));
--- a/jdk/test/java/rmi/testlibrary/JavaVM.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/testlibrary/JavaVM.java	Fri Nov 11 16:44:36 2016 +0100
@@ -21,8 +21,11 @@
  * questions.
  */
 
+import java.io.BufferedReader;
+import java.io.DataInputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.util.Arrays;
 import java.util.StringTokenizer;
@@ -39,8 +42,8 @@
     protected Process vm = null;
 
     private String classname = "";
-    private String args = "";
-    private String options = "";
+    protected String args = "";
+    protected String options = "";
     private OutputStream outputStream = System.out;
     private OutputStream errorStream = System.err;
     private String policyFileName = null;
@@ -113,7 +116,7 @@
     /**
      * Exec the VM as specified in this object's constructor.
      */
-    public void start() throws IOException {
+    private void start0() throws IOException {
 
         if (vm != null)
             throw new IllegalStateException("JavaVM already started");
@@ -152,12 +155,50 @@
         mesg("command = " + Arrays.asList(javaCommand).toString());
 
         vm = Runtime.getRuntime().exec(javaCommand);
+    }
 
-        /* output from the execed process may optionally be captured. */
+    public void start() throws IOException {
+        start0();
+
+        /* output from the exec'ed process may optionally be captured. */
         outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
         errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
     }
 
+    public int startAndGetPort() throws IOException {
+        start0();
+
+        int port = -1;
+        if (options.contains("java.nio.channels.spi.SelectorProvider=RMIDSelectorProvider")) {
+            // Obtain the server socket channel's ephemeral port number of the
+            // child rmid process.
+            BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(vm.getInputStream()));
+            String s;
+            while ((s = reader.readLine()) != null) {
+                System.out.println(s);
+                int i = s.indexOf(RMID.EPHEMERAL_MSG);
+                if (i != -1) {
+                    String v = s.substring(RMID.EPHEMERAL_MSG.length());
+                    port = Integer.valueOf(v);
+                    break;
+                }
+            }
+            if (port == -1) {
+                // something failed
+                reader = new BufferedReader(new InputStreamReader(vm.getErrorStream()));
+                while ((s = reader.readLine()) != null)
+                    System.err.println(s);
+            }
+        }
+
+        /* output from the exec'ed process may optionally be captured. */
+        outPipe = StreamPipe.plugTogether(vm.getInputStream(), this.outputStream);
+        errPipe = StreamPipe.plugTogether(vm.getErrorStream(), this.errorStream);
+
+        return port;
+    }
+
     public void destroy() {
         if (vm != null) {
             vm.destroy();
--- a/jdk/test/java/rmi/testlibrary/RMID.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/testlibrary/RMID.java	Fri Nov 11 16:44:36 2016 +0100
@@ -49,20 +49,31 @@
 
     public static String MANAGER_OPTION="-Djava.security.manager=";
 
-    /** Test port for rmid */
-    private final int port;
+    /**
+     * Test port for rmid.
+     *
+     * May initially be 0, which means that the child rmid process will choose
+     * an ephemeral port and report it back to the parent process. This field
+     * will then be set to the child rmid's ephemeral port value.
+     */
+    private volatile int port;
+    //private final boolean ephemeralPort
 
     /** Initial log name */
     protected static String log = "log";
     /** rmid's logfile directory; currently must be "." */
     protected static String LOGDIR = ".";
 
+    /** The output message from the child rmid process that directly precedes
+     * the ephemeral port number.*/
+    public static final String EPHEMERAL_MSG = "RmidSelectorProvider-listening-On:";
+
     private static void mesg(Object mesg) {
         System.err.println("RMID: " + mesg.toString());
     }
 
     /** make test options and arguments */
-    private static String makeOptions(boolean debugExec) {
+    private static String makeOptions(int port, boolean debugExec) {
 
         String options = " -Dsun.rmi.server.activation.debugExec=" +
             debugExec;
@@ -87,6 +98,17 @@
         // to avoid spurious timeouts on slow machines.
         options += " -Dsun.rmi.activation.execTimeout=60000";
 
+        if (port == 0) {
+            // Ephemeral port, so have the rmid child process create the
+            // server socket channel and report its port number, over stdin.
+            options += " -classpath " + TestParams.testClassPath;
+            options += " --add-exports=java.base/sun.nio.ch=ALL-UNNAMED";
+            options += " -Djava.nio.channels.spi.SelectorProvider=RMIDSelectorProvider";
+
+            // Disable redirection of System.err to /tmp
+            options += " -Dsun.rmi.server.activation.disableErrRedirect=true";
+        }
+
         return options;
     }
 
@@ -107,7 +129,8 @@
         String args =
             " -log " + (new File(LOGDIR, log)).getAbsolutePath();
 
-        if (includePortArg) {
+        // 0 = ephemeral port, do not include an explicit port number
+        if (includePortArg && port != 0) {
             args += " -port " + port;
         }
 
@@ -160,7 +183,7 @@
                                   boolean debugExec, boolean includePortArg,
                                   int port)
     {
-        String options = makeOptions(debugExec);
+        String options = makeOptions(port, debugExec);
         String args = makeArgs(includePortArg, port);
         RMID rmid = new RMID("sun.rmi.server.Activation", options, args,
                              out, err, port);
@@ -169,6 +192,17 @@
         return rmid;
     }
 
+    public static RMID createRMIDOnEphemeralPort() {
+        return createRMID(System.out, System.err, true, true, 0);
+    }
+
+    public static RMID createRMIDOnEphemeralPort(OutputStream out,
+                                                 OutputStream err,
+                                                 boolean debugExec)
+    {
+        return createRMID(out, err, debugExec, true, 0);
+    }
+
 
     /**
      * Private constructor. RMID instances should be created
@@ -247,7 +281,10 @@
         // a well recognized exception (port already in use...).
 
         mesg("Starting rmid on port " + port + ".");
-        super.start();
+        int p = super.startAndGetPort();
+        if (p != -1)
+            port = p;
+        mesg("Started rmid on port " + port + ".");
 
         // int slopFactor = 1;
         // try {
@@ -271,8 +308,11 @@
 
             try {
                 int status = vm.exitValue();
+                waitFor(TIMEOUT_SHUTDOWN_MS);
                 TestLibrary.bomb("Rmid process exited with status " + status + " after " +
                     (System.currentTimeMillis() - startTime) + "ms.");
+            } catch (InterruptedException | TimeoutException e) {
+                mesg(e);
             } catch (IllegalThreadStateException ignore) { }
 
             // The rmid process is alive; check to see whether
@@ -307,6 +347,8 @@
      */
     public void restart() throws IOException {
         destroy();
+        options = makeOptions(port, true);
+        args = makeArgs(true, port);
         start();
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/testlibrary/RMIDSelectorProvider.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+import java.io.*;
+import java.net.InetSocketAddress;
+import java.net.ProtocolFamily;
+import java.nio.channels.Channel;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.Pipe;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import static java.net.StandardSocketOptions.SO_REUSEADDR;
+import static java.net.StandardSocketOptions.SO_REUSEPORT;
+
+/**
+ * A SelectorProvider, that can be loaded by the child rmid process, whose
+ * inheritedChannel method will create a new server socket channel and report
+ * it back to the parent process, over stdout.
+ */
+public class RMIDSelectorProvider extends SelectorProvider {
+
+    private final SelectorProvider provider;
+    private ServerSocketChannel channel;
+
+    public RMIDSelectorProvider() {
+        provider = sun.nio.ch.DefaultSelectorProvider.create();
+    }
+
+    public DatagramChannel openDatagramChannel()
+        throws IOException
+    {
+        return provider.openDatagramChannel();
+    }
+
+    public DatagramChannel openDatagramChannel(ProtocolFamily family)
+        throws IOException
+    {
+        return provider.openDatagramChannel(family);
+    }
+
+    public Pipe openPipe()
+        throws IOException
+    {
+        return provider.openPipe();
+    }
+
+    public AbstractSelector openSelector()
+        throws IOException
+    {
+        return provider.openSelector();
+    }
+
+    public ServerSocketChannel openServerSocketChannel()
+        throws IOException
+    {
+        return provider.openServerSocketChannel();
+    }
+
+    public SocketChannel openSocketChannel()
+        throws IOException
+    {
+        return provider.openSocketChannel();
+    }
+
+    public synchronized Channel inheritedChannel() throws IOException {
+        System.out.println("RMIDSelectorProvider.inheritedChannel");
+        if (channel == null) {
+            // Create and bind a new server socket channel
+            channel = ServerSocketChannel.open();
+
+            // Enable SO_REUSEADDR before binding
+            channel.setOption(SO_REUSEADDR, true);
+
+            // Enable SO_REUSEPORT, if supported, before binding
+            if (channel.supportedOptions().contains(SO_REUSEPORT)) {
+                channel.setOption(SO_REUSEPORT, true);
+            }
+
+            channel.bind(new InetSocketAddress(0));
+
+            System.out.println(RMID.EPHEMERAL_MSG + channel.socket().getLocalPort());
+        }
+        return channel;
+    }
+}
--- a/jdk/test/java/rmi/testlibrary/TestParams.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/rmi/testlibrary/TestParams.java	Fri Nov 11 16:44:36 2016 +0100
@@ -34,6 +34,7 @@
     /** variables that hold value property values */
     public static final String testSrc;
     public static final String testClasses;
+    public static final String testClassPath;
 
     /** name of default security policy for test JVM */
     public static final String defaultPolicy;
@@ -57,6 +58,7 @@
     static {
         testSrc = TestLibrary.getProperty("test.src", ".");
         testClasses = TestLibrary.getProperty("test.classes", ".");
+        testClassPath = TestLibrary.getProperty("test.class.path", ".");
 
         String dp = TestLibrary.getProperty("java.security.policy", null);
         if (dp == null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/misc/GetInstanceNullsEmpties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,696 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.*;
+import java.security.cert.*;
+import javax.crypto.*;
+import javax.net.ssl.*;
+import javax.security.auth.login.*;
+import java.lang.reflect.*;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 4985694
+ * @summary Incomplete spec for most of the getInstances
+ */
+/**
+ * A simple test to see what is being thrown when null Strings are passed
+ * to the various getInstance() methods.
+ *
+ * These tests use various algorithm names that don't exist (e.g. "FOO"
+ * Ciphers). Just need something non-null for testing, as the tests will throw
+ * exceptions before trying to instantiate a real object.
+ */
+public class GetInstanceNullsEmpties {
+
+    private static final Provider SUN = Security.getProvider("SUN");
+
+    /*
+     * See if there are more than "expected" number of getInstance() methods,
+     * which will indicate to developers that this test needs an update.
+     */
+    private static void checkNewMethods(Class<?> clazz, int expected)
+            throws Exception {
+
+        long found = Arrays.stream(clazz.getMethods())
+                .filter(name -> name.getName().equals("getInstance"))
+                .count();
+
+        if (found != expected) {
+            throw new Exception("Number of getInstance() mismatch: "
+                    + expected + " expected, " + found + " found");
+        }
+    }
+
+    /**
+     * Main loop.
+     */
+    public static void main(String[] args) throws Exception {
+
+        /*
+         * JCA
+         */
+        testAlgorithmParameterGenerator();
+        testAlgorithmParameters();
+        testCertificateFactory();
+        testCertPathBuilder();
+        testCertPathValidator();
+        testCertStore();
+        testKeyFactory();
+        testKeyPairGenerator();
+        testKeyStore();
+        testMessageDigest();
+        testPolicy();
+        testSecureRandom();
+        testSignature();
+
+        /*
+         * JCE
+         */
+        testCipher();
+        testExemptionMechanism();
+        testKeyAgreement();
+        testKeyGenerator();
+        testMac();
+        testSecretKeyFactory();
+
+        /*
+         * JSSE
+         */
+        testKeyManagerFactory();
+        testSSLContext();
+        testTrustManagerFactory();
+
+        /*
+         * JGSS
+         *
+         * KeyTab.getInstance doesn't take algorithm names, so we'll
+         * ignore this one.
+         */
+        testConfiguration();
+
+        System.out.println("\nTEST PASSED!");
+    }
+
+    private static Method getInstance(Class clazz, Class... args)
+            throws Exception {
+        boolean firstPrinted = false;
+
+        System.out.print("\n" + clazz.getName() + "(");
+        for (Class c : args) {
+            System.out.print(firstPrinted
+                    ? ", " + c.getName() : c.getName());
+            firstPrinted = true;
+        }
+        System.out.println("):");
+
+        return clazz.getMethod("getInstance", args);
+    }
+
+    private static void run(Method m, Class expectedException,
+            Object... args) throws Exception {
+
+        try {
+            m.invoke(null, args);
+            throw new Exception("Didn't throw exception");
+        } catch (InvocationTargetException ite) {
+            Throwable root = ite.getCause();
+            if (root instanceof Exception) {
+                Exception e = (Exception) root;
+                if (expectedException.isInstance(e)) {
+                    System.out.print("OK ");
+                    return;
+                } else {
+                    System.out.println(
+                        "Unexpected InvocationTargetException!");
+                    throw e;
+                }
+            }
+            throw ite;
+        }
+    }
+
+    /*
+     * Constants so lines aren't so long.
+     */
+    private static final Class STRING = String.class;
+    private static final Class PROVIDER = Provider.class;
+
+    private static void testAlgorithmParameterGenerator() throws Exception {
+        Class clazz = AlgorithmParameterGenerator.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testAlgorithmParameters() throws Exception {
+        Class clazz = AlgorithmParameters.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testCertPathBuilder() throws Exception {
+        Class clazz = CertPathBuilder.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testCertPathValidator() throws Exception {
+        Class clazz = CertPathValidator.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testCertStore() throws Exception {
+        Class clazz = CertStore.class;
+        Method m;
+        CertStoreParameters csp = () -> null;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING, CertStoreParameters.class);
+        run(m, NullPointerException.class, (Object) null, csp);
+        run(m, NoSuchAlgorithmException.class, "", csp);
+
+        m = getInstance(clazz, STRING, CertStoreParameters.class, STRING);
+        run(m, NullPointerException.class, null, csp, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", csp, "SUN");
+        run(m, IllegalArgumentException.class, "FOO", csp, null);
+        run(m, IllegalArgumentException.class, "FOO", csp, "");
+
+        m = getInstance(clazz, STRING, CertStoreParameters.class, PROVIDER);
+        run(m, NullPointerException.class, null, csp, SUN);
+        run(m, NoSuchAlgorithmException.class, "", csp, SUN);
+        run(m, IllegalArgumentException.class, "FOO", csp, null);
+    }
+
+    private static void testCertificateFactory() throws Exception {
+        Class clazz = CertificateFactory.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, CertificateException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, CertificateException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, CertificateException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testCipher() throws Exception {
+        Class clazz = Cipher.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        /*
+         * Note the Cipher API is spec'd to throw a NoSuchAlgorithmException
+         * for a null transformation.
+         */
+        m = getInstance(clazz, STRING);
+        run(m, NoSuchAlgorithmException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NoSuchAlgorithmException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NoSuchAlgorithmException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testConfiguration() throws Exception {
+        Class clazz = Configuration.class;
+        Method m;
+        Configuration.Parameters cp = new Configuration.Parameters() {
+        };
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING, Configuration.Parameters.class);
+        run(m, NullPointerException.class, (Object) null, cp);
+        run(m, NoSuchAlgorithmException.class, "", cp);
+
+        m = getInstance(clazz, STRING, Configuration.Parameters.class, STRING);
+        run(m, NullPointerException.class, null, cp, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", cp, "SUN");
+        run(m, IllegalArgumentException.class, "FOO", cp, null);
+        run(m, IllegalArgumentException.class, "FOO", cp, "");
+
+        m = getInstance(clazz, STRING, Configuration.Parameters.class,
+                PROVIDER);
+        run(m, NullPointerException.class, null, cp, SUN);
+        run(m, NoSuchAlgorithmException.class, "", cp, SUN);
+        run(m, IllegalArgumentException.class, "FOO", cp, null);
+    }
+
+    private static void testExemptionMechanism() throws Exception {
+        Class clazz = ExemptionMechanism.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyAgreement() throws Exception {
+        Class clazz = KeyAgreement.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyFactory() throws Exception {
+        Class clazz = KeyFactory.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyGenerator() throws Exception {
+        Class clazz = KeyGenerator.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyManagerFactory() throws Exception {
+        Class clazz = KeyManagerFactory.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyPairGenerator() throws Exception {
+        Class clazz = KeyPairGenerator.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testKeyStore() throws Exception {
+        Class clazz = KeyStore.class;
+        Method m;
+
+        /*
+         * There are actually two additional getInstance() methods with File
+         * as the first parameter.
+         */
+        checkNewMethods(clazz, 5);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, KeyStoreException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, KeyStoreException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, KeyStoreException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testMac() throws Exception {
+        Class clazz = Mac.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testMessageDigest() throws Exception {
+        Class clazz = MessageDigest.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testPolicy() throws Exception {
+        Class clazz = Policy.class;
+        Method m;
+        Policy.Parameters pp = new Policy.Parameters() {
+        };
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING, Policy.Parameters.class);
+        run(m, NullPointerException.class, (Object) null, pp);
+        run(m, NoSuchAlgorithmException.class, "", pp);
+
+        m = getInstance(clazz, STRING, Policy.Parameters.class, STRING);
+        run(m, NullPointerException.class, null, pp, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", pp, "SUN");
+        run(m, IllegalArgumentException.class, "FOO", pp, null);
+        run(m, IllegalArgumentException.class, "FOO", pp, "");
+
+        m = getInstance(clazz, STRING, Policy.Parameters.class, PROVIDER);
+        run(m, NullPointerException.class, null, pp, SUN);
+        run(m, NoSuchAlgorithmException.class, "", pp, SUN);
+        run(m, IllegalArgumentException.class, "FOO", pp, null);
+    }
+
+    private static void testSSLContext() throws Exception {
+        Class clazz = SSLContext.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testSecretKeyFactory() throws Exception {
+        Class clazz = SecretKeyFactory.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testSecureRandom() throws Exception {
+        Class clazz = SecureRandom.class;
+        Method m;
+        SecureRandomParameters srp = new SecureRandomParameters() {
+        };
+
+        checkNewMethods(clazz, 6);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+
+        m = getInstance(clazz, STRING, SecureRandomParameters.class);
+        run(m, NullPointerException.class, (Object) null, srp);
+        run(m, NoSuchAlgorithmException.class, "", srp);
+
+        m = getInstance(clazz, STRING, SecureRandomParameters.class, STRING);
+        run(m, NullPointerException.class, null, srp, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", srp, "SUN");
+        run(m, IllegalArgumentException.class, "FOO", srp, null);
+        run(m, IllegalArgumentException.class, "FOO", srp, "");
+
+        m = getInstance(clazz, STRING, SecureRandomParameters.class, PROVIDER);
+        run(m, NullPointerException.class, null, srp, SUN);
+        run(m, NoSuchAlgorithmException.class, "", srp, SUN);
+        run(m, IllegalArgumentException.class, "FOO", srp, null);
+    }
+
+    private static void testSignature() throws Exception {
+        Class clazz = Signature.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+
+    private static void testTrustManagerFactory() throws Exception {
+        Class clazz = TrustManagerFactory.class;
+        Method m;
+
+        checkNewMethods(clazz, 3);
+
+        m = getInstance(clazz, STRING);
+        run(m, NullPointerException.class, (Object) null);
+        run(m, NoSuchAlgorithmException.class, "");
+
+        m = getInstance(clazz, STRING, STRING);
+        run(m, NullPointerException.class, null, "SUN");
+        run(m, NoSuchAlgorithmException.class, "", "SUN");
+        run(m, IllegalArgumentException.class, "FOO", null);
+        run(m, IllegalArgumentException.class, "FOO", "");
+
+        m = getInstance(clazz, STRING, PROVIDER);
+        run(m, NullPointerException.class, null, SUN);
+        run(m, NoSuchAlgorithmException.class, "", SUN);
+        run(m, IllegalArgumentException.class, "FOO", null);
+    }
+}
--- a/jdk/test/java/security/testlibrary/Proc.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/security/testlibrary/Proc.java	Fri Nov 11 16:44:36 2016 +0100
@@ -243,16 +243,23 @@
     // Starts the proc
     public Proc start() throws IOException {
         List<String> cmd = new ArrayList<>();
+        boolean hasModules;
         if (launcher != null) {
             cmd.add(launcher);
+            File base = new File(launcher).getParentFile().getParentFile();
+            hasModules = new File(base, "modules").exists() ||
+                    new File(base, "jmods").exists();
         } else {
             cmd.add(new File(new File(System.getProperty("java.home"), "bin"),
                         "java").getPath());
+            hasModules = true;
         }
 
-        Stream.of(jdk.internal.misc.VM.getRuntimeArguments())
-            .filter(arg -> arg.startsWith("--add-exports="))
-            .forEach(cmd::add);
+        if (hasModules) {
+            Stream.of(jdk.internal.misc.VM.getRuntimeArguments())
+                    .filter(arg -> arg.startsWith("--add-exports="))
+                    .forEach(cmd::add);
+        }
 
         Collections.addAll(cmd, splitProperty("test.vm.opts"));
         Collections.addAll(cmd, splitProperty("test.java.opts"));
--- a/jdk/test/java/util/Arrays/ParallelPrefix.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/Arrays/ParallelPrefix.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,7 +26,6 @@
  * @summary unit test for Arrays.ParallelPrefix().
  * @author Tristan Yan
  * @run testng ParallelPrefix
- * @key intermittent
  */
 
 import java.util.Arrays;
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, 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
@@ -89,7 +89,7 @@
             String[] jresResult = new String[4];
             if (jreSupportsLocale) {
                 for (int i = 0; i < 4; i++) {
-                    jresResult[i] = "sun.util.locale.provider."+classNames[i];
+                    jresResult[i] = "sun.text." + classNames[i];
                 }
             }
 
--- a/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/PluggableLocale/BreakIteratorProviderTest.sh	Fri Nov 11 16:44:36 2016 +0100
@@ -1,6 +1,6 @@
 #!/bin/sh
 # 
-# Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 # 
 # This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,6 @@
 #
 #
 # @test
-# @bug 4052440 8062588
+# @bug 4052440 8062588 8165804
 # @summary BreakIteratorProvider tests
 # @run shell ExecTest.sh foo BreakIteratorProviderTest
--- a/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/MyResources_ja_JP.properties	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-#
-# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-# 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/asiabundles/jdk/test/resources/asia/MyResources_ja_JP.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -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
--- a/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesProvider.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/ResourceBundle/modules/basic/src/mainbundles/jdk/test/resources/MyResourcesProvider.java	Fri Nov 11 16:44:36 2016 +0100
@@ -62,9 +62,7 @@
 
     @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);
+        String name = addRegion(baseName);
         return Control.getControl(Control.FORMAT_DEFAULT).toBundleName(name, locale);
     }
 
--- a/jdk/test/java/util/Scanner/ScanTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/Scanner/ScanTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,7 +24,7 @@
 /**
  * @test
  * @bug 4313885 4926319 4927634 5032610 5032622 5049968 5059533 6223711 6277261 6269946 6288823
- *      8072722 8139414
+ *      8072722 8139414 8166261
  * @summary Basic tests of java.util.Scanner methods
  * @key randomness
  * @modules jdk.localedata
@@ -36,6 +36,7 @@
 import java.nio.*;
 import java.text.*;
 import java.util.*;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.regex.*;
 import java.util.stream.*;
@@ -79,6 +80,7 @@
             resetTest();
             streamCloseTest();
             streamComodTest();
+            outOfRangeRadixTest();
 
             for (int j = 0; j < NUM_SOURCE_TYPES; j++) {
                 hasNextTest(j);
@@ -1509,6 +1511,48 @@
         report("Reset test");
     }
 
+    static List<BiConsumer <Scanner, Integer>> methodWRList = Arrays.asList(
+        (s, r) -> s.hasNextByte(r),
+        (s, r) -> s.nextByte(r),
+        (s, r) -> s.hasNextShort(r),
+        (s, r) -> s.nextShort(r),
+        (s, r) -> s.hasNextInt(r),
+        (s, r) -> s.nextInt(r),
+        (s, r) -> s.hasNextLong(r),
+        (s, r) -> s.nextLong(r),
+        (s, r) -> s.hasNextBigInteger(r),
+        (s, r) -> s.nextBigInteger(r)
+    );
+
+    /*
+     * Test that setting the radix to an out of range value triggers
+     * an IllegalArgumentException
+     */
+    public static void outOfRangeRadixTest() throws Exception {
+        int[] bad = new int[] { -1, 0,  1, 37, 38 };
+        int[] good = IntStream.rangeClosed(Character.MIN_RADIX, Character.MAX_RADIX)
+                              .toArray();
+
+        methodWRList.stream().forEach( m -> {
+            for (int r : bad) {
+                try (Scanner sc = new Scanner("10 10 10 10")) {
+                    m.accept(sc, r);
+                    failCount++;
+                } catch (IllegalArgumentException ise) {}
+            }
+        });
+        methodWRList.stream().forEach( m -> {
+            for (int r : good) {
+                try (Scanner sc = new Scanner("10 10 10 10")) {
+                    m.accept(sc, r);
+                } catch (Exception x) {
+                    failCount++;
+                }
+            }
+        });
+        report("Radix out of range test");
+    }
+
     /*
      * Test that closing the stream also closes the underlying Scanner.
      * The cases of attempting to open streams on a closed Scanner are
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/LogManager/LinkageErrorTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * @test 8152515
+ * @summary Checks that LinkageError are ignored when closing handlers
+ *          during Shutdown.
+ * @build LinkageErrorTest
+ * @run main/othervm LinkageErrorTest
+ */
+
+public class LinkageErrorTest {
+
+    public static class TestHandler extends Handler {
+
+        private volatile boolean closed;
+        public TestHandler() {
+            INSTANCES.add(this);
+        }
+
+        @Override
+        public void publish(LogRecord record) {
+        }
+
+        @Override
+        public void flush() {
+        }
+
+        @Override
+        public void close() throws SecurityException {
+            closed = true;
+            try {
+                System.out.println(INSTANCES);
+            } catch (Throwable t) {
+                // ignore
+            }
+            throw new LinkageError();
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + "{closed=" + closed + '}';
+        }
+
+        private static final CopyOnWriteArrayList<Handler> INSTANCES
+                = new CopyOnWriteArrayList<>();
+    }
+
+    private static final Logger LOGGER = Logger.getLogger("test");
+    private static final Logger GLOBAL = Logger.getGlobal();
+
+    public static void main(String[] args) {
+        LOGGER.addHandler(new TestHandler());
+        LOGGER.addHandler(new TestHandler());
+        GLOBAL.addHandler(new TestHandler());
+    }
+}
--- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThowableHelper.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +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.
- */
-package java.util.stream;
-
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-public final class ThowableHelper {
-
-    public static void checkException(Class<? extends Exception> ce, Runnable r) {
-        Exception caught = null;
-        try {
-            r.run();
-        } catch (Exception e) {
-            caught = e;
-        }
-
-        assertNotNull(caught);
-        assertTrue(ce.isInstance(caught));
-    }
-
-    public static void checkNPE(Runnable r) {
-        checkException(NullPointerException.class, r);
-    }
-
-    public static void checkISE(Runnable r) {
-        checkException(IllegalStateException.class, r);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/ThrowableHelper.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,49 @@
+/*
+ * 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 java.util.stream;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+public final class ThrowableHelper {
+
+    public static void checkException(Class<? extends Exception> ce, Runnable r) {
+        Exception caught = null;
+        try {
+            r.run();
+        } catch (Exception e) {
+            caught = e;
+        }
+
+        assertNotNull(caught);
+        assertTrue(ce.isInstance(caught));
+    }
+
+    public static void checkNPE(Runnable r) {
+        checkException(NullPointerException.class, r);
+    }
+
+    public static void checkISE(Runnable r) {
+        checkException(IllegalStateException.class, r);
+    }
+}
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -43,7 +43,7 @@
 import java.util.stream.OpTestCase;
 
 import static java.util.stream.LambdaTestHelpers.countTo;
-import static java.util.stream.ThowableHelper.checkNPE;
+import static java.util.stream.ThrowableHelper.checkNPE;
 
 @Test
 public class CollectAndSummaryStatisticsTest extends OpTestCase {
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CollectionAndMapModifyStreamTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -113,7 +113,7 @@
         Map<String, Supplier<Map<Integer, Integer>>> maps = new HashMap<>();
 
         maps.put(HashMap.class.getName(), () -> new HashMap<>(content));
-        maps.put(HashMap.class.getName(), () -> new LinkedHashMap<>(content));
+        maps.put(LinkedHashMap.class.getName(), () -> new LinkedHashMap<>(content));
         maps.put(IdentityHashMap.class.getName(), () -> new IdentityHashMap<>(content));
         maps.put(WeakHashMap.class.getName(), () -> new WeakHashMap<>(content));
 
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -49,7 +49,7 @@
 import java.util.stream.TestData;
 
 import static java.util.stream.LambdaTestHelpers.*;
-import static java.util.stream.ThowableHelper.checkNPE;
+import static java.util.stream.ThrowableHelper.checkNPE;
 
 @Test
 public class FlatMapOpTest extends OpTestCase {
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -38,7 +38,7 @@
 import java.util.stream.TestData;
 import java.util.stream.TestData.Factory;
 
-import static java.util.stream.ThowableHelper.checkNPE;
+import static java.util.stream.ThrowableHelper.checkNPE;
 
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -38,7 +38,7 @@
 import java.util.stream.TestData;
 
 import static java.util.stream.Collectors.toList;
-import static java.util.stream.ThowableHelper.checkISE;
+import static java.util.stream.ThrowableHelper.checkISE;
 
 @Test
 public class StreamBuilderTest extends OpTestCase {
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -36,8 +36,8 @@
 import org.testng.annotations.Test;
 
 import static java.util.stream.LambdaTestHelpers.countTo;
-import static java.util.stream.ThowableHelper.checkNPE;
-import static java.util.stream.ThowableHelper.checkISE;
+import static java.util.stream.ThrowableHelper.checkNPE;
+import static java.util.stream.ThrowableHelper.checkISE;
 
 @Test(groups = { "serialization-hostile" })
 public class StreamCloseTest extends OpTestCase {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/ImageCompressionTypesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
+  * @bug     6294607
+  * @summary Test verifies whether ImageWriteParam.getCompressionTypes()
+  *          returns any duplicate compression type for ImageIO plugins.
+  * @run     main ImageCompressionTypesTest
+  */
+
+import java.util.Iterator;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+
+public class ImageCompressionTypesTest {
+
+    static ImageWriter writer = null;
+
+    public ImageCompressionTypesTest(String format) {
+        Iterator it = ImageIO.getImageWritersByFormatName(format);
+        while (it.hasNext()) {
+            writer = (ImageWriter) it.next();
+            break;
+        }
+        ImageWriteParam param = writer.getDefaultWriteParam();
+
+        param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+        System.out.println("Checking compression types for : " + format);
+        String compTypes[] = param.getCompressionTypes();
+        if (compTypes.length > 1) {
+            for (int i = 0; i < compTypes.length; i++) {
+                for (int j = i + 1; j < compTypes.length; j++) {
+                    if (compTypes[i].equalsIgnoreCase(compTypes[j])) {
+                        throw new RuntimeException("Duplicate compression"
+                                + " type exists for image format " + format);
+                    }
+                }
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+        final String[] formats = {"bmp", "png", "gif", "jpg", "tiff"};
+        for (String format : formats) {
+            new ImageCompressionTypesTest(format);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/GetElementsByTagNameTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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     8167281
+ * @summary Test verifies that Element.getElementsByTagName("*") is not empty
+ *          for valid image.
+ * @run     main GetElementsByTagNameTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import org.w3c.dom.Element;
+
+public class GetElementsByTagNameTest {
+
+    public static void main(String[] args) throws IOException {
+        // Generate some trivial image and save it to a temporary array
+        ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+        ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB),
+                "gif", tmp);
+
+        // Read the stream
+        ImageInputStream in = new MemoryCacheImageInputStream(
+                new ByteArrayInputStream(tmp.toByteArray()));
+        ImageReader reader = ImageIO.getImageReaders(in).next();
+        reader.setInput(in);
+
+        // Retrieve standard image metadata tree
+        IIOMetadata meta = reader.getImageMetadata(0);
+        if (meta == null || !meta.isStandardMetadataFormatSupported()) {
+            throw new Error("Test failure: Missing metadata");
+        }
+        Element root = (Element) meta.
+                getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
+
+        // Test getElementsByTagName("*")
+        if (root.getElementsByTagName("*").getLength() == 0) {
+            throw new RuntimeException("getElementsByTagName(\"*\") returns"
+                    + " nothing");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/imageio/metadata/NthItemNodeListTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     8167281
+ * @summary Test verifies that accessing nth item in NodeList doesn't throw
+ *          IndexOutOfBoundsException.
+ * @run     main NthItemNodeListTest
+ */
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import javax.imageio.ImageIO;
+import javax.imageio.ImageReader;
+import javax.imageio.metadata.IIOMetadata;
+import javax.imageio.metadata.IIOMetadataFormatImpl;
+import javax.imageio.stream.ImageInputStream;
+import javax.imageio.stream.MemoryCacheImageInputStream;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class NthItemNodeListTest {
+
+    public static void main(String[] args) throws IOException {
+        // Generate some trivial image and save it to a temporary array
+        ByteArrayOutputStream tmp = new ByteArrayOutputStream();
+        ImageIO.write(new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB),
+                "gif", tmp);
+
+        // Read it back in
+        ImageInputStream in = new MemoryCacheImageInputStream(
+                new ByteArrayInputStream(tmp.toByteArray()));
+        ImageReader reader = ImageIO.getImageReaders(in).next();
+        reader.setInput(in);
+
+        // Retrieve standard image metadata tree
+        IIOMetadata meta = reader.getImageMetadata(0);
+        if (meta == null || !meta.isStandardMetadataFormatSupported()) {
+            throw new Error("Test failure: Missing metadata");
+        }
+        Element root = (Element) meta.
+                getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName);
+
+        NodeList nodeList = root.
+                getElementsByTagName(root.getFirstChild().getNodeName());
+        /*
+         * Accessing the nth node should return null and not throw
+         * IndexOutOfBoundsException.
+         */
+        Node n = (nodeList.item(nodeList.getLength()));
+    }
+}
+
--- a/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/net/ssl/DTLS/DTLSOverDatagram.java	Fri Nov 11 16:44:36 2016 +0100
@@ -48,10 +48,6 @@
  */
 public class DTLSOverDatagram {
 
-    static {
-        System.setProperty("javax.net.debug", "ssl");
-    }
-
     private static int MAX_HANDSHAKE_LOOPS = 200;
     private static int MAX_APP_READ_LOOPS = 60;
     private static int SOCKET_TIMEOUT = 10 * 1000; // in millis
@@ -160,6 +156,7 @@
             }
 
             SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
+            log(side, "=======handshake(" + loops + ", " + hs + ")=======");
             if (hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ||
                 hs == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
 
@@ -239,6 +236,7 @@
                 boolean finished = produceHandshakePackets(
                     engine, peerAddr, side, packets);
 
+                log(side, "Produced " + packets.size() + " packets");
                 for (DatagramPacket p : packets) {
                     socket.send(p);
                 }
@@ -252,14 +250,16 @@
             } else if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) {
                 runDelegatedTasks(engine);
             } else if (hs == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
-                log(side, "Handshake status is NOT_HANDSHAKING, finish the loop");
+                log(side,
+                    "Handshake status is NOT_HANDSHAKING, finish the loop");
                 endLoops = true;
             } else if (hs == SSLEngineResult.HandshakeStatus.FINISHED) {
                 throw new Exception(
                         "Unexpected status, SSLEngine.getHandshakeStatus() "
                                 + "shouldn't return FINISHED");
             } else {
-                throw new Exception("Can't reach here, handshake status is " + hs);
+                throw new Exception(
+                        "Can't reach here, handshake status is " + hs);
             }
         }
 
@@ -279,7 +279,9 @@
         log(side, "Negotiated cipher suite is " + session.getCipherSuite());
 
         // handshake status should be NOT_HANDSHAKING
-        // according to the spec, SSLEngine.getHandshakeStatus() can't return FINISHED
+        //
+        // According to the spec, SSLEngine.getHandshakeStatus() can't
+        // return FINISHED.
         if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
             throw new Exception("Unexpected handshake status " + hs);
         }
@@ -348,13 +350,16 @@
 
             SSLEngineResult.Status rs = r.getStatus();
             SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus();
+            log(side, "====packet(" + loops + ", " + rs + ", " + hs + ")====");
             if (rs == SSLEngineResult.Status.BUFFER_OVERFLOW) {
                 // the client maximum fragment size config does not work?
                 throw new Exception("Buffer overflow: " +
                             "incorrect server maximum fragment size");
             } else if (rs == SSLEngineResult.Status.BUFFER_UNDERFLOW) {
-                log(side, "Produce handshake packets: BUFFER_UNDERFLOW occured");
-                log(side, "Produce handshake packets: Handshake status: " + hs);
+                log(side,
+                        "Produce handshake packets: BUFFER_UNDERFLOW occured");
+                log(side,
+                        "Produce handshake packets: Handshake status: " + hs);
                 // bad packet, or the client maximum fragment size
                 // config does not work?
                 if (hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
@@ -453,6 +458,53 @@
         return packets;
     }
 
+    // Get a datagram packet for the specified handshake type.
+    static DatagramPacket getPacket(
+            List<DatagramPacket> packets, byte handshakeType) {
+        boolean matched = false;
+        for (DatagramPacket packet : packets) {
+            byte[] data = packet.getData();
+            int offset = packet.getOffset();
+            int length = packet.getLength();
+
+            // Normally, this pakcet should be a handshake message
+            // record.  However, even if the underlying platform
+            // splits the record more, we don't really worry about
+            // the improper packet loss because DTLS implementation
+            // should be able to handle packet loss properly.
+            //
+            // See RFC 6347 for the detailed format of DTLS records.
+            if (handshakeType == -1) {      // ChangeCipherSpec
+                // Is it a ChangeCipherSpec message?
+                matched = (length == 14) && (data[offset] == 0x14);
+            } else if ((length >= 25) &&    // 25: handshake mini size
+                (data[offset] == 0x16)) {   // a handshake message
+
+                // check epoch number for initial handshake only
+                if (data[offset + 3] == 0x00) {     // 3,4: epoch
+                    if (data[offset + 4] == 0x00) { // plaintext
+                        matched =
+                            (data[offset + 13] == handshakeType);
+                    } else {                        // cipherext
+                        // The 1st ciphertext is a Finished message.
+                        //
+                        // If it is not proposed to loss the Finished
+                        // message, it is not necessary to check the
+                        // following packets any mroe as a Finished
+                        // message is the last handshake message.
+                        matched = (handshakeType == 20);
+                    }
+                }
+            }
+
+            if (matched) {
+                return packet;
+            }
+        }
+
+        return null;
+    }
+
     // run delegated tasks
     void runDelegatedTasks(SSLEngine engine) throws Exception {
         Runnable runnable;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/DTLS/PacketLossRetransmission.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8161086
+ * @summary DTLS handshaking fails if some messages were lost
+ * @modules java.base/sun.security.util
+ * @build DTLSOverDatagram
+ *
+ * @run main/othervm PacketLossRetransmission client 0 hello_request
+ * @run main/othervm PacketLossRetransmission client 1 client_hello
+ * @run main/othervm PacketLossRetransmission client 2 server_hello
+ * @run main/othervm PacketLossRetransmission client 3 hello_verify_request
+ * @run main/othervm PacketLossRetransmission client 4 new_session_ticket
+ * @run main/othervm PacketLossRetransmission client 11 certificate
+ * @run main/othervm PacketLossRetransmission client 12 server_key_exchange
+ * @run main/othervm PacketLossRetransmission client 13 certificate_request
+ * @run main/othervm PacketLossRetransmission client 14 server_hello_done
+ * @run main/othervm PacketLossRetransmission client 15 certificate_verify
+ * @run main/othervm PacketLossRetransmission client 16 client_key_exchange
+ * @run main/othervm PacketLossRetransmission client 20 finished
+ * @run main/othervm PacketLossRetransmission client 21 certificate_url
+ * @run main/othervm PacketLossRetransmission client 22 certificate_status
+ * @run main/othervm PacketLossRetransmission client 23 supplemental_data
+ * @run main/othervm PacketLossRetransmission client -1 change_cipher_spec
+ * @run main/othervm PacketLossRetransmission server 0 hello_request
+ * @run main/othervm PacketLossRetransmission server 1 client_hello
+ * @run main/othervm PacketLossRetransmission server 2 server_hello
+ * @run main/othervm PacketLossRetransmission server 3 hello_verify_request
+ * @run main/othervm PacketLossRetransmission server 4 new_session_ticket
+ * @run main/othervm PacketLossRetransmission server 11 certificate
+ * @run main/othervm PacketLossRetransmission server 12 server_key_exchange
+ * @run main/othervm PacketLossRetransmission server 13 certificate_request
+ * @run main/othervm PacketLossRetransmission server 14 server_hello_done
+ * @run main/othervm PacketLossRetransmission server 15 certificate_verify
+ * @run main/othervm PacketLossRetransmission server 16 client_key_exchange
+ * @run main/othervm PacketLossRetransmission server 20 finished
+ * @run main/othervm PacketLossRetransmission server 21 certificate_url
+ * @run main/othervm PacketLossRetransmission server 22 certificate_status
+ * @run main/othervm PacketLossRetransmission server 23 supplemental_data
+ * @run main/othervm PacketLossRetransmission server -1 change_cipher_spec
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.net.DatagramPacket;
+import java.net.SocketAddress;
+import javax.net.ssl.SSLEngine;
+
+/**
+ * Test that DTLS implementation is able to do retransmission internally
+ * automatically if packet get lost.
+ */
+public class PacketLossRetransmission extends DTLSOverDatagram {
+    private static boolean isClient;
+    private static byte handshakeType;
+
+    private boolean needPacketLoss = true;
+
+    public static void main(String[] args) throws Exception {
+        isClient = args[0].equals("client");
+        handshakeType = Byte.valueOf(args[1]);
+
+        PacketLossRetransmission testCase = new PacketLossRetransmission();
+        testCase.runTest(testCase);
+    }
+
+    @Override
+    boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr,
+            String side, List<DatagramPacket> packets) throws Exception {
+
+        boolean finished = super.produceHandshakePackets(
+                engine, socketAddr, side, packets);
+
+        if (needPacketLoss && (!(isClient ^ engine.getUseClientMode()))) {
+            DatagramPacket packet = getPacket(packets, handshakeType);
+            if (packet != null) {
+                needPacketLoss = false;
+
+                System.out.println("Loss a packet of handshake messahe");
+                packets.remove(packet);
+            }
+        }
+
+        return finished;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/DTLS/RespondToRetransmit.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+// SunJSSE does not support dynamic system properties, no way to re-use
+// system properties in samevm/agentvm mode.
+
+/*
+ * @test
+ * @bug 8161086
+ * @summary DTLS handshaking fails if some messages were lost
+ * @modules java.base/sun.security.util
+ * @build DTLSOverDatagram
+ *
+ * @run main/othervm RespondToRetransmit client 0 hello_request
+ * @run main/othervm RespondToRetransmit client 1 client_hello
+ * @run main/othervm RespondToRetransmit client 2 server_hello
+ * @run main/othervm RespondToRetransmit client 3 hello_verify_request
+ * @run main/othervm RespondToRetransmit client 4 new_session_ticket
+ * @run main/othervm RespondToRetransmit client 11 certificate
+ * @run main/othervm RespondToRetransmit client 12 server_key_exchange
+ * @run main/othervm RespondToRetransmit client 13 certificate_request
+ * @run main/othervm RespondToRetransmit client 14 server_hello_done
+ * @run main/othervm RespondToRetransmit client 15 certificate_verify
+ * @run main/othervm RespondToRetransmit client 16 client_key_exchange
+ * @run main/othervm RespondToRetransmit client 20 finished
+ * @run main/othervm RespondToRetransmit client 21 certificate_url
+ * @run main/othervm RespondToRetransmit client 22 certificate_status
+ * @run main/othervm RespondToRetransmit client 23 supplemental_data
+ * @run main/othervm RespondToRetransmit client -1 change_cipher_spec
+ * @run main/othervm RespondToRetransmit server 0 hello_request
+ * @run main/othervm RespondToRetransmit server 1 client_hello
+ * @run main/othervm RespondToRetransmit server 2 server_hello
+ * @run main/othervm RespondToRetransmit server 3 hello_verify_request
+ * @run main/othervm RespondToRetransmit server 4 new_session_ticket
+ * @run main/othervm RespondToRetransmit server 11 certificate
+ * @run main/othervm RespondToRetransmit server 12 server_key_exchange
+ * @run main/othervm RespondToRetransmit server 13 certificate_request
+ * @run main/othervm RespondToRetransmit server 14 server_hello_done
+ * @run main/othervm RespondToRetransmit server 15 certificate_verify
+ * @run main/othervm RespondToRetransmit server 16 client_key_exchange
+ * @run main/othervm RespondToRetransmit server 20 finished
+ * @run main/othervm RespondToRetransmit server 21 certificate_url
+ * @run main/othervm RespondToRetransmit server 22 certificate_status
+ * @run main/othervm RespondToRetransmit server 23 supplemental_data
+ * @run main/othervm RespondToRetransmit server -1 change_cipher_spec
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.net.DatagramPacket;
+import java.net.SocketAddress;
+import javax.net.ssl.SSLEngine;
+
+/**
+ * Test that DTLS implementation is able to do retransmission internally
+ * automatically if packet get lost.
+ */
+public class RespondToRetransmit extends DTLSOverDatagram {
+    private static boolean isClient;
+    private static byte handshakeType;
+
+    private boolean needPacketDuplicate = true;
+
+    public static void main(String[] args) throws Exception {
+        isClient = args[0].equals("client");
+        handshakeType = Byte.valueOf(args[1]);
+
+        RespondToRetransmit testCase = new RespondToRetransmit();
+        testCase.runTest(testCase);
+    }
+
+    @Override
+    boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr,
+            String side, List<DatagramPacket> packets) throws Exception {
+
+        boolean finished = super.produceHandshakePackets(
+                engine, socketAddr, side, packets);
+
+        if (needPacketDuplicate && (!(isClient ^ engine.getUseClientMode()))) {
+            DatagramPacket packet = getPacket(packets, handshakeType);
+            if (packet != null) {
+                needPacketDuplicate = false;
+
+                System.out.println("Duplicate the flight.");
+                List<DatagramPacket> duplicates = new ArrayList<>();
+                finished = super.produceHandshakePackets(
+                        engine, socketAddr, side, duplicates);
+                packets.addAll(duplicates);
+            }
+        }
+
+        return finished;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,373 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8133632
+ * @summary javax.net.ssl.SSLEngine does not properly handle received
+ * SSL fatal alerts
+ * @run main/othervm EngineCloseOnAlert
+ */
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import javax.net.ssl.*;
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.security.*;
+import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
+
+public class EngineCloseOnAlert {
+
+    private static final String pathToStores = "../etc";
+    private static final String keyStoreFile = "keystore";
+    private static final String trustStoreFile = "truststore";
+    private static final String passwd = "passphrase";
+    private static final String keyFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + keyStoreFile;
+    private static final String trustFilename =
+            System.getProperty("test.src", ".") + "/" + pathToStores +
+                "/" + trustStoreFile;
+
+    private static KeyManagerFactory KMF;
+    private static TrustManagerFactory TMF;
+    private static TrustManagerFactory EMPTY_TMF;
+
+    private static final String[] TLS10ONLY = { "TLSv1" };
+    private static final String[] TLS12ONLY = { "TLSv1.2" };
+    private static final String[] ONECIPHER =
+            { "TLS_RSA_WITH_AES_128_CBC_SHA" };
+
+    public interface TestCase {
+        public void runTest() throws Exception;
+    }
+
+    public static void main(String[] args) throws Exception {
+        int failed = 0;
+        List<TestCase> testMatrix = new LinkedList<TestCase>() {{
+            add(clientReceivesAlert);
+            add(serverReceivesAlert);
+        }};
+
+        // Create the various key/trust manager factories we'll need
+        createManagerFactories();
+
+        for (TestCase test : testMatrix) {
+            try {
+                test.runTest();
+            } catch (Exception e) {
+                System.out.println("Exception in test:\n" + e);
+                e.printStackTrace(System.out);
+                failed++;
+            }
+        }
+
+        System.out.println("Total tests: " + testMatrix.size() + ", passed: " +
+                (testMatrix.size() - failed) + ", failed: " + failed);
+        if (failed > 0) {
+            throw new RuntimeException("One or more tests failed.");
+        }
+    }
+
+    private static final TestCase clientReceivesAlert = new TestCase() {
+        @Override
+        public void runTest() throws Exception {
+            System.out.println("");
+            System.out.println("=======================================");
+            System.out.println("Test: Client receives alert from server");
+            System.out.println("=======================================");
+
+            // For this test, we won't initialize any keystore so the
+            // server will throw an exception because it has no key/cert to
+            // match the requested ciphers offered by the client.  This
+            // will generate an alert from the server to the client.
+
+            SSLContext context = SSLContext.getDefault();
+            SSLEngine client = context.createSSLEngine();
+            SSLEngine server = context.createSSLEngine();
+            client.setUseClientMode(true);
+            server.setUseClientMode(false);
+            SSLEngineResult clientResult;
+            SSLEngineResult serverResult;
+
+            ByteBuffer raw = ByteBuffer.allocate(32768);
+            ByteBuffer plain = ByteBuffer.allocate(32768);
+
+            // Generate the client hello and have the server unwrap it
+            client.wrap(plain, raw);
+            checkEngineState(client, NEED_UNWRAP, false, false);
+            raw.flip();
+            System.out.println("Client-to-Server:\n-----------------\n" +
+                    dumpHexBytes(raw, 16, "\n", ":"));
+
+
+            // The server should need to run a delegated task while processing
+            // the client hello data.
+            serverResult = server.unwrap(raw, plain);
+            checkEngineState(server, NEED_TASK, false, false);
+            System.out.println("Server result: " + serverResult);
+            runDelegatedTasks(serverResult, server);
+            checkEngineState(server, NEED_WRAP, true, false);
+
+            try {
+                raw.clear();
+                serverResult = server.wrap(plain, raw);
+                System.out.println("Server result: " + serverResult);
+                runDelegatedTasks(serverResult, server);
+            } catch (SSLException e) {
+                // This is the expected code path
+                System.out.println("Server throws exception: " + e);
+                System.out.println("Server engine state: " +
+                        "isInboundDone = "+ server.isInboundDone() +
+                        ", isOutboundDone = " + server.isOutboundDone() +
+                        ", handshake status = " + server.getHandshakeStatus());
+                checkEngineState(server, NEED_WRAP, true, false);
+            }
+            raw.clear();
+
+            // The above should show that isInboundDone returns true, and
+            // handshake status is NEED_WRAP. That is the correct behavior,
+            // wrap will put a fatal alert message in the buffer.
+            serverResult = server.wrap(plain, raw);
+            System.out.println("Server result (wrap after exception): " +
+                    serverResult);
+            System.out.println("Server engine closure state: isInboundDone="
+                    + server.isInboundDone() + ", isOutboundDone="
+                    + server.isOutboundDone());
+            checkEngineState(server, NEED_UNWRAP, true, true);
+            raw.flip();
+
+            System.out.println("Server-to-Client:\n-----------------\n" +
+                    dumpHexBytes(raw, 16, "\n", ":"));
+
+            // Client side will read the fatal alert and throw exception.
+            try {
+                clientResult = client.unwrap(raw, plain);
+                System.out.println("Client result (unwrap alert): " +
+                    clientResult);
+            } catch (SSLException e) {
+                System.out.println("Client throws exception: " + e);
+                System.out.println("Engine closure status: isInboundDone="
+                        + client.isInboundDone() + ", isOutboundDone="
+                        + client.isOutboundDone() + ", handshake status="
+                        + client.getHandshakeStatus());
+                checkEngineState(client, NOT_HANDSHAKING, true, true);
+            }
+            raw.clear();
+
+            // Last test, we try to unwrap
+            clientResult = client.unwrap(raw, plain);
+            checkEngineState(client, NOT_HANDSHAKING, true, true);
+            System.out.println("Client result (wrap after exception): " +
+                    clientResult);
+        }
+    };
+
+    private static final TestCase serverReceivesAlert = new TestCase() {
+        @Override
+        public void runTest() throws Exception {
+            SSLContext cliContext = SSLContext.getDefault();
+            SSLContext servContext = SSLContext.getInstance("TLS");
+            servContext.init(KMF.getKeyManagers(), TMF.getTrustManagers(),
+                    null);
+            SSLEngine client = cliContext.createSSLEngine();
+            SSLEngine server = servContext.createSSLEngine();
+            client.setUseClientMode(true);
+            client.setEnabledProtocols(TLS12ONLY);
+            client.setEnabledCipherSuites(ONECIPHER);
+            server.setUseClientMode(false);
+            server.setEnabledProtocols(TLS10ONLY);
+            SSLEngineResult clientResult;
+            SSLEngineResult serverResult;
+            ByteBuffer raw = ByteBuffer.allocate(32768);
+            ByteBuffer plain = ByteBuffer.allocate(32768);
+
+            System.out.println("");
+            System.out.println("=======================================");
+            System.out.println("Test: Server receives alert from client");
+            System.out.println("=======================================");
+
+            // Generate the client hello and have the server unwrap it
+            checkEngineState(client, NOT_HANDSHAKING, false, false);
+            client.wrap(plain, raw);
+            checkEngineState(client, NEED_UNWRAP, false, false);
+            raw.flip();
+            System.out.println("Client-to-Server:\n-----------------\n" +
+                    dumpHexBytes(raw, 16, "\n", ":"));
+
+            // The server should need to run a delegated task while processing
+            // the client hello data.
+            serverResult = server.unwrap(raw, plain);
+            checkEngineState(server, NEED_TASK, false, false);
+            runDelegatedTasks(serverResult, server);
+            checkEngineState(server, NEED_WRAP, false, false);
+            raw.compact();
+
+            // The server should now wrap the response back to the client
+            server.wrap(plain, raw);
+            checkEngineState(server, NEED_UNWRAP, false, false);
+            raw.flip();
+            System.out.println("Server-to-Client:\n-----------------\n" +
+                    dumpHexBytes(raw, 16, "\n", ":"));
+
+            // The client should parse this and throw an exception because
+            // It is unwiling to do TLS 1.0
+            clientResult = client.unwrap(raw, plain);
+            checkEngineState(client, NEED_TASK, false, false);
+            runDelegatedTasks(clientResult, client);
+            checkEngineState(client, NEED_UNWRAP, false, false);
+
+            try {
+                client.unwrap(raw, plain);
+            } catch (SSLException e) {
+                System.out.println("Client throws exception: " + e);
+                System.out.println("Engine closure status: isInboundDone="
+                        + client.isInboundDone() + ", isOutboundDone="
+                        + client.isOutboundDone() + ", handshake status="
+                        + client.getHandshakeStatus());
+                checkEngineState(client, NEED_WRAP, true, false);
+            }
+            raw.clear();
+
+            // Now the client should wrap the exception
+            client.wrap(plain, raw);
+            checkEngineState(client, NEED_UNWRAP, true, true);
+            raw.flip();
+            System.out.println("Client-to-Server:\n-----------------\n" +
+                    dumpHexBytes(raw, 16, "\n", ":"));
+
+            try {
+                server.unwrap(raw, plain);
+                checkEngineState(server, NEED_UNWRAP, false, false);
+            } catch (SSLException e) {
+                System.out.println("Server throws exception: " + e);
+                System.out.println("Engine closure status: isInboundDone="
+                        + server.isInboundDone() + ", isOutboundDone="
+                        + server.isOutboundDone() + ", handshake status="
+                        + server.getHandshakeStatus());
+                checkEngineState(server, NOT_HANDSHAKING, true, true);
+            }
+            raw.clear();
+        }
+    };
+
+
+    /*
+     * If the result indicates that we have outstanding tasks to do,
+     * go ahead and run them in this thread.
+     */
+    private static void runDelegatedTasks(SSLEngineResult result,
+            SSLEngine engine) throws Exception {
+
+        if (result.getHandshakeStatus() ==
+                SSLEngineResult.HandshakeStatus.NEED_TASK) {
+            Runnable runnable;
+            while ((runnable = engine.getDelegatedTask()) != null) {
+                System.out.println("\trunning delegated task...");
+                runnable.run();
+            }
+            SSLEngineResult.HandshakeStatus hsStatus =
+                    engine.getHandshakeStatus();
+            if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) {
+                throw new Exception(
+                    "handshake shouldn't need additional tasks");
+            }
+            System.out.println("\tnew HandshakeStatus: " + hsStatus);
+        }
+    }
+
+    /**
+     *
+     * @param data The array of bytes to dump to stdout.
+     * @param itemsPerLine The number of bytes to display per line
+     * if the {@code lineDelim} character is blank then all bytes will be
+     * printed on a single line.
+     * @param lineDelim The delimiter between lines
+     * @param itemDelim The delimiter between bytes
+     *
+     * @return The hexdump of the byte array
+     */
+    private static String dumpHexBytes(ByteBuffer data, int itemsPerLine,
+            String lineDelim, String itemDelim) {
+        StringBuilder sb = new StringBuilder();
+
+        if (data != null) {
+            data.mark();
+            for (int i = 0; i < data.limit(); i++) {
+                if (i % itemsPerLine == 0 && i != 0) {
+                    sb.append(lineDelim);
+                }
+                sb.append(String.format("%02X", data.get(i)));
+                if (i % itemsPerLine != (itemsPerLine - 1) &&
+                        i != (data.limit() -1)) {
+                    sb.append(itemDelim);
+                }
+            }
+            data.reset();
+        }
+
+        return sb.toString();
+    }
+
+    private static void createManagerFactories()
+            throws GeneralSecurityException, IOException {
+        KeyStore keystore = KeyStore.getInstance("PKCS12");
+        KeyStore truststore = KeyStore.getInstance("PKCS12");
+        KeyStore empty_ts = KeyStore.getInstance("PKCS12");
+        char[] passphrase = passwd.toCharArray();
+
+        keystore.load(new FileInputStream(keyFilename), passphrase);
+        truststore.load(new FileInputStream(trustFilename), passphrase);
+        empty_ts.load(null, "".toCharArray());
+
+        KMF = KeyManagerFactory.getInstance("PKIX");
+        KMF.init(keystore, passphrase);
+        TMF = TrustManagerFactory.getInstance("PKIX");
+        TMF.init(truststore);
+        EMPTY_TMF = TrustManagerFactory.getInstance("PKIX");
+        EMPTY_TMF.init(truststore);
+    }
+
+    private static void checkEngineState(SSLEngine engine,
+            SSLEngineResult.HandshakeStatus expectedHSStat,
+            boolean expectedInboundDone, boolean expectedOutboundDone) {
+        if (engine.getHandshakeStatus() != expectedHSStat ||
+                engine.isInboundDone() != expectedInboundDone ||
+                engine.isOutboundDone() != expectedOutboundDone) {
+            throw new RuntimeException("Error: engine not in expected state\n" +
+                    "Expected: state = " + expectedHSStat +
+                    ", inDone = " + expectedInboundDone +
+                    ", outDone = " + expectedOutboundDone + "\n" +
+                    "Actual: state = " + engine.getHandshakeStatus() +
+                    ", inDone = " + engine.isInboundDone() +
+                    ", outDone = " + engine.isOutboundDone());
+        } else {
+            System.out.println((engine.getUseClientMode() ?
+                    "Client" : "Server") + " handshake status: " +
+                    engine.getHandshakeStatus() + ", inDone = " +
+                    engine.isInboundDone() + ", outDone = " +
+                    engine.isOutboundDone());
+        }
+    }
+}
--- a/jdk/test/javax/net/ssl/TLSCommon/SSLEngineTestCase.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/net/ssl/TLSCommon/SSLEngineTestCase.java	Fri Nov 11 16:44:36 2016 +0100
@@ -27,7 +27,9 @@
 import javax.net.ssl.SNIServerName;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLSession;
 import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLException;
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.TrustManagerFactory;
@@ -57,19 +59,21 @@
     public enum Ciphers {
 
         /**
-         * Ciphers supported by the tested SSLEngine without those with kerberos
-         * authentication.
+         * Ciphers supported by the tested SSLEngine without those with
+         * kerberos authentication.
          */
         SUPPORTED_NON_KRB_CIPHERS(SSLEngineTestCase.SUPPORTED_NON_KRB_CIPHERS,
                 "Supported non kerberos"),
         /**
-         * Ciphers supported by the tested SSLEngine without those with kerberos
-         * authentication and without those with SHA256 ans SHA384.
+         * Ciphers supported by the tested SSLEngine without those with
+         * kerberos authentication and without those with SHA256 ans SHA384.
          */
-        SUPPORTED_NON_KRB_NON_SHA_CIPHERS(SSLEngineTestCase.SUPPORTED_NON_KRB_NON_SHA_CIPHERS,
+        SUPPORTED_NON_KRB_NON_SHA_CIPHERS(
+                SSLEngineTestCase.SUPPORTED_NON_KRB_NON_SHA_CIPHERS,
                 "Supported non kerberos non SHA256 and SHA384"),
         /**
-         * Ciphers supported by the tested SSLEngine with kerberos authentication.
+         * Ciphers supported by the tested SSLEngine with kerberos
+         * authentication.
          */
         SUPPORTED_KRB_CIPHERS(SSLEngineTestCase.SUPPORTED_KRB_CIPHERS,
                 "Supported kerberos"),
@@ -147,13 +151,13 @@
             = System.getProperty("test.src", ".") + FS + PATH_TO_STORES
             + FS + TRUST_STORE_FILE;
 
+    // Need an enhancement to use none-static mutable global variables.
     private static ByteBuffer net;
-    private static ByteBuffer netReplicatedClient;
-    private static ByteBuffer netReplicatedServer;
+    private static boolean doUnwrapForNotHandshakingStatus;
+    private static boolean endHandshakeLoop = false;
+
     private static final int MAX_HANDSHAKE_LOOPS = 100;
     private static final String EXCHANGE_MSG_SENT = "Hello, peer!";
-    private static boolean doUnwrapForNotHandshakingStatus;
-    private static boolean endHandshakeLoop = false;
     private static final String TEST_SRC = System.getProperty("test.src", ".");
     private static final String KTAB_FILENAME = "krb5.keytab.data";
     private static final String KRB_REALM = "TEST.REALM";
@@ -179,11 +183,13 @@
             List<String> supportedCiphersList = new LinkedList<>();
             for (String cipher : allSupportedCiphers) {
                 if (!cipher.contains("KRB5")
-                        && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+                    && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+
                     supportedCiphersList.add(cipher);
                 }
             }
-            SUPPORTED_NON_KRB_CIPHERS = supportedCiphersList.toArray(new String[0]);
+            SUPPORTED_NON_KRB_CIPHERS =
+                    supportedCiphersList.toArray(new String[0]);
         } catch (Exception ex) {
             throw new Error("Unexpected issue", ex);
         }
@@ -220,7 +226,7 @@
             List<String> supportedCiphersList = new LinkedList<>();
             for (String cipher : allSupportedCiphers) {
                 if (cipher.contains("KRB5")
-                        && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+                    && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
                     supportedCiphersList.add(cipher);
                 }
             }
@@ -240,11 +246,12 @@
             List<String> enabledCiphersList = new LinkedList<>();
             for (String cipher : enabledCiphers) {
                 if (!cipher.contains("anon") && !cipher.contains("KRB5")
-                        && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
+                    && !cipher.contains("TLS_EMPTY_RENEGOTIATION_INFO_SCSV")) {
                     enabledCiphersList.add(cipher);
                 }
             }
-            ENABLED_NON_KRB_NOT_ANON_CIPHERS = enabledCiphersList.toArray(new String[0]);
+            ENABLED_NON_KRB_NOT_ANON_CIPHERS =
+                    enabledCiphersList.toArray(new String[0]);
         } catch (Exception ex) {
             throw new Error("Unexpected issue", ex);
         }
@@ -300,10 +307,10 @@
      * Wraps data with the specified engine.
      *
      * @param engine        - SSLEngine that wraps data.
-     * @param wrapper       - Set wrapper id, e.g. "server" of "client". Used for
-     *                      logging only.
-     * @param maxPacketSize - Max packet size to check that MFLN extension works
-     *                      or zero for no check.
+     * @param wrapper       - Set wrapper id, e.g. "server" of "client".
+     *                        Used for logging only.
+     * @param maxPacketSize - Max packet size to check that MFLN extension
+     *                        works or zero for no check.
      * @param app           - Buffer with data to wrap.
      * @return - Buffer with wrapped data.
      * @throws SSLException - thrown on engine errors.
@@ -319,13 +326,13 @@
      * Wraps data with the specified engine.
      *
      * @param engine        - SSLEngine that wraps data.
-     * @param wrapper       - Set wrapper id, e.g. "server" of "client". Used for
-     *                      logging only.
-     * @param maxPacketSize - Max packet size to check that MFLN extension works
-     *                      or zero for no check.
+     * @param wrapper       - Set wrapper id, e.g. "server" of "client".
+     *                        Used for logging only.
+     * @param maxPacketSize - Max packet size to check that MFLN extension
+     *                        works or zero for no check.
      * @param app           - Buffer with data to wrap.
-     * @param result        - Array which first element will be used to output wrap
-     *                      result object.
+     * @param result        - Array which first element will be used to
+     *                        output wrap result object.
      * @return - Buffer with wrapped data.
      * @throws SSLException - thrown on engine errors.
      */
@@ -341,10 +348,10 @@
      * Wraps data with the specified engine.
      *
      * @param engine        - SSLEngine that wraps data.
-     * @param wrapper       - Set wrapper id, e.g. "server" of "client". Used for
-     *                      logging only.
-     * @param maxPacketSize - Max packet size to check that MFLN extension works
-     *                      or zero for no check.
+     * @param wrapper       - Set wrapper id, e.g. "server" of "client".
+     *                        Used for logging only.
+     * @param maxPacketSize - Max packet size to check that MFLN extension
+     *                        works or zero for no check.
      * @param app           - Buffer with data to wrap.
      * @param wantedStatus  - Specifies expected result status of wrapping.
      * @return - Buffer with wrapped data.
@@ -362,14 +369,14 @@
      * Wraps data with the specified engine.
      *
      * @param engine        - SSLEngine that wraps data.
-     * @param wrapper       - Set wrapper id, e.g. "server" of "client". Used for
-     *                      logging only.
-     * @param maxPacketSize - Max packet size to check that MFLN extension works
-     *                      or zero for no check.
+     * @param wrapper       - Set wrapper id, e.g. "server" of "client".
+     *                        Used for logging only.
+     * @param maxPacketSize - Max packet size to check that MFLN extension
+     *                        works or zero for no check.
      * @param app           - Buffer with data to wrap.
      * @param wantedStatus  - Specifies expected result status of wrapping.
-     * @param result        - Array which first element will be used to output wrap
-     *                      result object.
+     * @param result        - Array which first element will be used to output
+     *                        wrap result object.
      * @return - Buffer with wrapped data.
      * @throws SSLException - thrown on engine errors.
      */
@@ -409,9 +416,9 @@
      * @throws SSLException - thrown on engine errors.
      */
     public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
-                                      ByteBuffer net)
-            throws SSLException {
-        return doUnWrap(engine, unwrapper, net, SSLEngineResult.Status.OK, null);
+            ByteBuffer net) throws SSLException {
+        return doUnWrap(engine, unwrapper,
+                net, SSLEngineResult.Status.OK, null);
     }
 
     /**
@@ -427,26 +434,25 @@
      * @throws SSLException - thrown on engine errors.
      */
     public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
-                                      ByteBuffer net, SSLEngineResult[] result)
-            throws SSLException {
-        return doUnWrap(engine, unwrapper, net, SSLEngineResult.Status.OK, result);
+            ByteBuffer net, SSLEngineResult[] result) throws SSLException {
+        return doUnWrap(engine, unwrapper,
+                net, SSLEngineResult.Status.OK, result);
     }
 
     /**
      * Unwraps data with the specified engine.
      *
      * @param engine       - SSLEngine that unwraps data.
-     * @param unwrapper    - Set unwrapper id, e.g. "server" of "client". Used for
-     *                     logging only.
+     * @param unwrapper    - Set unwrapper id, e.g. "server" of "client".
+     *                     Used for logging only.
      * @param net          - Buffer with data to unwrap.
      * @param wantedStatus - Specifies expected result status of wrapping.
      * @return - Buffer with unwrapped data.
      * @throws SSLException - thrown on engine errors.
      */
     public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
-                                      ByteBuffer net,
-                                      SSLEngineResult.Status wantedStatus)
-            throws SSLException {
+            ByteBuffer net,
+            SSLEngineResult.Status wantedStatus) throws SSLException {
         return doUnWrap(engine, unwrapper, net, wantedStatus, null);
     }
 
@@ -454,25 +460,23 @@
      * Unwraps data with the specified engine.
      *
      * @param engine       - SSLEngine that unwraps data.
-     * @param unwrapper    - Set unwrapper id, e.g. "server" of "client". Used for
-     *                     logging only.
+     * @param unwrapper    - Set unwrapper id, e.g. "server" of "client".
+     *                       Used for logging only.
      * @param net          - Buffer with data to unwrap.
      * @param wantedStatus - Specifies expected result status of wrapping.
-     * @param result       - Array which first element will be used to output wrap
-     *                     result object.
+     * @param result       - Array which first element will be used to output
+     *                       wrap result object.
      * @return - Buffer with unwrapped data.
      * @throws SSLException - thrown on engine errors.
      */
     public static ByteBuffer doUnWrap(SSLEngine engine, String unwrapper,
-                                      ByteBuffer net,
-                                      SSLEngineResult.Status wantedStatus,
-                                      SSLEngineResult[] result)
-            throws SSLException {
-        ByteBuffer app = ByteBuffer.allocate(engine.getSession()
-                .getApplicationBufferSize());
+            ByteBuffer net, SSLEngineResult.Status wantedStatus,
+            SSLEngineResult[] result) throws SSLException {
+
+        ByteBuffer app = ByteBuffer.allocate(
+                engine.getSession().getApplicationBufferSize());
         int length = net.remaining();
-        System.out.println(unwrapper + " unwrapping "
-                + length + " bytes...");
+        System.out.println(unwrapper + " unwrapping " + length + " bytes...");
         SSLEngineResult r = engine.unwrap(net, app);
         app.flip();
         System.out.println(unwrapper + " handshake status is "
@@ -491,13 +495,14 @@
      * @param clientEngine  - Client SSLEngine.
      * @param serverEngine  - Server SSLEngine.
      * @param maxPacketSize - Maximum packet size for MFLN of zero for no limit.
-     * @param mode          - Handshake mode according to {@link HandshakeMode} enum.
+     * @param mode          - Handshake mode according to
+     *                        {@link HandshakeMode} enum.
      * @throws SSLException - thrown on engine errors.
      */
     public static void doHandshake(SSLEngine clientEngine,
-                                   SSLEngine serverEngine,
-                                   int maxPacketSize, HandshakeMode mode)
-            throws SSLException {
+        SSLEngine serverEngine,
+        int maxPacketSize, HandshakeMode mode) throws SSLException {
+
         doHandshake(clientEngine, serverEngine, maxPacketSize, mode, false);
     }
 
@@ -507,19 +512,20 @@
      *
      * @param clientEngine          - Client SSLEngine.
      * @param serverEngine          - Server SSLEngine.
-     * @param maxPacketSize         - Maximum packet size for MFLN of zero for no limit.
-     * @param mode                  - Handshake mode according to {@link HandshakeMode} enum.
+     * @param maxPacketSize         - Maximum packet size for MFLN of zero
+     *                                for no limit.
+     * @param mode                  - Handshake mode according to
+     *                                {@link HandshakeMode} enum.
      * @param enableReplicatedPacks - Set {@code true} to enable replicated
-     *                              packet sending.
+     *                                packet sending.
      * @throws SSLException - thrown on engine errors.
      */
     public static void doHandshake(SSLEngine clientEngine,
-                                   SSLEngine serverEngine, int maxPacketSize,
-                                   HandshakeMode mode,
-                                   boolean enableReplicatedPacks)
-            throws SSLException {
-        System.out.println("================================================="
-                + "===========");
+            SSLEngine serverEngine, int maxPacketSize,
+            HandshakeMode mode,
+            boolean enableReplicatedPacks) throws SSLException {
+
+        System.out.println("=============================================");
         System.out.println("Starting handshake " + mode.name());
         int loop = 0;
         if (maxPacketSize < 0) {
@@ -561,18 +567,16 @@
             if (++loop > MAX_HANDSHAKE_LOOPS) {
                 throw new Error("Too much loops for handshaking");
             }
-            System.out.println("==============================================");
-            System.out.println("Handshake loop " + loop);
-            SSLEngineResult.HandshakeStatus clientHSStatus
-                    = clientEngine.getHandshakeStatus();
-            SSLEngineResult.HandshakeStatus serverHSStatus
-                    = serverEngine.getHandshakeStatus();
-            System.out.println("Client handshake status "
-                    + clientHSStatus.name());
-            System.out.println("Server handshake status "
-                    + serverHSStatus.name());
+            System.out.println("============================================");
+            System.out.println("Handshake loop " + loop + ": round 1");
+            System.out.println("==========================");
             handshakeProcess(firstEngine, secondEngine, maxPacketSize,
                     enableReplicatedPacks);
+            if (endHandshakeLoop) {
+                break;
+            }
+            System.out.println("Handshake loop " + loop + ": round 2");
+            System.out.println("==========================");
             handshakeProcess(secondEngine, firstEngine, maxPacketSize,
                     enableReplicatedPacks);
         }
@@ -596,15 +600,15 @@
             sender = "Client";
             reciever = "Server";
             excMsgSent += " Client.";
-        } else if (toEngine.getUseClientMode() && !fromEngine.getUseClientMode()) {
+        } else if (toEngine.getUseClientMode() &&
+                !fromEngine.getUseClientMode()) {
             sender = "Server";
             reciever = "Client";
             excMsgSent += " Server.";
         } else {
             throw new Error("Test issue: both engines are in the same mode");
         }
-        System.out.println("================================================="
-                + "===========");
+        System.out.println("=============================================");
         System.out.println("Trying to send application data from " + sender
                 + " to " + reciever);
         ByteBuffer clientAppSent
@@ -643,20 +647,24 @@
         if (fromEngine.getUseClientMode() && !toEngine.getUseClientMode()) {
             from = "Client";
             to = "Server";
-        } else if (toEngine.getUseClientMode() && !fromEngine.getUseClientMode()) {
+        } else if (toEngine.getUseClientMode() &&
+                !fromEngine.getUseClientMode()) {
             from = "Server";
             to = "Client";
         } else {
             throw new Error("Both engines are in the same mode");
         }
-        System.out.println("=========================================================");
-        System.out.println("Trying to close engines from " + from + " to " + to);
+        System.out.println("=============================================");
+        System.out.println(
+                "Trying to close engines from " + from + " to " + to);
         // Sending close outbound request to peer
         fromEngine.closeOutbound();
-        app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
+        app = ByteBuffer.allocate(
+                fromEngine.getSession().getApplicationBufferSize());
         net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
         doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
-        app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
+        app = ByteBuffer.allocate(
+                fromEngine.getSession().getApplicationBufferSize());
         net = doWrap(toEngine, to, 0, app, SSLEngineResult.Status.CLOSED);
         doUnWrap(fromEngine, from, net, SSLEngineResult.Status.CLOSED);
         if (!toEngine.isInboundDone()) {
@@ -665,7 +673,8 @@
         }
         // Executing close inbound
         fromEngine.closeInbound();
-        app = ByteBuffer.allocate(fromEngine.getSession().getApplicationBufferSize());
+        app = ByteBuffer.allocate(
+                fromEngine.getSession().getApplicationBufferSize());
         net = doWrap(fromEngine, from, 0, app, SSLEngineResult.Status.CLOSED);
         doUnWrap(toEngine, to, net, SSLEngineResult.Status.CLOSED);
         if (!toEngine.isOutboundDone()) {
@@ -712,7 +721,8 @@
                 runTests(Ciphers.SUPPORTED_KRB_CIPHERS);
                 break;
             default:
-                throw new Error("Test error: unexpected test mode: " + TEST_MODE);
+                throw new Error(
+                        "Test error: unexpected test mode: " + TEST_MODE);
         }
     }
 
@@ -743,28 +753,36 @@
     }
 
     /**
-     * Returns SSLContext with TESTED_SECURITY_PROTOCOL protocol and sets up keys.
+     * Returns SSLContext with TESTED_SECURITY_PROTOCOL protocol and
+     * sets up keys.
      *
-     * @return - SSLContext with a protocol specified by TESTED_SECURITY_PROTOCOL.
+     * @return - SSLContext with a protocol specified by
+     *           TESTED_SECURITY_PROTOCOL.
      */
     public static SSLContext getContext() {
         try {
-            java.security.Security.setProperty("jdk.tls.disabledAlgorithms", "");
-            java.security.Security.setProperty("jdk.certpath.disabledAlgorithms", "");
+            java.security.Security.setProperty(
+                    "jdk.tls.disabledAlgorithms", "");
+            java.security.Security.setProperty(
+                    "jdk.certpath.disabledAlgorithms", "");
             KeyStore ks = KeyStore.getInstance("JKS");
             KeyStore ts = KeyStore.getInstance("JKS");
             char[] passphrase = PASSWD.toCharArray();
-            try (FileInputStream keyFileStream = new FileInputStream(KEY_FILE_NAME)) {
+            try (FileInputStream keyFileStream =
+                    new FileInputStream(KEY_FILE_NAME)) {
                 ks.load(keyFileStream, passphrase);
             }
-            try (FileInputStream trustFileStream = new FileInputStream(TRUST_FILE_NAME)) {
+            try (FileInputStream trustFileStream =
+                    new FileInputStream(TRUST_FILE_NAME)) {
                 ts.load(trustFileStream, passphrase);
             }
             KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
             kmf.init(ks, passphrase);
-            TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+            TrustManagerFactory tmf =
+                    TrustManagerFactory.getInstance("SunX509");
             tmf.init(ts);
-            SSLContext sslCtx = SSLContext.getInstance(TESTED_SECURITY_PROTOCOL);
+            SSLContext sslCtx =
+                    SSLContext.getInstance(TESTED_SECURITY_PROTOCOL);
             sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
             return sslCtx;
         } catch (KeyStoreException | IOException | NoSuchAlgorithmException |
@@ -791,7 +809,8 @@
     }
 
     /**
-     * Sets up and starts kerberos KDC server if SSLEngineTestCase.TEST_MODE is "krb".
+     * Sets up and starts kerberos KDC server if
+     * SSLEngineTestCase.TEST_MODE is "krb".
      */
     public static void setUpAndStartKDCIfNeeded() {
         if (TEST_MODE.equals("krb")) {
@@ -806,7 +825,9 @@
      * @param useSNI  - flag used to enable or disable using SNI extension.
      *                Needed for Kerberos.
      */
-    public static SSLEngine getClientSSLEngine(SSLContext context, boolean useSNI) {
+    public static SSLEngine getClientSSLEngine(
+            SSLContext context, boolean useSNI) {
+
         SSLEngine clientEngine = context.createSSLEngine(HOST, 80);
         clientEngine.setUseClientMode(true);
         if (useSNI) {
@@ -827,7 +848,9 @@
      * @param useSNI  - flag used to enable or disable using SNI extension.
      *                Needed for Kerberos.
      */
-    public static SSLEngine getServerSSLEngine(SSLContext context, boolean useSNI) {
+    public static SSLEngine getServerSSLEngine(
+            SSLContext context, boolean useSNI) {
+
         SSLEngine serverEngine = context.createSSLEngine();
         serverEngine.setUseClientMode(false);
         if (useSNI) {
@@ -860,18 +883,20 @@
     protected int testSomeCiphers(Ciphers ciphers) {
         int failedNum = 0;
         String description = ciphers.description;
-        System.out.println("==================================================="
-                + "=========");
+        System.out.println("===============================================");
         System.out.println(description + " ciphers testing");
-        System.out.println("==================================================="
-                + "=========");
+        System.out.println("===========================================");
         for (String cs : ciphers.ciphers) {
-            System.out.println("-----------------------------------------------"
-                    + "-------------");
+            System.out.println("---------------------------------------");
             System.out.println("Testing cipher suite " + cs);
-            System.out.println("-----------------------------------------------"
-                    + "-------------");
+            System.out.println("---------------------------------------");
             Throwable error = null;
+
+            // Reset global mutable static variables
+            net = null;
+            doUnwrapForNotHandshakingStatus = false;
+            endHandshakeLoop = false;
+
             try {
                 testOneCipher(cs);
             } catch (Throwable t) {
@@ -894,8 +919,9 @@
                 case UNSUPPORTED_CIPHERS:
                     if (error == null) {
                         System.out.println("Test Failed: " + cs);
-                        System.err.println("Test for " + cs + " should have thrown"
-                                + " IllegalArgumentException, but it has not!");
+                        System.err.println("Test for " + cs +
+                                " should have thrown " +
+                                "IllegalArgumentException, but it has not!");
                         failedNum++;
                     } else if (!(error instanceof IllegalArgumentException)) {
                         System.out.println("Test Failed: " + cs);
@@ -911,6 +937,7 @@
                             + ciphers.name());
             }
         }
+
         return failedNum;
     }
 
@@ -919,20 +946,20 @@
      *
      * @param wrapingEngine         - Engine that is expected to wrap data.
      * @param unwrapingEngine       - Engine that is expected to unwrap data.
-     * @param maxPacketSize         - Maximum packet size for MFLN of zero for no limit.
+     * @param maxPacketSize         - Maximum packet size for MFLN of zero
+     *                                for no limit.
      * @param enableReplicatedPacks - Set {@code true} to enable replicated
-     *                              packet sending.
+     *                                packet sending.
      * @throws SSLException - thrown on engine errors.
      */
     private static void handshakeProcess(SSLEngine wrapingEngine,
-                                         SSLEngine unwrapingEngine,
-                                         int maxPacketSize,
-                                         boolean enableReplicatedPacks)
-            throws SSLException {
-        SSLEngineResult.HandshakeStatus wrapingHSStatus = wrapingEngine
-                .getHandshakeStatus();
-        SSLEngineResult.HandshakeStatus unwrapingHSStatus = unwrapingEngine
-                .getHandshakeStatus();
+            SSLEngine unwrapingEngine,
+            int maxPacketSize,
+            boolean enableReplicatedPacks) throws SSLException {
+
+        HandshakeStatus wrapingHSStatus = wrapingEngine.getHandshakeStatus();
+        HandshakeStatus unwrapingHSStatus =
+                unwrapingEngine.getHandshakeStatus();
         SSLEngineResult r;
         String wrapper, unwrapper;
         if (wrapingEngine.getUseClientMode()
@@ -946,6 +973,13 @@
         } else {
             throw new Error("Both engines are in the same mode");
         }
+        System.out.println(
+                wrapper + " handshake (wrap) status " + wrapingHSStatus);
+        System.out.println(
+                unwrapper + " handshake (unwrap) status " + unwrapingHSStatus);
+
+        ByteBuffer netReplicatedClient = null;
+        ByteBuffer netReplicatedServer = null;
         switch (wrapingHSStatus) {
             case NEED_WRAP:
                 if (enableReplicatedPacks) {
@@ -960,9 +994,11 @@
                         }
                     }
                 }
-                ByteBuffer app = ByteBuffer.allocate(wrapingEngine.getSession()
-                        .getApplicationBufferSize());
+                ByteBuffer app = ByteBuffer.allocate(
+                        wrapingEngine.getSession().getApplicationBufferSize());
                 net = doWrap(wrapingEngine, wrapper, maxPacketSize, app);
+                wrapingHSStatus = wrapingEngine.getHandshakeStatus();
+                // No break, falling into unwrapping.
             case NOT_HANDSHAKING:
                 switch (unwrapingHSStatus) {
                     case NEED_TASK:
@@ -970,12 +1006,12 @@
                     case NEED_UNWRAP:
                         doUnWrap(unwrapingEngine, unwrapper, net);
                         if (enableReplicatedPacks) {
-                            System.out.println("Unwrapping replicated packet...");
+                            System.out.println(unwrapper +
+                                    " unwrapping replicated packet...");
                             if (unwrapingEngine.getHandshakeStatus()
-                                    .equals(SSLEngineResult.HandshakeStatus.NEED_TASK)) {
+                                    .equals(HandshakeStatus.NEED_TASK)) {
                                 runDelegatedTasks(unwrapingEngine);
                             }
-                            runDelegatedTasks(unwrapingEngine);
                             ByteBuffer netReplicated;
                             if (unwrapingEngine.getUseClientMode()) {
                                 netReplicated = netReplicatedClient;
@@ -983,7 +1019,8 @@
                                 netReplicated = netReplicatedServer;
                             }
                             if (netReplicated != null) {
-                                doUnWrap(unwrapingEngine, unwrapper, netReplicated);
+                                doUnWrap(unwrapingEngine,
+                                        unwrapper, netReplicated);
                             } else {
                                 net.flip();
                                 doUnWrap(unwrapingEngine, unwrapper, net);
@@ -994,15 +1031,39 @@
                         break;
                     case NOT_HANDSHAKING:
                         if (doUnwrapForNotHandshakingStatus) {
+                            System.out.println("Not handshake status unwrap");
                             doUnWrap(unwrapingEngine, unwrapper, net);
                             doUnwrapForNotHandshakingStatus = false;
                             break;
                         } else {
-                            endHandshakeLoop = true;
+                            if (wrapingHSStatus ==
+                                        HandshakeStatus.NOT_HANDSHAKING) {
+                                System.out.println("Handshake is completed");
+                                endHandshakeLoop = true;
+                            }
                         }
                         break;
+                    case NEED_WRAP:
+                        SSLSession session = unwrapingEngine.getSession();
+                        int bufferSize = session.getApplicationBufferSize();
+                        ByteBuffer b = ByteBuffer.allocate(bufferSize);
+                        net = doWrap(unwrapingEngine,
+                                        unwrapper, maxPacketSize, b);
+                        unwrapingHSStatus =
+                                unwrapingEngine.getHandshakeStatus();
+                        if ((wrapingHSStatus ==
+                                    HandshakeStatus.NOT_HANDSHAKING) &&
+                            (unwrapingHSStatus ==
+                                    HandshakeStatus.NOT_HANDSHAKING)) {
+
+                            System.out.println("Handshake is completed");
+                            endHandshakeLoop = true;
+                        }
+
+                        break;
                     default:
-                        throw new Error("Unexpected unwraping engine handshake status "
+                        throw new Error(
+                                "Unexpected unwraping engine handshake status "
                                 + unwrapingHSStatus.name());
                 }
                 break;
@@ -1027,8 +1088,8 @@
         while ((runnable = engine.getDelegatedTask()) != null) {
             runnable.run();
         }
-        SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
-        if (hs == SSLEngineResult.HandshakeStatus.NEED_TASK) {
+        HandshakeStatus hs = engine.getHandshakeStatus();
+        if (hs == HandshakeStatus.NEED_TASK) {
             throw new Error("Handshake shouldn't need additional tasks.");
         }
     }
--- a/jdk/test/javax/print/attribute/Services_getDocFl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/print/attribute/Services_getDocFl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -28,7 +28,7 @@
 
 /*
  * @test
- * @bug 4901243 8040139
+ * @bug 4901243 8040139 8167291
  * @summary JPG, GIF, and PNG DocFlavors (URL) should be supported if Postscript is supported.
  * @run main Services_getDocFl
 */
@@ -58,6 +58,7 @@
             pngImagesSupported = false;
             gifImagesSupported = false;
             jpgImagesSupported = false;
+            psSupported = false;
             for (int j=0; j<flavors.length; j++) {
                 System.out.println(flavors[j]);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/ClosedReceiver.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,184 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly
+ */
+public class ClosedReceiver {
+
+    public static void main(String[] args) throws Exception {
+        out("#4616517: Receiver.send() does not work properly");
+        if (!isMidiInstalled()) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+            return;
+        }
+
+        boolean passed = true;
+
+        passed &= testReceiverSend();
+        passed &= testClosedReceivers();
+        if (passed) {
+            out("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED.");
+        }
+    }
+
+    /**
+     * Execute Receiver.send() and expect that there is no exception.
+     */
+    private static boolean testReceiverSend() {
+        boolean result = true;
+
+        Receiver receiver;
+        ShortMessage shMsg = new ShortMessage();
+
+        try {
+            receiver = MidiSystem.getReceiver();
+            shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93);
+            try {
+                receiver.send( shMsg, -1 );
+            } catch(IllegalStateException ilEx) {
+                ilEx.printStackTrace(System.out);
+                out("IllegalStateException was thrown incorrectly!");
+                result = false;
+            }
+            receiver.close();
+        } catch(MidiUnavailableException e) {
+            out("Midi unavailable, cannot test.");
+        } catch(InvalidMidiDataException ine) {
+            out("InvalidMidiDataException, cannot test.");
+        }
+        return result;
+    }
+
+    private static boolean testClosedReceivers() {
+        boolean result = true;
+        Receiver receiver;
+        Synthesizer synt = null;
+
+        // test Synthesizer's Receiver
+        try {
+            synt = MidiSystem.getSynthesizer();
+            synt.open();
+        } catch(MidiUnavailableException e) {
+            out("Midi unavailable, cannot test.");
+            return result;
+        }
+        try {
+            receiver = synt.getReceiver();
+        } catch (MidiUnavailableException e) {
+            out("unable to get Receiver from synthesizer, cannot test.");
+            return result;
+        }
+        result &= testClosedReceiver(receiver);
+        synt.close();
+
+        // test all MidiDevices' Receivers
+
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                if (device.getMaxReceivers() != 0) {
+                    receiver = device.getReceiver();
+                    result &= testClosedReceiver(receiver);
+                }
+            } catch (Exception e) {
+                out(e);
+                out("cannot test.");
+                return result;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute send() on a closed Receivers and expect IllegalStateException.
+     */
+    private static boolean testClosedReceiver(Receiver receiver) {
+        boolean result = true;
+        out("testing Receiver: " + receiver);
+        ShortMessage shMsg = new ShortMessage();
+        try {
+            shMsg.setMessage(ShortMessage.NOTE_ON, 0,60, 93);
+        } catch(InvalidMidiDataException e) {
+            out(e);
+            out("unable to construct ShortMessage, cannot test.");
+            return result;
+        }
+
+        // begin of test
+        receiver.close();
+        try {
+            receiver.send( shMsg, -1 );
+            out("IllegalStateException was not thrown "
+                + "on Receiver.send()!");
+            result = false;
+        } catch(IllegalStateException e) {
+            out("IllegalStateException was thrown. Ok.");
+        }
+        return result;
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    private static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = !(device instanceof Sequencer)
+                        && !(device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/IOLoop.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,404 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.ByteArrayOutputStream;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.SysexMessage;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4782924
+ * @bug 4812168
+ * @bug 4356787
+ * @summary MIDI i/o. This is an interactive test! Start it and follow the
+ *          instructions.
+ * @run main/manual IOLoop
+ */
+public class IOLoop {
+    private static final int LONG_SYSEX_LENGTH = 2000;
+
+    private static Receiver receiver;
+    private static Transmitter transmitter;
+    private static MidiMessage receivedMessage;
+    private static ByteArrayOutputStream baos;
+    private static int expectedBytes;
+    private static int receivedBytes;
+    private static Object lock = new Object();
+    private static long lastTimestamp;
+
+    public static void main(String[] args) throws Exception {
+        ShortMessage sMsg = new ShortMessage();
+        SysexMessage syMsg = new SysexMessage();
+        boolean isTestPassed = true;
+        boolean sysExTestPassed = true;
+        boolean isTestExecuted = true;
+
+        out("To run this test successfully, you need to have attached");
+        out("  your MIDI out port with the MIDI in port.");
+
+        MidiDevice inDev = null;
+        MidiDevice outDev = null;
+
+        // setup
+        try {
+            MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+
+            int devNum = Integer.decode(args[0]).intValue();
+            out("-> opening Transmitter from "+infos[devNum]);
+            inDev = MidiSystem.getMidiDevice(infos[devNum]);
+            inDev.open();
+            transmitter = inDev.getTransmitter();
+            Receiver testReceiver = new TestReceiver();
+            transmitter.setReceiver(testReceiver);
+
+            devNum = Integer.decode(args[1]).intValue();
+            out("-> opening Receiver from "+infos[devNum]);
+            outDev = MidiSystem.getMidiDevice(infos[devNum]);
+            outDev.open();
+            receiver = outDev.getReceiver();
+
+        } catch (Exception e) {
+            System.out.println(e);
+            System.out.println("Cannot test!");
+            return;
+        }
+
+        // test
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 27, 100);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_OFF | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 4, 27, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.NOTE_ON | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 11, 98, 99);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.POLY_PRESSURE | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 13, 1, 63);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTROL_CHANGE | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 2, 120, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PROGRAM_CHANGE | 15, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 6, 30, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CHANNEL_PRESSURE | 15, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 6, 56, 4);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 0, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.PITCH_BEND | 15, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.MIDI_TIME_CODE, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 1, 77);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_POSITION_POINTER, 127, 127);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 51, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 0, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SONG_SELECT, 127, 0);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.TUNE_REQUEST);
+        isTestPassed &= testMessage(sMsg);
+
+        sMsg.setMessage(ShortMessage.TIMING_CLOCK);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.START);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.CONTINUE);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.STOP);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.ACTIVE_SENSING);
+        isTestPassed &= testMessage(sMsg);
+        sMsg.setMessage(ShortMessage.SYSTEM_RESET);
+        isTestPassed &= testMessage(sMsg);
+
+        syMsg.setMessage(new byte[]{(byte) 0xF0, (byte) 0xF7}, 2);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x01, (byte) 0xF7}, 3);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x02, 0x03, (byte) 0xF7}, 4);
+        isTestPassed &= testMessage(syMsg);
+        syMsg.setMessage(new byte[]{(byte) 0xF0, 0x04, 0x05, 0x06, (byte) 0xF7}, 5);
+        isTestPassed &= testMessage(syMsg);
+
+        if (isTestPassed) {
+            byte[] sysexArray = new byte[LONG_SYSEX_LENGTH];
+            sysexArray[0] = (byte) 0xF0;
+            for (int i = 1; i < sysexArray.length; i++) {
+                sysexArray[i] = (byte) (i % 0x80);
+            }
+//          syMsg.setMessage(new byte[]{(byte) 0xF7, (byte) ShortMessage.START}, 2);
+//          sMsg.setMessage(ShortMessage.START);
+//          isTestPassed &= testMessage(syMsg, sMsg, DEFAULT_SLEEP_INTERVALL);
+            for (int trial = sysexArray.length; trial > 4; trial -= 1234) {
+                sleep(500);
+                sysexArray[trial - 1] = (byte) 0xF7;
+                syMsg.setMessage(sysexArray, trial);
+                sysExTestPassed &= testMessage(syMsg);
+                break;
+            }
+        }
+
+        // cleanup
+        receiver.close();
+        transmitter.close();
+        inDev.close();
+        outDev.close();
+
+        if (isTestExecuted) {
+            if (isTestPassed && sysExTestPassed) {
+
+                out("Test PASSED.");
+            } else {
+                if (isTestPassed
+                    && !sysExTestPassed
+                    && (System.getProperty("os.name").startsWith("Windows"))) {
+                    out("Some Windows MIDI i/o drivers have a problem with larger ");
+                    out("sys ex messages. The failing sys ex cases are OK, therefore.");
+                    out("Test PASSED.");
+                } else {
+                    throw new Exception("Test FAILED.");
+                }
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static boolean testMessage(MidiMessage message) {
+        receivedMessage = null;
+        baos = new ByteArrayOutputStream();
+        expectedBytes = message.getLength();
+        receivedBytes = 0;
+        System.out.print("Sending message " + getMessageString(message.getMessage())+"...");
+        receiver.send(message, -1);
+        /* sending 3 bytes can roughly be done in 1 millisecond,
+         * so this estimate waits at max 3 times longer than the message takes,
+         * plus a little offset to allow the MIDI subsystem some processing time
+         */
+        int offset = 300; // standard offset 100 millis
+        if (message instanceof SysexMessage) {
+            // add a little processing time to sysex messages
+            offset += 1000;
+        }
+        if (receivedBytes < expectedBytes) {
+            sleep(expectedBytes + offset);
+        }
+        boolean equal;
+        byte[] data = baos.toByteArray();
+        if (data.length > 0) {
+            equal = messagesEqual(message.getMessage(), data);
+        } else {
+            equal = messagesEqual(message, receivedMessage);
+            if (receivedMessage != null) {
+                data = receivedMessage.getMessage();
+            } else {
+                data = null;
+            }
+        }
+        if (!equal) {
+            if ((message.getStatus() & 0xF0) == ShortMessage.PITCH_BEND) {
+                out("NOT failed (may expose a bug in ALSA)");
+                equal = true;
+                sleep(100);
+            }
+            if ((message.getStatus() == 0xF6) && (message.getLength() == 1)) {
+                out("NOT failed (may expose an issue on Solaris)");
+                equal = true;
+                sleep(100);
+            }
+            else if ((message.getStatus()) == 0xF0 && message.getLength() < 4) {
+                out("NOT failed (not a correct sys ex message)");
+                equal = true;
+                sleep(200);
+            } else {
+                out("FAILED:");
+                out("  received as " + getMessageString(data));
+            }
+        } else {
+            System.out.println("OK");
+        }
+        return equal;
+    }
+
+    private static void sleep(int milliseconds) {
+        synchronized(lock) {
+            try {
+                lock.wait(milliseconds);
+            } catch (InterruptedException e) {
+            }
+        }
+    }
+
+    private static String getMessageString(byte[] data) {
+        String s;
+        if (data == null) {
+            s = "<null>";
+        } else if (data.length == 0) {
+            s = "0-sized array";
+        } else {
+            int status = data[0] & 0xFF;
+            if (data.length <= 3) {
+                if (status < 240) {
+                    s = "command 0x" + Integer.toHexString(status & 0xF0) + " channel " + (status & 0x0F);
+                } else {
+                    s = "status 0x" + Integer.toHexString(status);
+                }
+                if (data.length > 1) {
+                    s += " data 0x" + Integer.toHexString(data[1] & 0xFF);
+                    if (data.length > 2) {
+                        s += " 0x" + Integer.toHexString(data[2] & 0xFF);
+                    }
+                }
+            } else {
+                s = "status " + Integer.toHexString(status)+" and length "+data.length+" bytes";
+            }
+        }
+        return s;
+    }
+
+    private static boolean messagesEqual(MidiMessage m1, MidiMessage m2) {
+        if (m1 == null || m2 == null) {
+            return false;
+        }
+        if (m1.getLength() != m2.getLength()) {
+            return false;
+        }
+        byte[] array1 = m1.getMessage();
+        byte[] array2 = m2.getMessage();
+        return messagesEqual(array1, array2);
+    }
+
+    private static boolean messagesEqual(byte[] a1, byte[] a2) {
+        if (a1.length != a2.length) return false;
+        for (int i = 0; i < a1.length; i++) {
+            if (a1[i] != a2[i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static void out(String s) {
+        System.out.println(s);
+        System.out.flush();
+    }
+
+    private static String canIn(MidiDevice dev) {
+        if (dev.getMaxTransmitters() != 0) {
+            return "IN ";
+        }
+        return "   ";
+    }
+
+    private static String canOut(MidiDevice dev) {
+        if (dev.getMaxReceivers() != 0) {
+            return "OUT ";
+        }
+        return "   ";
+    }
+
+
+    private static void checkTimestamp(long timestamp) {
+        // out("checking timestamp...");
+        if (timestamp < 1) {
+            out("timestamp 0 or negative!");
+        }
+        if (timestamp < lastTimestamp) {
+            out("timestamp not progressive!");
+        }
+        lastTimestamp = timestamp;
+    }
+
+    private static class TestReceiver implements Receiver {
+        public void send(MidiMessage message, long timestamp) {
+            //System.out.print(""+message.getLength()+"..");
+            checkTimestamp(timestamp);
+            try {
+                receivedMessage = message;
+                if (message.getStatus() == 0xF0
+                    || (message.getLength() > 3 && message.getStatus() != 0xF7)) {
+                    // sys ex message
+                    byte[] data = message.getMessage();
+                    baos.write(data);
+                    receivedBytes += data.length;
+                }
+                else if (message.getStatus() == 0xF7) {
+                    // sys ex cont'd message
+                    byte[] data = message.getMessage();
+                    // ignore the prepended 0xF7
+                    baos.write(data, 1, data.length-1);
+                    receivedBytes += (data.length - 1);
+                } else {
+                    receivedBytes += message.getLength();
+                }
+                if (receivedBytes >= expectedBytes) {
+                    synchronized(lock) {
+                        lock.notify();
+                    }
+                }
+                System.out.print(""+receivedBytes+"..");
+
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+
+        public void close() {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiDeviceGetReceivers.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,187 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4931387
+ * @summary Add methods to MidiDevice to get list of Transmitters and Receivers
+ */
+public class MidiDeviceGetReceivers {
+
+    private static boolean executed = false;
+    private static boolean failed = false;
+
+    public static void main(String[] args) throws Exception {
+        out("unit test 4931387: Add methods to MidiDevice to get list of Transmitters and Receivers");
+        doAllTests();
+        if (executed) {
+            if (failed) throw new Exception("Test FAILED!");
+            out("Test PASSED.");
+        } else {
+            out("Test NOT failed.");
+        }
+    }
+
+    private static void doAllTests() {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+                doTest(device);
+            } catch (MidiUnavailableException e) {
+                out("Exception occured when retrieving device "+infos[i]+": "+e);
+            }
+        }
+        if (infos.length == 0) {
+            out("No MIDI devices exist or sound drivers not installed!");
+        }
+    }
+
+    private static boolean containsReceiver(MidiDevice dev, Receiver rec) {
+        List<Receiver> recvs = dev.getReceivers();
+        return recvs.contains(rec);
+    }
+
+    private static boolean containsTransmitter(MidiDevice dev, Transmitter tra) {
+        List<Transmitter> tras = dev.getTransmitters();
+        return tras.contains(tra);
+    }
+
+    private static void doTest(MidiDevice device) {
+        boolean thisFailed = false;
+        out1("Testing: " + device+"...");
+        try {
+            device.open();
+        } catch (Exception e) {
+            out2("device.open threw exception: "+e);
+            out2("cannot test this device.");
+            return;
+        }
+        if (device.getMaxReceivers() != 0) {
+            // device offers receivers
+            try {
+                List<Receiver> origList = device.getReceivers();
+                Receiver rec = device.getReceiver();
+                if (!containsReceiver(device, rec)) {
+                    out2("Getting a receiver did not add it to device list!");
+                    thisFailed = true;
+                }
+                if (origList.contains(rec)) {
+                    out2("Original unmodifiable list was modified by adding a receiver!");
+                    thisFailed = true;
+                }
+                rec.close();
+                if (containsReceiver(device, rec)) {
+                    out2("Closing a receiver did not remove it from device list!");
+                    thisFailed = true;
+                }
+                // add a new receiver so that the device.close will really test
+                // that the receiver is removed
+                rec = device.getReceiver();
+                if (!containsReceiver(device, rec)) {
+                    out2("Getting a receiver again did not add it to device list!");
+                    thisFailed = true;
+                }
+            } catch (MidiUnavailableException e) {
+                out2("Exception on getting Receiver: " + e);
+            }
+        }
+        if (device.getMaxTransmitters() != 0) {
+            // device offers transmitters
+            try {
+                List<Transmitter> origList = device.getTransmitters();
+                Transmitter tra = device.getTransmitter();
+                if (!containsTransmitter(device, tra)) {
+                    out2("Getting a transmitter did not add it to device list!");
+                    thisFailed = true;
+                }
+                if (origList.contains(tra)) {
+                    out2("Original unmodifiable list was modified by adding a transmitter!");
+                    thisFailed = true;
+                }
+                tra.close();
+                if (containsTransmitter(device, tra)) {
+                    out2("Closing a transmitter did not remove it from device list!");
+                    thisFailed = true;
+                }
+                tra = device.getTransmitter();
+                if (!containsTransmitter(device, tra)) {
+                    out2("Getting a transmitter again did not add it to device list!");
+                    thisFailed = true;
+                }
+            } catch (MidiUnavailableException e) {
+                out("Exception on getting Transmitter: " + e);
+            }
+        }
+        try {
+            device.close();
+            if (device.getTransmitters().size() > 0) {
+                out2(" Device still has transmitters after close() was called!");
+                thisFailed = true;
+            }
+            if (device.getReceivers().size() > 0) {
+                out2(" Device still has receivers after close() was called!");
+                thisFailed = true;
+            }
+        } catch (Exception e) {
+            out2("device.close threw exception: "+e);
+        }
+        if (!thisFailed) {
+            out("OK");
+        } else {
+            failed = true;
+        }
+        executed = true;
+    }
+
+    static boolean lfMissing = false;
+
+    private static void out(String message) {
+        lfMissing = true;
+        System.out.println(message);
+    }
+
+    /* don't print LF at end */
+    private static void out1(String message) {
+        System.out.print(message);
+        lfMissing = true;
+    }
+
+    /* print at a new line, indented */
+    private static void out2(String message) {
+        if (lfMissing) {
+            System.out.println();
+            lfMissing = false;
+        }
+        System.out.println("  "+message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiIO.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,92 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+
+/**
+ * @test
+ * @bug 4356787
+ * @summary MIDI device I/O is not working
+ */
+public class MidiIO {
+
+    public static void main(String[] args) throws Exception {
+        out("4356787: MIDI device I/O is not working (windows)");
+
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            boolean forInput=true;
+            boolean forOutput=true;
+            int outOnlyCount=0;
+            int inOnlyCount=0;
+            out("  available MIDI devices:");
+            MidiDevice.Info[] aInfos = MidiSystem.getMidiDeviceInfo();
+            for (int i = 0; i < aInfos.length; i++) {
+                try {
+                    MidiDevice      device = MidiSystem.getMidiDevice(aInfos[i]);
+                    boolean         bAllowsInput = (device.getMaxTransmitters() != 0);
+                    boolean         bAllowsOutput = (device.getMaxReceivers() != 0);
+                    if (bAllowsInput && !bAllowsOutput) {
+                        inOnlyCount++;
+                    }
+                    if (!bAllowsInput && bAllowsOutput) {
+                        outOnlyCount++;
+                    }
+                    if ((bAllowsInput && forInput) || (bAllowsOutput && forOutput)) {
+                        out(""+i+"  "
+                                +(bAllowsInput?"IN ":"   ")
+                                +(bAllowsOutput?"OUT ":"    ")
+                                +aInfos[i].getName()+", "
+                                +aInfos[i].getVendor()+", "
+                                +aInfos[i].getVersion()+", "
+                                +aInfos[i].getDescription());
+                    }
+                }
+                catch (MidiUnavailableException e) {
+                    // device is obviously not available...
+                }
+            }
+            if (aInfos.length == 0) {
+                out("No devices available. Test should be run on systems with MIDI drivers installed.");
+            } else {
+                if (outOnlyCount>1) {
+                    if (inOnlyCount==0) {
+                        //throw new Exception("No input devices! test fails.");
+                        out("System provides out devices, but no input devices. This means either");
+                        out("a bug in Java Sound, or the drivers are not set up correctly.");
+                    }
+                    out("Test passed.");
+                } else {
+                    out("no MIDI I/O installed. Test should be run on systems with MIDI drivers installed.");
+                }
+            }
+        } else {
+            out("  -- not on Windows. Test doesn't apply.");
+        }
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/MidiOutGetMicrosecondPositionBug.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4903786
+ * @summary MIDI OUT does not implement getMicrosecondPosition() consistently
+ */
+public class MidiOutGetMicrosecondPositionBug {
+    static int successfulTests = 0;
+
+    private static void testDevice(MidiDevice device) throws Exception {
+        boolean timestampsAvailable = false;
+        boolean timestampPrecisionOk = false;
+        try {
+            // expected behaviour if not opened?
+            device.open();
+            /* First, we're testing if timestamps are provided at all.
+               Returning -1 (unsupported), while allowed by the API
+               specification, is not sufficient to pass this test. */
+            long timestamp = device.getMicrosecondPosition();
+            timestampsAvailable = (timestamp != -1);
+
+            /* Then, we're testing the precision. Note that the system time
+               is measured in milliseconds, while the device time is measured
+               in microseconds. */
+
+            long systemTime1 = System.currentTimeMillis();
+            long deviceTime1 = device.getMicrosecondPosition();
+            // rest for 5 seconds
+            Thread.sleep(5000);
+            long systemTime2 = System.currentTimeMillis();
+            long deviceTime2 = device.getMicrosecondPosition();
+
+            // now both period measurements are calculated in milliseconds.
+            long systemDuration = systemTime2 - systemTime1;
+            long deviceDuration = (deviceTime2 - deviceTime1) / 1000;
+            long delta = Math.abs(systemDuration - deviceDuration);
+            // a deviation of 0.5 seconds (= 500 ms) is allowed.
+            timestampPrecisionOk = (delta <= 500);
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - " + t.toString());
+            return;
+        } finally {
+            device.close();
+        }
+        if (! timestampsAvailable) {
+            throw new Exception("timestamps are not supported");
+        }
+        if (! timestampPrecisionOk) {
+            throw new Exception("device timer not precise enough");
+        }
+        successfulTests++;
+    }
+
+    private static void doAll() throws Exception {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i=0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if ((! (device instanceof Sequencer)) &&
+                (! (device instanceof Synthesizer)) &&
+                (device.getMaxReceivers() > 0 || device.getMaxReceivers() == -1)) {
+
+                System.out.println("--------------");
+                System.out.println("Testing MIDI device: " + infos[i]);
+                testDevice(device);
+            }
+            if (infos.length==0) {
+                System.out.println("No MIDI devices available!");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!isMidiInstalled()) {
+            return;
+        }
+        doAll();
+        if (successfulTests==0) {
+            System.out.println("Could not execute any of the tests. Test NOT failed.");
+        } else {
+            System.out.println("Test PASSED.");
+        }
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    public static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/OpenClose.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,611 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly. Tests open/close behaviour
+ *          of MidiDevices. For this test, it is essential that the MidiDevice
+ *          picked from the list of devices (MidiSystem.getMidiDeviceInfo()) is
+ *          the same as the one used by
+ *          MidiSystem.getReceiver()/getTransmitter(). To achieve this, default
+ *          provider properties for Receivers/Transmitters are used.
+ */
+public class OpenClose {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    public static void main(String[] args) throws Exception {
+        boolean failed = false;
+        out("#4616517: Receiver.send() does not work properly");
+        if (!isMidiInstalled()) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+            return;
+        }
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        MidiDevice outDevice = null;
+        MidiDevice inDevice = null;
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if (! (device instanceof Synthesizer) &&
+                ! (device instanceof Sequencer)) {
+                if (device.getMaxReceivers() != 0) {
+                    outDevice = device;
+                }
+                if (device.getMaxTransmitters() != 0) {
+                    inDevice = device;
+                }
+            }
+        }
+        if (outDevice != null) {
+            // set the default provider properties
+            System.setProperty(Receiver.class.getName(),
+                               "#" + outDevice.getDeviceInfo().getName());
+        }
+        if (inDevice != null) {
+            System.setProperty(Transmitter.class.getName(),
+                               "#" + inDevice.getDeviceInfo().getName());
+        }
+        out("Using MIDI OUT Device: " + outDevice);
+        out("Using MIDI IN Device: " + inDevice);
+
+        isTestExecuted = false;
+        if (outDevice != null) {
+            isTestExecuted = true;
+            TestHelper testHelper = new ReceiverTestHelper(outDevice);
+            try {
+                doTest("Receiver", testHelper);
+                failed |= testHelper.hasFailed();
+            } catch (Exception e) {
+                out("Exception occured, cannot test!");
+                isTestExecuted = false;
+            }
+        }
+
+        if (inDevice != null) {
+            isTestExecuted = true;
+            TestHelper testHelper = new TransmitterTestHelper(inDevice);
+            try {
+                doTest("Transmitter", testHelper);
+                failed |= testHelper.hasFailed();
+            } catch (Exception e) {
+                out("Exception occured, cannot test!");
+                isTestExecuted = false;
+            }
+        }
+
+        isTestPassed = ! failed;
+
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static void doTest(String type,
+                               TestHelper testHelper) throws Exception {
+        /* Case 1:
+           - MidiDevice.open()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 1...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 2a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 2a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 2b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 2b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 3a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 3a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 3b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 3b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 4a:
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 4a...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 4b:
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.open()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 4b...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 5a:
+           - MidiDevice.open()
+           - MidiSystem.get[Receiver|Transmitter]()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 5a...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 5b:
+           - MidiDevice.open()
+           - MidiDevice.get[Receiver|Transmitter]()
+           - MidiDevice.close()
+           - [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case 5b...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 6a:
+           - MidiDevice.open()
+           - MidiSystem.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 6a...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 6b:
+           - MidiDevice.open()
+           - MidiDevice.get[Receiver|Transmitter]()
+           - [Receiver|Transmitter].close()
+           - MidiDevice.close()
+        */
+        out("checking " + type + " case 6b...");
+        testHelper.checkClosed();
+
+        testHelper.openDevice();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 7:
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - [Receiver|Transmitter].close() // 2
+           - [Receiver|Transmitter].close() // 1
+        */
+        out("checking " + type + " case 7...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 8:
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - [Receiver|Transmitter].close() // 1
+           - [Receiver|Transmitter].close() // 2
+        */
+        out("checking " + type + " case 8...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 9:
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - [Receiver|Transmitter].close() // 2
+           - [Receiver|Transmitter].close() // 1
+        */
+        out("checking " + type + " case 9...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case 10:
+           - MidiDevice.get[Receiver|Transmitter]() // 2
+           - MidiSystem.get[Receiver|Transmitter]() // 1
+           - [Receiver|Transmitter].close() // 1
+           - [Receiver|Transmitter].close() // 2
+        */
+        out("checking " + type + " case 10...");
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectDevice();
+        testHelper.checkClosed();
+
+        testHelper.fetchObjectMidiSystem();
+        testHelper.checkOpen();
+
+        testHelper.closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        testHelper.closeObjectDevice();
+        testHelper.checkClosed();
+
+        out("...OK");
+
+        /* Case N - 1:
+           - 10 x MidiSystem.get[Receiver|Transmitter]()
+           - 10 x [Receiver|Transmitter].close()
+        */
+        out("checking " + type + " case N - 1...");
+        TestHelper[] testHelpers = new TestHelper[10];
+        for (int i = 0; i < 10; i++) {
+            testHelpers[i] = (TestHelper) testHelper.clone();
+        }
+        testHelper.checkClosed();
+
+        for (int i = 0; i < 10; i++) {
+            testHelpers[i].fetchObjectMidiSystem();
+            testHelper.checkOpen();
+        }
+
+
+        for (int i = 0; i < 9; i++) {
+            testHelpers[i].closeObjectMidiSystem();
+            testHelper.checkOpen();
+        }
+
+        testHelpers[9].closeObjectMidiSystem();
+        testHelper.checkClosed();
+
+        out("...OK");
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    private static abstract class TestHelper implements Cloneable {
+        private MidiDevice device;
+        private boolean failed;
+
+        protected TestHelper(MidiDevice device) {
+            this.device = device;
+            failed = false;
+        }
+
+        protected MidiDevice getDevice() {
+            return device;
+        }
+
+        public boolean hasFailed() {
+            return failed;
+        }
+
+        public void openDevice() throws MidiUnavailableException {
+            getDevice().open();
+        }
+
+        public void closeDevice() {
+            getDevice().close();
+        }
+
+        public void checkOpen(){
+            checkOpen(getDevice(), true);
+        }
+
+        public void checkClosed(){
+            checkOpen(getDevice(), false);
+        }
+
+        private void checkOpen(MidiDevice device, boolean desiredState) {
+            if (device.isOpen() != desiredState) {
+                out("device should be " +
+                                    getStateString(desiredState) + ", but isn't!");
+                failed = true;
+            }
+        }
+
+
+        private String getStateString(boolean state) {
+            return state ? "open" : "closed";
+        }
+
+
+        public abstract void fetchObjectMidiSystem() throws MidiUnavailableException;
+        public abstract void fetchObjectDevice() throws MidiUnavailableException;
+        public abstract void closeObjectMidiSystem();
+        public abstract void closeObjectDevice();
+
+        public Object clone() {
+            try {
+                return super.clone();
+            } catch (CloneNotSupportedException e) {
+                return null;
+            }
+        }
+    }
+
+    private static class ReceiverTestHelper extends TestHelper {
+        private Receiver receiverMidiSystem;
+        private Receiver receiverDevice;
+
+        public ReceiverTestHelper(MidiDevice device) {
+            super(device);
+        }
+
+        public void fetchObjectMidiSystem() throws MidiUnavailableException {
+            receiverMidiSystem = MidiSystem.getReceiver();
+        }
+
+
+        public void fetchObjectDevice() throws MidiUnavailableException {
+            receiverDevice = getDevice().getReceiver();
+        }
+
+
+        public void closeObjectMidiSystem() {
+            receiverMidiSystem.close();
+        }
+
+
+        public void closeObjectDevice() {
+            receiverDevice.close();
+        }
+    }
+
+    private static class TransmitterTestHelper extends TestHelper {
+        private Transmitter transmitterMidiSystem;
+        private Transmitter transmitterDevice;
+
+        public TransmitterTestHelper(MidiDevice device) {
+            super(device);
+        }
+
+        public void fetchObjectMidiSystem() throws MidiUnavailableException {
+            transmitterMidiSystem = MidiSystem.getTransmitter();
+        }
+
+
+        public void fetchObjectDevice() throws MidiUnavailableException {
+            transmitterDevice = getDevice().getTransmitter();
+        }
+
+
+        public void closeObjectMidiSystem() {
+            transmitterMidiSystem.close();
+        }
+
+
+        public void closeObjectDevice() {
+            transmitterDevice.close();
+        }
+    }
+
+    /**
+     * Returns true if at least one MIDI (port) device is correctly installed on
+     * the system.
+     */
+    public static boolean isMidiInstalled() {
+        boolean result = false;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            try {
+                MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+                result = ! (device instanceof Sequencer) && ! (device instanceof Synthesizer);
+            } catch (Exception e1) {
+                System.err.println(e1);
+            }
+            if (result)
+                break;
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/ReceiverTransmitterAvailable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,113 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4616517
+ * @summary Receiver.send() does not work properly
+ */
+public class ReceiverTransmitterAvailable {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    public static void main(String[] args) throws Exception {
+        out("#4616517: Receiver.send() does not work properly");
+        doAllTests();
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static void doAllTests() {
+        boolean problemOccured = false;
+        boolean succeeded = true;
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+                succeeded &= doTest(device);
+            } catch (MidiUnavailableException e) {
+                out("exception occured; cannot test");
+                problemOccured = true;
+            }
+        }
+        if (infos.length == 0) {
+            out("Soundcard does not exist or sound drivers not installed!");
+            out("This test requires sound drivers for execution.");
+        }
+        isTestExecuted = !problemOccured;
+        isTestPassed = succeeded;
+    }
+
+    private static boolean doTest(MidiDevice device) {
+        boolean succeeded = true;
+        out("Testing: " + device);
+        boolean expectingReceivers = (device.getMaxReceivers() != 0);
+        boolean expectingTransmitters = (device.getMaxTransmitters() != 0);
+        try {
+            Receiver rec = device.getReceiver();
+            rec.close();
+            if (! expectingReceivers) {
+                out("no exception on getting Receiver");
+                succeeded = false;
+            }
+        } catch (MidiUnavailableException e) {
+            if (expectingReceivers) {
+                out("Exception on getting Receiver: " + e);
+                succeeded = false;
+            }
+        }
+        try {
+            Transmitter trans = device.getTransmitter();
+            trans.close();
+            if (! expectingTransmitters) {
+                out("no exception on getting Transmitter");
+                succeeded = false;
+            }
+        } catch (MidiUnavailableException e) {
+            if (expectingTransmitters) {
+                out("Exception on getting Transmitter: " + e);
+                succeeded = false;
+            }
+        }
+        return succeeded;
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Devices/Reopen.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4914667
+ * @summary Closing and reopening MIDI IN device on Linux throws
+ *          MidiUnavailableException
+ */
+public class Reopen {
+
+    private static boolean isTestExecuted;
+    private static boolean isTestPassed;
+
+    /*
+     * run manually:
+     * java Reopen 100 in      for 100 iterations on the MIDI IN device
+     * java Reopen 16 out      for 16 iterations on the MIDI OUT device
+     */
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            doAllTests();
+        } else if (args.length == 2) {
+            int numIterations = Integer.parseInt(args[0]);
+            if (args[1].equals("in")) {
+                doTest(numIterations, true);
+            } else {
+                doTest(numIterations, false);
+            }
+        } else {
+            out("usage: java Reopen <iterations> in|out");
+        }
+    }
+
+    private static void doAllTests() throws Exception {
+        out("#4914667: Closing and reopening MIDI IN device on Linux throws MidiUnavailableException");
+        boolean success = true;
+        try {
+            success &= doTest(20, true); // MIDI IN
+            success &= doTest(20, false); // MIDI OUT
+            isTestExecuted = true;
+        } catch (Exception e) {
+            out(e);
+            isTestExecuted = false;
+        }
+        isTestPassed = success;
+        if (isTestExecuted) {
+            if (isTestPassed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        } else {
+            out("Test NOT FAILED");
+        }
+    }
+
+    private static boolean doTest(int numIterations, boolean input) throws Exception {
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        MidiDevice outDevice = null;
+        MidiDevice inDevice = null;
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(infos[i]);
+            if (! (device instanceof Sequencer) &&
+                ! (device instanceof Synthesizer)) {
+                if (device.getMaxReceivers() != 0) {
+                    outDevice = device;
+                }
+                if (device.getMaxTransmitters() != 0) {
+                    inDevice = device;
+                }
+            }
+        }
+        MidiDevice testDevice = null;
+        if (input) {
+            testDevice = inDevice;
+        } else {
+            testDevice = outDevice;
+        }
+        if (testDevice == null) {
+            out("Cannot test: device not available.");
+            return true;
+        }
+        out("Using Device: " + testDevice);
+
+        for (int i = 0; i < numIterations; i++) {
+            out("@@@ ITERATION: " + i);
+            testDevice.open();
+            // This sleep ensures that the thread of MidiInDevice is started.
+            sleep(50);
+            testDevice.close();
+        }
+        return true;
+    }
+
+    private static void sleep(int milliseconds) {
+        try {
+            Thread.sleep(milliseconds);
+        } catch (InterruptedException e) {
+        }
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/SMFCp037.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,60 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4303933
+ * @summary MidiSystem fails to load MIDI file on systems with EBCDIC simulation
+ */
+public class SMFCp037 {
+
+    public static void main(String args[]) throws Exception {
+        // Test to read MIDI files with Cp037 character set - close enough
+        // for EBCDIC simulation
+        System.setProperty("file.encoding", "Cp037");
+        // try to read this file with Cp037 encoding
+        MidiSystem.getSequence(new ByteArrayInputStream(SHORT_SMF));
+        System.out.println("  test passed.");
+    }
+
+public static byte[] SHORT_SMF = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0,
+        0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32,
+        116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44,
+        0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114,
+        97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14,
+        71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5,
+        66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60,
+        94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5,
+        2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43,
+        -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3,
+        0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3,
+        5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5,
+        0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0,
+        64, 117, -112, 63, 0, 0, -1, 47, 0
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/SMFParserBreak.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,109 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+
+/**
+ * @test
+ * @bug 4910986
+ * @summary MIDI file parser breaks up on http connection
+ */
+public class SMFParserBreak {
+
+    public static void main(String[] args) throws Exception {
+
+        InputStream is = new ByteArrayInputStream(midifile);
+        // create a buffered input stream that seems
+        // to be on an unfortunate boundary for the
+        // 1.4.2 SMF parser implementation
+        is = new ChunkInputStream(is, 32);
+        Sequence sequence = MidiSystem.getSequence(is);
+
+        long duration = sequence.getMicrosecondLength() / 10000;
+        System.out.println("Duration: "+duration+" deciseconds ");
+
+        // the test is passed if no exception thrown
+        System.out.println("Test passed");
+    }
+
+    // A MIDI file
+    static byte[] midifile = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0,
+        0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31,
+        100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52,
+        100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34,
+        100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55,
+        100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37,
+        100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58,
+        100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40,
+        100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61,
+        100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114,
+        107, 0, 0, 0, 4, 0, -1, 47, 0
+    };
+}
+
+/* an input stream that always returns data in chunks */
+class ChunkInputStream extends FilterInputStream {
+    int chunkSize;
+    int p = 0; // position
+
+    public ChunkInputStream(InputStream is, int chunkSize) {
+        super(is);
+        this.chunkSize = chunkSize;
+    }
+
+    // override to increase counter
+    public int read() throws IOException {
+        int ret = super.read();
+        if (ret >= 0) {
+            p++;
+        }
+        return ret;
+    }
+
+    // override to make sure that read(byte[], int, int) is used
+    public int read(byte[] b) throws IOException {
+        return read(b, 0, b.length);
+    }
+
+    // override to split the data in chunks
+    public int read(byte[] b, int off, int len) throws IOException {
+        // if we would pass a chunk boundary,
+        // only return up to the chunk boundary
+        if ( (p / chunkSize) < ( (p+len) / chunkSize)) {
+            // p+len is in the next chunk
+            len -= ((p+len) % chunkSize);
+        }
+        int ret = super.read(b, off, len);
+        if (ret >= 0) {
+            p += ret;
+        }
+        return ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/File/WriteRealTimeMessageNPE.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary NPE when writing a sequence with a realtime MIDI message
+ */
+public class WriteRealTimeMessageNPE {
+
+    public static void main(String args[]) throws Exception {
+        System.out.println("5048381: NullPointerException when saving a MIDI sequence");
+        boolean npeThrown = false;
+        boolean noEx = false;
+
+        Sequence seq = new Sequence(Sequence.PPQ, 384, 1);
+        Track t = seq.getTracks()[0];
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(0xF8, 0, 0);
+        t.add(new MidiEvent(msg, 0));
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try {
+            MidiSystem.write(seq, 0, out);
+            noEx = true;
+        } catch (NullPointerException npe) {
+            npeThrown = true;
+            System.out.println("## Failed: Threw unexpected NPE: "+npe);
+            throw new Exception("Test FAILED!");
+        } catch (Exception e) {
+            System.out.println("Threw unexpected Exception: "+e);
+            System.out.println("But at least did not throw NPE...");
+        }
+        if (noEx) {
+            InputStream is = new ByteArrayInputStream(out.toByteArray());
+            seq = MidiSystem.getSequence(is);
+            System.out.println("Sequence has "+seq.getTracks().length+" tracks.");
+            if (seq.getTracks().length > 0) {
+                System.out.println("Track 0 has "+seq.getTracks()[0].size()+" events.");
+            }
+        }
+        System.out.println("Test passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MetaMessage/MetaMessageClone.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MetaMessage;
+
+/**
+ * @test
+ * @bug 4511796
+ * @summary Check that MetaMessage.clone() works correctly
+ */
+public class MetaMessageClone {
+
+    private static void printMsg(MetaMessage msg, byte[] data) {
+        System.out.println(""+msg.getLength()+" total bytes, type="+msg.getType()+", dataLength="+data.length);
+    }
+
+    private static void checkClone(MetaMessage msg) throws Exception {
+        System.out.print("Original: ");
+        byte[] msgData=msg.getData();
+        printMsg(msg, msgData);
+        MetaMessage msg2=(MetaMessage) msg.clone();
+        byte[] msg2Data=msg2.getData();
+        System.out.print("Clone:    ");
+        printMsg(msg2, msg2Data);
+
+        if (msg2.getLength()!=msg.getLength()
+            || msg.getType()!=msg2.getType()
+            || msgData.length!=msg2Data.length) {
+                throw new Exception("cloned MetaMessage is not equal.");
+        }
+        int max=Math.min(msgData.length, 10);
+        for (int i=0; i<max; i++) {
+            if (msgData[i]!=msg2Data[i]) {
+                throw new Exception("Cloned MetaMessage data is not equal.");
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // let's create some MetaMessages and check them
+        MetaMessage msg=new MetaMessage();
+        String text="a textmarker";
+        msg.setMessage(1, text.getBytes(), text.length());
+        checkClone(msg);
+        msg.setMessage(0x2E, new byte[0], 0);
+        checkClone(msg);
+        byte[] data=new byte[17000];
+        for (int i=0; i<30; data[i]=(byte) (i++ & 0xFF));
+        msg.setMessage(0x02, data, 80); checkClone(msg);
+        msg.setMessage(0x02, data, 160); checkClone(msg);
+        msg.setMessage(0x02, data, 400); checkClone(msg);
+        msg.setMessage(0x02, data, 1000); checkClone(msg);
+        msg.setMessage(0x02, data, 10000); checkClone(msg);
+        msg.setMessage(0x02, data, 17000); checkClone(msg);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/6411624/Test6411624.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @test
+ * @bug 6411624
+ * @summary Tests that MidiSystem.getReceiver() & MidiSystem.getTransmitter
+ *          doesn't return sequencer
+ * @build bug6411624
+ * @run main/manual Test6411624
+ */
+public class Test6411624 {
+
+   private static void init() throws Exception {
+        //*** Create instructions for the user here ***
+
+        String[] instructions =
+        {
+         "This test should only be run on solaris or linux system",
+         "WITHOUT audio card installed (to test on SunRay set",
+         "incorrect $AUDIODEV value).",
+         "If you system does not meet this conditions, press PASS.",
+         "To run the test follow these instructions:",
+         "1. Open a terminal window.",
+         "2. Type \"cd " + System.getProperty("test.classes") + "\".",
+         "3. Type \"" + System.getProperty("java.home") + "/bin/java bug6411624\".",
+         "4. Follow the instructions shown in the terminal window.",
+         "If you see \"All tests sucessfully passed\", press PASS else press FAIL."
+       };
+
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+    }
+
+ /*****************************************************
+     Standard Test Machinery Section
+      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+   ******************************************************/
+   private static boolean theTestPassed = false;
+   private static boolean testGeneratedInterrupt = false;
+   private static String failureMessage = "";
+
+   private static Thread mainThread = null;
+
+   private static int sleepTime = 300000;
+
+   public static void main( String args[] ) throws Exception
+    {
+      mainThread = Thread.currentThread();
+      try
+       {
+         init();
+       }
+      catch( TestPassedException e )
+       {
+         //The test passed, so just return from main and harness will
+         // interepret this return as a pass
+         return;
+       }
+      //At this point, neither test passed nor test failed has been
+      // called -- either would have thrown an exception and ended the
+      // test, so we know we have multiple threads.
+
+      //Test involves other threads, so sleep and wait for them to
+      // called pass() or fail()
+      try
+       {
+         Thread.sleep( sleepTime );
+         //Timed out, so fail the test
+         throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
+       }
+      catch (InterruptedException e)
+       {
+         if( ! testGeneratedInterrupt ) throw e;
+
+         //reset flag in case hit this code more than once for some reason (just safety)
+         testGeneratedInterrupt = false;
+         if ( theTestPassed == false )
+          {
+            throw new RuntimeException( failureMessage );
+          }
+       }
+
+    }//main
+
+   public static synchronized void setTimeoutTo( int seconds )
+    {
+      sleepTime = seconds * 1000;
+    }
+
+   public static synchronized void pass()
+    {
+      Sysout.println( "The test passed." );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //first check if this is executing in main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //Still in the main thread, so set the flag just for kicks,
+         // and throw a test passed exception which will be caught
+         // and end the test.
+         theTestPassed = true;
+         throw new TestPassedException();
+       }
+      //pass was called from a different thread, so set the flag and interrupt
+      // the main thead.
+      theTestPassed = true;
+      testGeneratedInterrupt = true;
+      mainThread.interrupt();
+    }//pass()
+
+   public static synchronized void fail()
+    {
+      //test writer didn't specify why test failed, so give generic
+      fail( "it just plain failed! :-)" );
+    }
+
+   public static synchronized void fail( String whyFailed )
+    {
+      Sysout.println( "The test failed: " + whyFailed );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //check if this called from main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //If main thread, fail now 'cause not sleeping
+         throw new RuntimeException( whyFailed );
+       }
+      theTestPassed = false;
+      testGeneratedInterrupt = true;
+      failureMessage = whyFailed;
+      mainThread.interrupt();
+    }//fail()
+
+ }// class Orient
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+
+//************ Begin classes defined for the test ****************
+
+// make listeners in a class defined here, and instantiate them in init()
+
+/* Example of a class which may be written as part of a test
+class NewClass implements anInterface
+ {
+   static int newVar = 0;
+
+   public void eventDispatched(AWTEvent e)
+    {
+      //Counting events to see if we get enough
+      eventCount++;
+
+      if( eventCount == 20 )
+       {
+         //got enough events, so pass
+
+         Orient.pass();
+       }
+      else if( tries == 20 )
+       {
+         //tried too many times without getting enough events so fail
+
+         Orient.fail();
+       }
+
+    }// eventDispatched()
+
+ }// NewClass class
+
+*/
+
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+   Panel  buttonP = new Panel();
+   Button passB = new Button( "pass" );
+   Button failB = new Button( "fail" );
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      passB = new Button( "pass" );
+      passB.setActionCommand( "pass" );
+      passB.addActionListener( this );
+      buttonP.add( "East", passB );
+
+      failB = new Button( "fail" );
+      failB.setActionCommand( "fail" );
+      failB.addActionListener( this );
+      buttonP.add( "West", failB );
+
+      add( "South", buttonP );
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+   //catch presses of the passed and failed buttons.
+   //simply call the standard pass() or fail() static methods of
+   //DialogOrient
+   public void actionPerformed( ActionEvent e )
+    {
+      if( e.getActionCommand() == "pass" )
+       {
+         Test6411624.pass();
+       }
+      else
+       {
+         Test6411624.fail();
+       }
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/6411624/bug6411624.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * This test should be run on specific environment (solaris or linux w/o
+ * audio card installed).
+ */
+public class bug6411624 {
+
+    public static void main(String args[]) throws Exception {
+        log("This test should only be run on solaris or linux system");
+        log("without audio card installed (to test on SunRay set");
+        log("incorrect $AUDIODEV value).");
+        readln();
+
+        boolean testRecv = false;
+        boolean testTrans = false;
+        boolean testSeq = true;
+
+        // print add info (midi device list)
+        try {
+            MidiDevice.Info[] midis = MidiSystem.getMidiDeviceInfo();
+            log("MidiDevices (total " + midis.length + "):");
+            for (int i=0; i<midis.length; i++) {
+                log("" + i + ": " + midis[i].toString());
+//                MidiDevice dev = MidiSystem.getMidiDevice(midis[i]);
+//                log("    device: " + dev);
+            }
+        } catch (Exception ex) {
+            log("!!!EXCEPTION:");
+            ex.printStackTrace();
+        }
+
+        log("");
+        log("getting default receiver...");
+        try {
+            Receiver rec = MidiSystem.getReceiver();
+            log(" - OK: " + rec);
+            testRecv = checkDevice(rec);
+            rec.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK");
+            testRecv = true;
+        }
+
+
+        log("");
+        log("getting default transmitter...");
+        try {
+            Transmitter trans = MidiSystem.getTransmitter();
+            log(" - OK: " + trans);
+            testTrans = checkDevice(trans);
+            trans.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK");
+            testTrans = true;
+        }
+
+
+        // print default synthesizer
+        log("");
+        log("getting default synth...");
+        try {
+            Synthesizer synth = MidiSystem.getSynthesizer();
+            log(" - OK: " + synth);
+            synth.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK:");
+            e.printStackTrace();
+        }
+
+
+        log("");
+        log("getting default sequencer (connected)...");
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            log("OK: " + seq);
+
+            // check that returned sequencer doesn't connected to another sequencer
+            log("  receivers:");
+            log("    max=" + seq.getMaxReceivers());
+            List<Receiver> recvList = seq.getReceivers();
+            log("    count=" + recvList.size());
+            Iterator<Receiver> recvIter = recvList.iterator();
+            int i = 0;
+            while (recvIter.hasNext()) {
+                Receiver recv = recvIter.next();
+                log("    " + (++i) + ": " + recv);
+            }
+
+            log("  transmitters:");
+            log("    max=" + seq.getMaxTransmitters());
+            List<Transmitter> transList = seq.getTransmitters();
+            log("    count=" + transList.size());
+            Iterator<Transmitter> transIter = transList.iterator();
+            i = 0;
+            while (transIter.hasNext()) {
+                Transmitter trans = transIter.next();
+                log("    " + (++i) + ": " + trans);
+                Receiver recv = trans.getReceiver();
+                log("      recv: " + recv);
+                if (!checkDevice(recv))
+                    testSeq = false;
+            }
+
+            log("opening sequencer...");
+            seq.open();
+            log("OK.");
+
+            log("closing...");
+            seq.close();
+            log("OK.");
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown - OK:");
+            e.printStackTrace();
+        }
+
+
+        // debug testing - non-connected sequencer
+        log("");
+        log("getting default sequencer (non-connected)...");
+        try {
+            Sequencer seq = MidiSystem.getSequencer(false);
+            log("OK: " + seq);
+
+            log("  receivers:");
+            log("    max=" + seq.getMaxReceivers());
+            List<Receiver> recvList = seq.getReceivers();
+            log("    count=" + recvList.size());
+            Iterator<Receiver> recvIter = recvList.iterator();
+            int i = 0;
+            while (recvIter.hasNext()) {
+                Receiver recv = recvIter.next();
+                log("    " + (++i) + ": " + recv);
+            }
+
+            log("  transmitters:");
+            log("    max=" + seq.getMaxTransmitters());
+            List<Transmitter> transList = seq.getTransmitters();
+            log("    count=" + transList.size());
+            Iterator<Transmitter> transIter = transList.iterator();
+            i = 0;
+            while (transIter.hasNext()) {
+                Transmitter trans = transIter.next();
+                log("    " + (++i) + ": " + trans);
+                Receiver recv = trans.getReceiver();
+                log("      recv: " + recv);
+            }
+            seq.close();
+        } catch (MidiUnavailableException e) {
+            log("MidiUnavailableException has been thrown (shouln't?):");
+            e.printStackTrace();
+        }
+
+        log("");
+        log("Test result:");
+        // print results
+        if (testRecv && testTrans && testSeq) {
+            log("  All tests sucessfully passed.");
+        } else {
+            log("  Some tests failed:");
+            log("    receiver test:    " + (testRecv ? "OK" : "FAILED"));
+            log("    transmitter test: " + (testTrans ? "OK" : "FAILED"));
+            log("    sequencer test:   " + (testSeq ? "OK" : "FAILED"));
+        }
+        log("\n\n\n");
+    }
+
+    // check that device is not sequencer
+    static boolean checkDevice(Object dev) {
+        String className = dev.getClass().toString().toLowerCase();
+        boolean result = (className.indexOf("sequencer") < 0);
+        if (!result)
+            log("ERROR: inapropriate device");
+        return result;
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+    static void readln() {
+        log("");
+        log("Press ENTER to continue...");
+        try {
+            while (System.in.read() != 10) ;
+        } catch (IOException e) { }
+        log("");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/DefaultDevices.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,226 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+import javax.sound.midi.spi.MidiDeviceProvider;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @bug 4934509
+ * @bug 4938236
+ * @modules java.desktop/com.sun.media.sound
+ * @run main/timeout=600 DefaultDevices
+ * @summary RFE: Setting the default MixerProvider
+ */
+/** Test the retrieving of MidiDevices with default device properties.
+ * This is a part of the test for 4776511.
+ * The test also functions as a unit test for 4934509: SPEC: Document
+ * explicitely MidiSystem.getReceiver's behavior
+ * and a regession test for 4938236: Crash when opening synthesizer implicitly
+ * The test has been updated to reflect a fix for 6411624: MidiSystem.getSequencer()
+ * doesn't throw MidiUnavaivableException if no audio card installed (see also
+ * 6422786: regression test javax/sound/midi/MidiSystem/DefaultDevices.java fails)
+ */
+public class DefaultDevices {
+
+    private static final String ERROR_PROVIDER_CLASS_NAME = "abc";
+    private static final String ERROR_INSTANCE_NAME = "def";
+
+    private static final Class RECEIVER_CLASS = javax.sound.midi.Receiver.class;
+    private static final Class TRANSMITTER_CLASS = javax.sound.midi.Transmitter.class;
+    private static final Class SEQUENCER_CLASS = javax.sound.midi.Sequencer.class;
+    private static final Class SYNTHESIZER_CLASS = javax.sound.midi.Synthesizer.class;
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        MidiDevice.Info[] infos;
+
+        out("\nTesting MidiDevices retrieved via MidiSystem");
+        infos = MidiSystem.getMidiDeviceInfo();
+        allOk &= testDevices(infos, null);
+
+        out("\nTesting MidiDevices retrieved from MidiDeviceProviders");
+        List providers = JDK13Services.getProviders(MidiDeviceProvider.class);
+        for (int i = 0; i < providers.size(); i++) {
+            MidiDeviceProvider provider = (MidiDeviceProvider)providers.get(i);
+            infos = provider.getDeviceInfo();
+            allOk &= testDevices(infos, provider.getClass().getName());
+        }
+
+        if (!allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static boolean testDevices(MidiDevice.Info[] infos,
+            String providerClassName) {
+        boolean allOk = true;
+
+        for (int i = 0; i < infos.length; i++) {
+            MidiDevice device = null;
+            try {
+                device = MidiSystem.getMidiDevice(infos[i]);
+            } catch (MidiUnavailableException e) {
+                out("Exception thrown; Test NOT failed.");
+                e.printStackTrace(System.out);
+                out("");
+            }
+            out("\nTesting device: " + device);
+            if (device instanceof Sequencer) {
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Synthesizer) {
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, true, true);
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, true);
+                // incorrect cases
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Receiver) {
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+            if (device instanceof Transmitter) {
+                allOk &= testDevice(device, TRANSMITTER_CLASS, providerClassName, true, true);
+                // incorrect cases
+                allOk &= testDevice(device, RECEIVER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SYNTHESIZER_CLASS, providerClassName, false, false);
+                allOk &= testDevice(device, SEQUENCER_CLASS, providerClassName, false, false);
+            }
+        }
+        return allOk;
+    }
+
+    private static boolean testDevice(MidiDevice device, Class type,
+            String providerClassName, boolean testWrong, boolean expectedResult) {
+        boolean allOk = true;
+        String instanceName = device.getDeviceInfo().getName();
+
+        // no error
+        allOk &= testDevice(device, type, providerClassName,
+                            instanceName, expectedResult);
+
+        if (testWrong) {
+            // erroneous provider class name, correct instance name
+            allOk &= testDevice(device, type, ERROR_PROVIDER_CLASS_NAME,
+                                instanceName, expectedResult);
+
+            // correct provider class name, erroneous instance name
+            // we presume that provider provides only one class of requested type
+            allOk &= testDevice(device, type, providerClassName,
+                                ERROR_INSTANCE_NAME, expectedResult);
+        }
+
+        return allOk;
+    }
+
+    private static boolean testDevice(MidiDevice device, Class type,
+            String providerClassName, String instanceName,
+            boolean expectedResult) {
+        boolean allOk = true;
+
+        try {
+            String propertyName = type.getName();
+            String propertyValue = (providerClassName != null) ? providerClassName: "" ;
+            propertyValue += "#" + instanceName;
+            out("property: " + propertyName + "="+ propertyValue);
+            System.setProperty(propertyName, propertyValue);
+            Object reference = null;
+            Object result = null;
+            if (type == SEQUENCER_CLASS) {
+                reference = device;
+                result = MidiSystem.getSequencer();
+            } else if (type == SYNTHESIZER_CLASS) {
+                reference = device;
+                result = MidiSystem.getSynthesizer();
+            } else if (type == RECEIVER_CLASS) {
+                reference = device.getReceiver();
+                result = MidiSystem.getReceiver();
+            } else if (type == TRANSMITTER_CLASS) {
+                reference = device.getTransmitter();
+                result = MidiSystem.getTransmitter();
+            }
+            out("result: " + result);
+            boolean rightDevice = (reference.getClass() == result.getClass());
+            if (rightDevice != expectedResult) {
+                out("\nERROR: type " + type + " failed:"
+                        + " class should" + (expectedResult ? "" : " NOT") + " be '"
+                        + reference.getClass()
+                        + "' but is '" + result.getClass() + "'!\n");
+                allOk = false;
+            }
+            if (expectedResult
+                    && reference instanceof MidiDevice
+                    && result instanceof MidiDevice) {
+                MidiDevice referenceDevice = (MidiDevice)reference;
+                MidiDevice resultDevice = (MidiDevice)result;
+                if (!referenceDevice.getDeviceInfo().getName().equals(
+                                    resultDevice.getDeviceInfo().getName())) {
+                    out("\nERROR: type " + type + " failed: name should be '"
+                            + referenceDevice.getDeviceInfo().getName()
+                            + "' but is '"
+                            + resultDevice.getDeviceInfo().getName() + "'!\n");
+                    allOk = false;
+                }
+            }
+            if (result instanceof Receiver) {
+                ((Receiver)result).close();
+            } else if (result instanceof Transmitter) {
+                ((Transmitter)result).close();
+            } else if (result instanceof Synthesizer) {
+                ((Synthesizer)result).close();
+            } else if (result instanceof Sequencer) {
+                ((Sequencer)result).close();
+            }
+        } catch (Exception e) {
+            out("Exception thrown; Test NOT failed.");
+            e.printStackTrace(System.out);
+            out("");
+        }
+        return allOk;
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/DefaultProperties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,164 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the retrieving and
+ *          parsing of properties. This is a part of the test for 4776511.
+ * @run main/othervm DefaultProperties
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class DefaultProperties {
+
+    private static final Class[] lineTypeClasses = {
+        javax.sound.midi.Receiver.class,
+        javax.sound.midi.Transmitter.class,
+        javax.sound.midi.Sequencer.class,
+        javax.sound.midi.Synthesizer.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        File file = new File(System.getProperty("test.src", "."), "testdata");
+        System.setProperty("java.home", file.getCanonicalPath());
+
+        for (int i = 0; i < lineTypeClasses.length; i++) {
+            Class cls = lineTypeClasses[i];
+            String propertyName = cls.getName();
+            String result;
+            String provClassName;
+            String instanceName;
+
+            // properties file, both provider class name and instance name
+            provClassName = "xyz";
+            instanceName = "123";
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, no trailing hash
+            provClassName = "abc";
+            System.setProperty(propertyName, provClassName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, trailing hash
+            provClassName = "def";
+            System.setProperty(propertyName, provClassName + "#");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, instance name only
+            instanceName = "ghi";
+            System.setProperty(propertyName, "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, both provider class and instance name
+            provClassName = "jkl";
+            instanceName = "mno";
+            System.setProperty(propertyName, provClassName + "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + "failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + "failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, empty
+            System.setProperty(propertyName, "");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + "failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+        }
+        if (! allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/GetSequencer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,128 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 4931400
+ * @summary Clarify default connections in default sequencer
+ */
+public class GetSequencer {
+
+    static boolean failed = false;
+
+    public static void main(String args[]) throws Exception {
+        doTest(1);
+        doTest(2);
+        doTest(3);
+
+        if (failed) throw new Exception("Test FAILED!");
+        out("test OK");
+    }
+
+    public static void doTest(int mode) {
+        Sequencer seq = null;
+        boolean connected = false;
+
+        try {
+            switch (mode) {
+            case 1:
+                seq = MidiSystem.getSequencer();
+                connected = true;
+                break;
+            case 2:
+                seq = MidiSystem.getSequencer(false);
+                connected = false;
+                break;
+            case 3:
+                seq = MidiSystem.getSequencer(true);
+                connected = true;
+                break;
+            }
+            out("Testing Sequencer "+seq);
+            if (connected) {
+                out("  opened in connected mode.");
+            } else {
+                out("  opened in non-connected mode.");
+            }
+            System.out.println("  opening...");
+            seq.open();
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was thrown: " + mue);
+            System.err.println("  could not test this sequencer.");
+            return;
+        }
+
+        try {
+            List<Transmitter> transmitters = seq.getTransmitters();
+            int size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 1 && connected) {
+                out("  should have 1 connection! Failed.");
+                failed = true;
+            }
+            if (size != 0 && !connected) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+            out("  closing...");
+            seq.close();
+            transmitters = seq.getTransmitters();
+            size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 0) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+
+            out("  opening again...");
+            seq.open();
+            transmitters = seq.getTransmitters();
+            size = transmitters.size();
+            out("  transmitters.size()="+size);
+            if (size != 1 && connected) {
+                out("  should have 1 connection! Failed.");
+                failed = true;
+            }
+            if (size != 0 && !connected) {
+                out("  should have 0 connections! Failed.");
+                failed = true;
+            }
+        } catch (Exception e) {
+            System.err.println("  unexpectedException was thrown: " + e);
+            System.err.println("  causes this test to FAIL.");
+            failed = true;
+        }
+        seq.close();
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/MidiFileTypeUniqueness.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,51 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4883060
+ * @summary  AudioSystem.getAudioFileTypes returns duplicates
+ */
+public class MidiFileTypeUniqueness {
+
+    public static void main(String[] args) throws Exception {
+        boolean foundDuplicates = false;
+        int[]   aTypes = MidiSystem.getMidiFileTypes();
+        for (int i = 0; i < aTypes.length; i++)
+        {
+            for (int j = 0; j < aTypes.length; j++)
+            {
+                if (aTypes[i] == aTypes[j] && i != j) {
+                    foundDuplicates = true;
+                }
+            }
+        }
+        if (foundDuplicates) {
+            throw new Exception("Test failed");
+        } else {
+            System.out.println("Test passed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/ProviderCacheing.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,65 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the cacheing of
+ *          providers. This is a part of the test for 4776511.
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class ProviderCacheing {
+
+    private static final Class[] providerClasses = {
+        javax.sound.midi.spi.MidiDeviceProvider.class,
+        javax.sound.midi.spi.MidiFileReader.class,
+        javax.sound.midi.spi.MidiFileWriter.class,
+        javax.sound.midi.spi.SoundbankReader.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allCached = true;
+        for (int i = 0; i < providerClasses.length; i++) {
+            List list0 = JDK13Services.getProviders(providerClasses[i]);
+            List list1 = JDK13Services.getProviders(providerClasses[i]);
+            if (list0 == list1) {
+                out("Providers should not be cached for " + providerClasses[i]);
+                allCached = false;
+            }
+        }
+
+        if (! allCached) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/MidiSystem/testdata/conf/sound.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,27 @@
+#
+# 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+javax.sound.midi.Receiver=xyz#123
+javax.sound.midi.Transmitter=xyz#123
+javax.sound.midi.Sequencer=xyz#123
+javax.sound.midi.Synthesizer=xyz#123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/GetMicrosecondLength.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,151 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4929955
+ * @summary Sequence.getMicrosecondLength() returns wrong value
+ */
+public class GetMicrosecondLength {
+
+    public static boolean failed = false;
+    //private static Sequencer seq = null;
+
+    public static void main(String[] args) throws Exception {
+        /*
+          try {
+          seq = MidiSystem.getSequencer();
+          } catch (Exception e) {
+          e.printStackTrace();
+          }
+        */
+        for (int sec = 1; sec < 10; sec += 4) {
+            for (int tempo=0; tempo < 1000; tempo+=120) {
+                for (int resolution=1; resolution < 480; ) {
+                    testSequence(sec, tempo, resolution);
+                    if (resolution == 1) {
+                        resolution = 120;
+                    } else {
+                        resolution += 120;
+                    }
+                }
+            }
+        }
+        if (failed) throw new Exception("Test FAILED!");
+        out("Test Passed.");
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     */
+    private static void testSequence(int lengthInSeconds, int tempoInBPM, int resolution) {
+        Sequence sequence = null;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        boolean createTempoEvent = true;
+        if (tempoInBPM == 0) {
+            tempoInBPM = 120;
+            createTempoEvent = false;
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +"resolution="+resolution+" ticks/beat...");
+        } else {
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +tempoInBPM+" beats/min, "
+                             +"resolution="+resolution+" ticks/beat...");
+        }
+        //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM;
+        long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l;
+        //out("expected length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution);
+            Track track = sequence.createTrack();
+            if (createTempoEvent) {
+                int tempoInMPQ = (int) (60000000l / tempoInBPM);
+                MetaMessage tm = new MetaMessage();
+                byte[] msg = new byte[3];
+                msg[0] = (byte) (tempoInMPQ >> 16);
+                msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF);
+                msg[2] = (byte) (tempoInMPQ & 0xFF);
+
+                tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length);
+                track.add(new MidiEvent(tm, 0));
+                //out("regtest: tempoInMPQ="+tempoInMPQ);
+                //out("Added tempo event: new size="+track.size());
+            }
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+            //out("Added realtime event: new size="+track.size());
+        } catch (InvalidMidiDataException e) {
+            out(e);
+        }
+        boolean thisFailed = false;
+        long actualLengthInTicks = sequence.getTickLength();
+        // allow +/- 5%
+        if (Math.abs(actualLengthInTicks - lengthInTicks) > lengthInTicks / 20) {
+            out("FAILED:");
+            out("  expected length in ticks: " + lengthInTicks);
+            out("  actual length in ticks  : " + actualLengthInTicks);
+            thisFailed = true;
+        }
+        long actualLengthInUs = sequence.getMicrosecondLength();
+        // allow +/- 5%
+        if (Math.abs(actualLengthInUs - lengthInMicroseconds) > lengthInMicroseconds / 20) {
+            if (!thisFailed) {
+                out("FAILED:");
+            }
+            out("  expected length in microsecs: " + lengthInMicroseconds);
+            out("  actual length in microsecs  : " + actualLengthInUs);
+            thisFailed = true;
+        }
+        if (!thisFailed) {
+            out("OK");
+        }
+        /*if (seq != null) {
+          try {
+          seq.setSequence(sequence);
+          out("Sequencer tempo="+seq.getTempoInBPM());
+          } catch (Exception e) {
+          e.printStackTrace();
+          }
+          }
+        */
+        failed |= thisFailed;
+    }
+
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/MidiSMPTE.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,85 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+
+/**
+ * @test
+ * @bug 4291250
+ * @summary Midi files with SMPTE time do not play properly
+ */
+public class MidiSMPTE {
+
+    public static void main(String[] args) throws Exception {
+        Sequence s = null;
+        //File midiFile = new File("outsmpte.mid");
+        //InputStream is = new FileInputStream(midiFile);
+        //is = new BufferedInputStream(is);
+        InputStream is = new ByteArrayInputStream(smptemidifile);
+        s = MidiSystem.getSequence(is);
+        long duration = s.getMicrosecondLength() / 1000000;
+        System.out.println("Duration: "+duration+" seconds ");
+        if (duration > 14) {
+            throw new Exception("SMPTE time reader is broken! Test FAILED");
+        }
+        System.out.println("Test passed");
+    }
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=String.valueOf(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    // A MIDI file with SMPTE timing
+    static byte[] smptemidifile = {
+            77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 3, -30, 120, 77, 84, 114, 107, 0,
+            0, 0, 123, 0, -112, 30, 100, -113, 49, -128, 50, 100, -114, 69, -112, 31,
+            100, -114, 33, -128, 51, 100, -114, 55, -112, 32, 100, -114, 120, -128, 52,
+            100, -114, 40, -112, 33, 100, -114, 26, -128, 53, 100, -114, 26, -112, 34,
+            100, -114, 76, -128, 54, 100, -114, 12, -112, 35, 100, -114, 91, -128, 55,
+            100, -114, 69, -112, 36, 100, -114, 33, -128, 56, 100, -114, 55, -112, 37,
+            100, -114, 84, -128, 57, 100, -114, 40, -112, 38, 100, -114, 26, -128, 58,
+            100, -114, 26, -112, 39, 100, -113, 24, -128, 59, 100, -113, 60, -112, 40,
+            100, -113, 110, -128, 60, 100, -113, 96, -112, 41, 100, -113, 39, -128, 61,
+            100, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, 4, 0, -1, 47, 0, 77, 84, 114,
+            107, 0, 0, 0, 4, 0, -1, 47, 0
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequence/SMPTEDuration.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,94 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4702328
+ * @summary Wrong time in sequence for SMPTE based types
+ */
+public class SMPTEDuration {
+
+    public static void main(String args[]) throws Exception {
+         int[][] dataMes =  { {ShortMessage.NOTE_ON, 10, 0x24, 0x50} ,
+                 { ShortMessage.NOTE_OFF, 10, 0x24, 0x44 },
+                 { ShortMessage.NOTE_ON, 10, 0x24, 0x50 },
+                 { ShortMessage.NOTE_ON, 10, 0x26, 0x50 },
+                 { ShortMessage.NOTE_OFF, 10, 0x26, 0x53 } };
+         long[] ticks = { 0, 68, 240, 240, 286};
+         int res = 240;
+         ShortMessage msg;
+         Sequence midiData = null;
+         Track track;
+         boolean failed = false;
+
+
+         try {
+             midiData = new Sequence(Sequence.SMPTE_24 , res);
+         } catch (InvalidMidiDataException invMidiEx) {
+             invMidiEx.printStackTrace(System.out);
+             System.out.println("Unexpected InvalidMidiDataException: "
+                     + invMidiEx.getMessage());
+             failed = true;
+         }
+         track = midiData.createTrack();
+         for (int i = 0; i < dataMes.length; i++) {
+             msg = new ShortMessage();
+             try {
+                 msg.setMessage(dataMes[i][0], dataMes[i][1], dataMes[i][2],
+                         dataMes[i][3]);
+             } catch (InvalidMidiDataException invMidiEx) {
+                 invMidiEx.printStackTrace(System.out);
+                 System.out.println("Unexpected InvalidMidiDataException: "
+                         + invMidiEx.getMessage());
+                 failed = true;
+             }
+             track.add(new MidiEvent(msg, ticks[i]));
+         }
+         //   lengthInMs = (tickLength*1000000)/(divType*Res)
+         long micros = (long) ((midiData.getTickLength() * 1000000) / (res * Sequence.SMPTE_24));
+         if (midiData.getMicrosecondLength() != micros) {
+             failed = true;
+             System.out.println("getMicrosecondLength() returns wrong length: "
+                     + midiData.getMicrosecondLength());
+             System.out.println("getMicrosecondLength() must return length: "
+                     + micros);
+         }
+         if (midiData.getTickLength() != 286) {
+             failed = true;
+             System.out.println("getTickLength() returns wrong length: "
+                     + midiData.getTickLength());
+         }
+
+         if( failed == true ) {
+             throw new Exception("test failed");
+         } else {
+             System.out.println("Passed.");
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/LoopIAE.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5025549
+ * @summary Verify that setLoopEndPoint throws IAE
+ */
+public class LoopIAE {
+
+    static ShortMessage MidiMsg3(int a, int b, int c) {
+        try {
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage((byte)a,(byte)b,(byte)c);
+            return msg;
+        } catch(InvalidMidiDataException ex) {
+            throw new RuntimeException();
+        }
+    }
+
+    static boolean failed = false;
+
+    public static void main(String[] argv) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+        Sequencer sequencer = MidiSystem.getSequencer();
+        Sequence sequence = new Sequence(Sequence.PPQ, 240);
+        Track track = sequence.createTrack();
+
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),10*20));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),10*20 + 10));
+
+        try {
+            sequencer.open();
+            sequencer.setSequence(sequence);
+            sequencer.setTempoInBPM(100);
+
+            System.out.println("Setting loop end point to 1");
+            sequencer.setLoopEndPoint(1);
+            System.out.println("  -> effectively: "+sequencer.getLoopEndPoint());
+            System.out.println("Setting loop start point to 2 -- should throw IAE");
+            sequencer.setLoopStartPoint(2);
+            System.out.println("  -> effectively: "+sequencer.getLoopStartPoint());
+            System.out.println("No IllegalArgumentException was thrown!");
+            failed = true;
+        } catch (IllegalArgumentException iae) {
+            System.out.println("IAE was thrown correctly.");
+        } catch (MidiUnavailableException mue) {
+            System.out.println("MidiUnavailableException was thrown: " + mue);
+            System.out.println("Cannot execute test.");
+        } catch (InvalidMidiDataException imEx) {
+            System.out.println("InvalidMidiDataException was thrown.");
+            imEx.printStackTrace();
+            System.out.println("Cannot execute test.");
+        } finally {
+            if (sequencer != null && sequencer.isOpen()) {
+                sequencer.close();
+            }
+        }
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        System.out.println("test passed.");
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                if (seq.isOpen()) {
+                    seq.close();
+                }
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/Looping.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,315 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4204105
+ * @summary RFE: add loop() method(s) to Sequencer
+ * @key intermittent
+ */
+public class Looping {
+
+    public static void main(String[] args) throws Exception {
+        out("4204105: RFE: add loop() method(s) to Sequencer");
+        boolean passed = testAll();
+        if (passed) {
+            out("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED.");
+        }
+    }
+
+    /**
+     * Execute the test on all available Sequencers.
+     *
+     * @return true if the test passed for all Sequencers, false otherwise
+     */
+    private static boolean testAll() throws Exception {
+        boolean result = true;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+            if (device instanceof Sequencer) {
+                result &= testSequencer((Sequencer) device);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute the test on the passed Sequencer.
+     *
+     * @return true if the test is passed this Sequencer, false otherwise
+     */
+    private static boolean testSequencer(Sequencer seq) throws Exception{
+        boolean result = true;
+        out("testing: " + seq);
+
+        result &= testGetSet(seq);
+
+        seq.setSequence(createSequence());
+
+        result &= testGetSet(seq);
+
+        result &= testPlay(seq);
+
+        return result;
+    }
+
+    private static boolean testGetSet(Sequencer seq) {
+        boolean result = true;
+        Sequence sequence = seq.getSequence();
+        boolean isSequenceLoaded = (sequence != null);
+
+        out("TestGetSet");
+
+        try {
+            if (seq.getLoopStartPoint() != 0) {
+                out("start point", isSequenceLoaded,
+                    "isn't 0!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        if (seq.getLoopEndPoint() != -1) {
+            out("end point", isSequenceLoaded,
+                "isn't -1!");
+            result = false;
+        }
+
+        try {
+            seq.setLoopStartPoint(25);
+            if (seq.getLoopStartPoint() != 25) {
+                out("setLoopStartPoint()", isSequenceLoaded,
+                    "doesn't set the start point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        try {
+            seq.setLoopEndPoint(26);
+            if (seq.getLoopEndPoint() != 26) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        try {
+            seq.setLoopStartPoint(0);
+            if (seq.getLoopStartPoint() != 0) {
+                out("setLoopStartPoint()", isSequenceLoaded,
+                    "doesn't set the start point correctly!");
+                result = false;
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isSequenceLoaded) {
+                out("Caught permissable IllegalArgumentException:");
+            } else {
+                out("Threw unacceptable IllegalArgumentException! FAILED");
+                result = false;
+            }
+            out(iae.toString());
+        }
+
+        if (isSequenceLoaded) {
+            seq.setLoopEndPoint(sequence.getTickLength());
+            if (seq.getLoopEndPoint() != sequence.getTickLength()) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        } else {
+            // fails
+            seq.setLoopEndPoint(-1);
+            if (seq.getLoopEndPoint() != -1) {
+                out("setLoopEndPoint()", isSequenceLoaded,
+                    "doesn't set the end point correctly!");
+                result = false;
+            }
+        }
+
+        if (seq.getLoopCount() != 0) {
+            out("loop count", isSequenceLoaded,
+                "isn't 0!");
+            result = false;
+        }
+
+        seq.setLoopCount(1001);
+        if (seq.getLoopCount() != 1001) {
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        seq.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
+        if (seq.getLoopCount() != Sequencer.LOOP_CONTINUOUSLY) {
+            out("setLoopCount(Sequencer.LOOP_CONTINUOUSLY)", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        try {
+            seq.setLoopCount(-55);
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't throw IllegalArgumentException on illegal value!");
+            result = false;
+        } catch (IllegalArgumentException e) {
+            // EXCEPTION IS EXPECTED
+            out("Caught permissable IAE");
+        }
+
+        seq.setLoopCount(0);
+        if (seq.getLoopCount() != 0) {
+            out("setLoopCount()", isSequenceLoaded,
+                "doesn't set the loop count correctly!");
+            result = false;
+        }
+
+        return result;
+    }
+
+    private static boolean testPlay(Sequencer seq) {
+        boolean result = true;
+        long stopTime;
+
+        out("TestPlay");
+
+        TestMetaEventListener listener = new TestMetaEventListener();
+        seq.addMetaEventListener(listener);
+        long startTime = System.currentTimeMillis();
+        try {
+            seq.open();
+            out("Playing sequence, length="+(seq.getMicrosecondLength()/1000)+"millis");
+            seq.start();
+            while (true) {
+                stopTime = listener.getStopTime();
+                if (stopTime != 0) {
+                    break;
+                }
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                }
+            }
+            long measuredDuration = stopTime - startTime;
+            out("play duration (us): " + measuredDuration);
+        } catch (Exception e) {
+            out("test not executed; exception:");
+            e.printStackTrace();
+        }
+        seq.close();
+        return result;
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     *
+     * @return a dummy Sequence, or null, if a problem occured while creating
+     *         the Sequence
+     */
+    private static Sequence createSequence() {
+        Sequence sequence = null;
+        int lengthInSeconds = 2;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        int resolution = 480;
+        long lengthInTicks = (lengthInMicroseconds * 120 * resolution) / 60000000l;
+        out("length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution, 1);
+            Track track = sequence.createTrack();
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+        } catch (InvalidMidiDataException e) {
+            // DO NOTHING
+        }
+        out("sequence length (ticks): " + sequence.getTickLength());
+        out("sequence length (us): " + sequence.getMicrosecondLength());
+        return sequence;
+    }
+
+
+    private static void out(String m1, boolean isSequenceLoaded, String m2) {
+        out(m1 + (isSequenceLoaded ? " with Sequence " : " without Sequence ") + m2);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+
+    private static class TestMetaEventListener implements MetaEventListener {
+        private long stopTime;
+
+
+        public void meta(MetaMessage m) {
+            System.out.print("  Got MetaMessage: ");
+            if (m.getType() == 47) {
+                stopTime = System.currentTimeMillis();
+                System.out.println(" End Of Track -- OK");
+            } else {
+                System.out.println(" unknown. Ignored.");
+            }
+        }
+
+        public long getStopTime() {
+            return stopTime;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/MetaCallback.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,133 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.Instrument;
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4347135
+ * @summary MIDI MetaMessage callback inconsistent
+ * @run main/othervm MetaCallback
+ */
+public class MetaCallback implements MetaEventListener {
+
+    static ShortMessage MidiMsg3(int a, int b, int c) {
+        try {
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage((byte)a,(byte)b,(byte)c);
+            return msg;
+        } catch(InvalidMidiDataException ex) {
+            throw new RuntimeException();
+        }
+    }
+
+    //Synthesizer synth;
+    Instrument[] instruments;
+    Sequencer sequencer;
+    Sequence sequence;
+    Track track;
+
+    public static int TOTAL_COUNT = 100;
+
+    int metaCount = 0;
+    boolean finished = false;
+
+    MetaCallback() throws Exception {
+
+        sequencer=MidiSystem.getSequencer();
+        sequence=new Sequence(Sequence.PPQ,240);
+        track=sequence.createTrack();
+        sequencer.addMetaEventListener(this);
+
+        byte[] data = new byte[1];
+
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,100),0));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+0,45,0),0 + 240));
+        int c;
+        for(c=0; c < TOTAL_COUNT; c++) {
+            data[0]=(byte)(c+1);
+            MetaMessage meta = new MetaMessage();
+            meta.setMessage(1, data, 1); // type, data, length
+            track.add(new MidiEvent(meta,c*20));
+        }
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,100),c*20));
+        track.add(new MidiEvent(MidiMsg3(ShortMessage.NOTE_ON+9,45,0),c*20 + 10));
+
+        sequencer.setSlaveSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK);
+        sequencer.setMasterSyncMode(Sequencer.SyncMode.INTERNAL_CLOCK);
+        sequencer.open();
+        sequencer.setSequence(sequence);
+        sequencer.setTempoInBPM(100);
+        System.out.println("Starting playback...");
+        this.start();
+        while (!finished && sequencer.getTickPosition() < sequencer.getTickLength()) {
+            System.out.println("Tick "+sequencer.getTickPosition()+"...");
+            Thread.sleep(1000);
+        }
+        System.out.println("Stopping playback...");
+        this.stop();
+        if (metaCount != TOTAL_COUNT) {
+            throw new Exception("Expected "+TOTAL_COUNT+" callbacks, but got "+metaCount+"!");
+        }
+    }
+    void start() {sequencer.start();}
+    void stop() {sequencer.stop();}
+
+    public void meta(MetaMessage msg) {
+        System.out.println(""+metaCount+": got "+msg);
+        if (msg.getType() == 0x2F) {
+            finished = true;
+        } else if (msg.getData().length > 0 && msg.getType() == 1) {
+            metaCount++;
+        }
+    }
+
+    public static void main(String[] argv) throws Exception {
+        if (hasSequencer()) {
+            new MetaCallback();
+            System.out.println("Test passed");
+        }
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/Recording.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,213 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4932841
+ * @key intermittent
+ * @summary Sequencer's recording feature does not work
+ */
+public class Recording {
+
+    public static boolean failed = false;
+    public static boolean passed = false;
+    private static Sequencer seq = null;
+
+    public static void main(String[] args) throws Exception {
+        try {
+            seq = MidiSystem.getSequencer();
+
+            // create an arbitrary sequence which lasts 10 seconds
+            Sequence sequence = createSequence(10, 120, 240);
+
+            seq.setSequence(sequence);
+            out("Set Sequence to Sequencer. Tempo="+seq.getTempoInBPM());
+
+            Track track = sequence.createTrack();
+            int oldSize = track.size();
+            seq.recordEnable(track, -1);
+
+            seq.open();
+
+            // if getReceiver throws Exception, failed!
+            failed = true;
+            Receiver rec = seq.getReceiver();
+
+            // start recording and add various events
+            seq.startRecording();
+
+            // is exception from here on, not failed
+            failed = false;
+
+            if (!seq.isRecording()) {
+                failed = true;
+                throw new Exception("Sequencer did not start recording!");
+            }
+            if (!seq.isRunning()) {
+                failed = true;
+                throw new Exception("Sequencer started recording, but is not running!");
+            }
+
+            // first: add an event to the middle of the sequence
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0xC0, 80, 00);
+            rec.send(msg, 5l * 1000l * 1000l);
+
+            Thread.sleep(1000);
+
+            // then add a real-time event
+            msg = new ShortMessage();
+            msg.setMessage(0xC0, 81, 00);
+            long secondEventTick = seq.getTickPosition();
+            rec.send(msg, -1);
+
+            seq.stopRecording();
+            if (seq.isRecording()) {
+                failed = true;
+                throw new Exception("Stopped recording, but Sequencer is still recording!");
+            }
+            if (!seq.isRunning()) {
+                failed = true;
+                throw new Exception("Stopped recording, but Sequencer but is not running anymore!");
+            }
+
+            seq.stop();
+            if (seq.isRunning()) {
+                failed = true;
+                throw new Exception("Stopped Sequencer, but it is still running!");
+            }
+
+            // now examine the contents of the recorded track:
+            // 1) number of events: should be 2 more
+            int newSize = track.size();
+            int addedEventCount = newSize - oldSize;
+
+            out("Added "+addedEventCount+" events to recording track.");
+            if (addedEventCount != 2) {
+                failed = true;
+                throw new Exception("Did not add 2 events!");
+            }
+
+            // 2) the first event should be at roughly "secondEventTick"
+            MidiEvent ev = track.get(0);
+            msg = (ShortMessage) ev.getMessage();
+            out("The first recorded event is at tick position: "+ev.getTick());
+            if (Math.abs(ev.getTick() - secondEventTick) > 1000) {
+                out(" -> but expected something like: "+secondEventTick+"! FAILED.");
+                failed = true;
+            }
+
+            ev = track.get(1);
+            msg = (ShortMessage) ev.getMessage();
+            out("The 2nd recorded event is at tick position: "+ev.getTick());
+            out(" -> sequence's tick length is "+seq.getTickLength());
+            if (Math.abs(ev.getTick() - (sequence.getTickLength() / 2)) > 1000) {
+                out(" -> but expected something like: "+(seq.getTickLength()/2)+"! FAILED.");
+                failed = true;
+            }
+
+            passed = true;
+        } catch (Exception e) {
+            out(e.toString());
+            if (!failed) out("Test not failed.");
+        }
+        if (seq != null) {
+            seq.close();
+        }
+
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        else if (passed) {
+            out("Test Passed.");
+        }
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     */
+    private static Sequence createSequence(int lengthInSeconds, int tempoInBPM,
+                                           int resolution) {
+        Sequence sequence = null;
+        long lengthInMicroseconds = lengthInSeconds * 1000000;
+        boolean createTempoEvent = true;
+        if (tempoInBPM == 0) {
+            tempoInBPM = 120;
+            createTempoEvent = false;
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +"resolution="+resolution+" ticks/beat...");
+        } else {
+            System.out.print("Creating sequence: "+lengthInSeconds+"sec, "
+                             +tempoInBPM+" beats/min, "
+                             +"resolution="+resolution+" ticks/beat...");
+        }
+        //long lengthInTicks = (lengthInMicroseconds * resolution) / tempoInBPM;
+        long lengthInTicks = (lengthInMicroseconds * tempoInBPM * resolution) / 60000000l;
+        //out("expected length in ticks: " + lengthInTicks);
+        try {
+            sequence = new Sequence(Sequence.PPQ, resolution);
+            Track track = sequence.createTrack();
+            if (createTempoEvent) {
+                int tempoInMPQ = (int) (60000000l / tempoInBPM);
+                MetaMessage tm = new MetaMessage();
+                byte[] msg = new byte[3];
+                msg[0] = (byte) (tempoInMPQ >> 16);
+                msg[1] = (byte) ((tempoInMPQ >> 8) & 0xFF);
+                msg[2] = (byte) (tempoInMPQ & 0xFF);
+
+                tm.setMessage(0x51 /* Meta Tempo */, msg, msg.length);
+                track.add(new MidiEvent(tm, 0));
+                //out("regtest: tempoInMPQ="+tempoInMPQ);
+                //out("Added tempo event: new size="+track.size());
+            }
+            ShortMessage mm = new ShortMessage();
+            mm.setMessage(0xF6, 0, 0);
+            MidiEvent me = new MidiEvent(mm, lengthInTicks);
+            track.add(me);
+            //out("Added realtime event: new size="+track.size());
+        } catch (InvalidMidiDataException e) {
+            out(e);
+        }
+        out("OK");
+
+        return sequence;
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordDoesNotCopy.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary Sequencer doesn't create distinct messages when recording events.
+ * @key headful
+ */
+public class SeqRecordDoesNotCopy {
+    public static void main(String argv[]) throws Exception {
+        Sequencer s = MidiSystem.getSequencer();
+        s.open();
+        try {
+            Sequence seq = new Sequence(Sequence.PPQ, 384, 2);
+            s.setSequence(seq);
+            Track t = seq.getTracks()[0];
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x7F);
+            t.add(new MidiEvent(msg, 11000));
+            msg.setMessage(0x90, 0x40, 0x00);
+            t.add(new MidiEvent(msg, 12000));
+            t = seq.getTracks()[1];
+            s.recordEnable(t, -1);
+            System.out.println("Started recording...");
+            s.startRecording();
+            Receiver r = s.getReceiver();
+            Thread.sleep(100);
+            // send a normal message
+            System.out.println("Recording a normal NOTE ON message...");
+            msg.setMessage(0x90, 0x40, 0x6F);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            // send a normal message
+            System.out.println("Recording a normal NOTE OFF message...");
+            msg.setMessage(0x90, 0x40, 0x00);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            s.stop();
+            // now see if the messages were recorded
+            System.out.println("Recorded messages:");
+            int sameMessage = 0;
+            for (int i = 0; i < t.size(); i++) {
+                System.out.print(" "+(i+1)+". ");
+                printEvent(t.get(i));
+                if (t.get(i).getMessage() == msg) {
+                    System.out.println("## Failed: Same Message reference!");
+                    sameMessage++;
+                }
+            }
+            if (sameMessage > 0) {
+                System.out.println("## Failed: The same instance was recorded!");
+                throw new Exception("Test FAILED!");
+            }
+            System.out.println("Did not detect any duplicate messages.");
+            System.out.println("Test passed.");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            //e.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } finally {
+            s.close();
+        }
+    }
+    public static void printEvent(MidiEvent event)
+    {
+        MidiMessage message = event.getMessage();
+        long tick = event.getTick();
+        byte[] data = message.getMessage();
+
+        StringBuffer sb = new StringBuffer((data.length * 3) - 1);
+
+        for (int i = 0; i < data.length; i++)
+        {
+                sb.append(toHexByteString(data[i]));
+                if (i < data.length - 1) sb.append(' ');
+        }
+        System.out.printf("%5d: %s%n", tick, sb);
+    }
+
+    private static String toHexByteString(int n)
+    {
+        if (n < 0) n &= 0xFF;
+        String s = Integer.toHexString(n).toUpperCase();
+        if (s.length() == 1) s = '0' + s;
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqRecordsRealTimeEvents.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5048381
+ * @summary Sequencer records real time messages into the sequence
+ * @key headful
+ */
+public class SeqRecordsRealTimeEvents {
+    public static void main(String argv[]) throws Exception {
+        Sequencer s = MidiSystem.getSequencer();
+        s.open();
+        try {
+            Sequence seq = new Sequence(Sequence.PPQ, 384, 2);
+            s.setSequence(seq);
+            Track t = seq.getTracks()[0];
+            ShortMessage msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x7F);
+            t.add(new MidiEvent(msg, 11000));
+            msg = new ShortMessage();
+            msg.setMessage(0x90, 0x40, 0x00);
+            t.add(new MidiEvent(msg, 12000));
+            t = seq.getTracks()[1];
+            s.recordEnable(t, -1);
+            System.out.println("Started recording...");
+            s.startRecording();
+            Receiver r = s.getReceiver();
+            Thread.sleep(100);
+            int oldTrackSize = t.size();
+            // send a realtime message to the track
+            System.out.println("Recording real time message...");
+            msg = new ShortMessage();
+            msg.setMessage(0xF8, 0, 0);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            // send a normal message
+            msg = new ShortMessage();
+            System.out.println("Recording a normal NOTE ON message...");
+            msg.setMessage(0x90, 0x40, 0x6F);
+            r.send(msg, -1);
+            Thread.sleep(100);
+            s.stop();
+            // now see if the messages were recorded
+            int newMessages = t.size() - oldTrackSize;
+            System.out.println("Recorded messages:");
+            for (int i = 0; i < t.size(); i++) {
+                System.out.print(" "+(i+1)+". ");
+                printEvent(t.get(i));
+            }
+            if (newMessages == 0) {
+                System.out.println("## Failed: No messages were recorded!");
+                throw new Exception("Test FAILED!");
+            } else if (newMessages == 1) {
+                System.out.println("Only one message was recorded. Correct!");
+            } else if (newMessages > 1) {
+                System.out.println("## Failed: 2 or more messages were recorded!");
+                throw new Exception("Test FAILED!");
+            }
+            System.out.println("Test passed.");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            //e.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } finally {
+            s.close();
+        }
+    }
+    public static void printEvent(MidiEvent event)
+    {
+        MidiMessage message = event.getMessage();
+        long tick = event.getTick();
+        byte[] data = message.getMessage();
+
+        StringBuffer sb = new StringBuffer((data.length * 3) - 1);
+
+        for (int i = 0; i < data.length; i++)
+        {
+                sb.append(toHexByteString(data[i]));
+                if (i < data.length - 1) sb.append(' ');
+        }
+        System.out.printf("%5d: %s%n", tick, sb);
+    }
+
+    private static String toHexByteString(int n)
+    {
+        if (n < 0) n &= 0xFF;
+        String s = Integer.toHexString(n).toUpperCase();
+        if (s.length() == 1) s = '0' + s;
+        return s;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SeqStartRecording.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 5001943
+ * @summary Sequencer.startRecording throws unexpected NPE
+ * @key headful
+ */
+public class SeqStartRecording {
+    public static void main(String argv[]) throws Exception {
+        Sequencer seq = MidiSystem.getSequencer();
+        seq.open();
+        try {
+            seq.startRecording();
+            System.out.println("Test passed.");
+        } catch (NullPointerException npe) {
+            System.out.println("Caught NPE: "+npe);
+            npe.printStackTrace();
+            throw new Exception("Test FAILED!");
+        } catch (Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            e.printStackTrace();
+            System.out.println("Test NOT failed.");
+        } finally {
+            seq.close();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerCacheValues.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,106 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4716740
+ * @summary default sequencer does not set the tempo factor
+ */
+public class SequencerCacheValues {
+
+    static boolean failed = false;
+
+    public static void main(String args[]) throws Exception {
+        Sequencer seq = null;
+        int totalNumberOfSequencers = 0;
+
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int device=0; device<infos.length; device++) {
+            //seq = MidiSystem.getSequencer();
+            MidiDevice dev = MidiSystem.getMidiDevice(infos[device]);
+            if (dev instanceof Sequencer) {
+                seq = (Sequencer) dev;
+                totalNumberOfSequencers++;
+                System.out.println("Opening sequencer "+infos[device]);
+                try {
+                    seq.open();
+                    try {
+                        doTest(seq);
+                    } finally {
+                        if (seq != null) {
+                            seq.close();
+                            seq = null;
+                        }
+                    }
+                } catch (MidiUnavailableException mue) {
+                    System.err.println("MidiUnavailableException was thrown: " + mue);
+                    System.err.println("could not test this sequencer.");
+                }
+            }
+        }
+        if (totalNumberOfSequencers == 0) {
+            System.out.println("No sequencers installed!");
+            failed = true;
+        }
+        if (failed) {
+            throw new Exception("FAILED");
+        } else {
+            System.out.println("test OK");
+        }
+    }
+
+    public static boolean equalsFloat(float f1, float f2) {
+        return (f1-f2<0.0001) && (f2-f1<0.0001);
+    }
+
+    public static void doTest(Sequencer seq) throws Exception {
+        seq.setTempoInMPQ(3.0f);
+        System.out.println("Setting tempo in MPQ to "+3.0f);
+        if (!equalsFloat(seq.getTempoInMPQ(), 3.0f)) {
+            System.err.println("getTempoInMPQ() returns wrong value : "
+                + seq.getTempoInMPQ());
+            failed = true;
+        }
+
+        System.out.println("Setting tempo factor to "+2.0f);
+        seq.setTempoFactor(2.0f);
+        if (!equalsFloat(seq.getTempoFactor(), 2.0f)) {
+            System.err.println("getTempoFactor() returns: " + seq.getTempoFactor());
+            failed = true;
+        }
+
+        float bpmTempo = 120.0f;
+        System.out.println("Setting tempo to "+120.0f+"bpm");
+        seq.setTempoInBPM(bpmTempo);
+        if (!equalsFloat(seq.getTempoInMPQ(), (60000000.0f/seq.getTempoInBPM()))) {
+            System.err.println("getTempoInMPQ() returns: " + seq.getTempoInMPQ());
+            System.err.println("getTempoInBPM() returns: " + seq.getTempoInBPM());
+            failed = true;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerSetMuteSolo.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,170 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4713900
+ * @summary default Sequencer allows to set Mute for invalid track
+ */
+public class SequencerSetMuteSolo {
+
+    public static void main(String args[]) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+
+        //printMidiFile(args[0]);
+
+        boolean failed = false;
+        Sequencer seq = null;
+        Sequence midiData = getSequence();
+        int numTracks = midiData.getTracks().length;
+        int totalNumberOfSequencers = 0;
+        int totalNumberOfTestedSequencers = 0;
+
+        MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
+        for (int device=0; device<infos.length; device++) {
+            //seq = MidiSystem.getSequencer();
+            MidiDevice dev = MidiSystem.getMidiDevice(infos[device]);
+            if (dev instanceof Sequencer) {
+                seq = (Sequencer) dev;
+                totalNumberOfSequencers++;
+                System.out.println("Opening sequencer "+infos[device]);
+                try {
+                    seq.open();
+                    try {
+                        seq.setSequence(midiData);
+                        System.err.println("Number of tracks: " + numTracks);
+                        System.err.println("TrackMute["+numTracks+"] state was: " + seq.getTrackMute(numTracks));
+                        System.err.println("  setting to muted.");
+                        seq.setTrackMute(numTracks, true);
+                        System.err.println("  TrackMute["+numTracks+"] is now: " + seq.getTrackMute(numTracks));
+                        if (seq.getTrackMute(numTracks)) {
+                            failed = true;
+                        }
+                        System.err.println("TrackSolo["+numTracks+"] state was: " + seq.getTrackSolo(numTracks));
+                        System.err.println("  setting to solo.");
+                        seq.setTrackSolo(numTracks, true);
+                        System.err.println("  TrackSolo["+numTracks+"] is now: " + seq.getTrackSolo(numTracks));
+                        if (seq.getTrackSolo(numTracks)) {
+                            failed = true;
+                        }
+                        totalNumberOfTestedSequencers++;
+                    } finally {
+                        if (seq != null) {
+                            seq.close();
+                            seq = null;
+                        }
+                    }
+                } catch (MidiUnavailableException mue) {
+                    System.err.println("MidiUnavailableException was thrown: " + mue);
+                    System.err.println("could not test this sequencer.");
+                    return;
+                }
+            }
+        }
+        if (totalNumberOfSequencers == 0) {
+            System.out.println("No sequencers installed!");
+            failed = true;
+        }
+        if (totalNumberOfTestedSequencers == 0) {
+            System.out.println("Could not test any sequencers!");
+            failed = true;
+        }
+        if( failed ) {
+            throw new Exception("FAILED");
+        } else {
+            System.out.println("test OK");
+        }
+    }
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printMidiFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+                s+=getString(data[i])+", ";
+                if (s.length()>72) {
+                        System.out.println(s);
+                        s="";
+                }
+        }
+        System.out.println(s);
+    }
+
+    public static Sequence getSequence() throws Exception {
+        ByteArrayInputStream bais = new ByteArrayInputStream(pitchbend);
+        Sequence seq = MidiSystem.getSequence(bais);
+        return seq;
+    }
+
+    public static byte[] pitchbend = {
+        77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, 2, 0, 120, 77, 84, 114, 107, 0, 0,
+        0, 27, 0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32,
+        116, 114, 97, 99, 107, 32, 48, 0, -1, 47, 0, 77, 84, 114, 107, 0, 0, 0, -44,
+        0, -1, 3, 19, 77, 73, 68, 73, 32, 116, 101, 115, 116, 32, 45, 32, 116, 114,
+        97, 99, 107, 32, 49, 0, -64, 30, 0, -112, 68, 126, 0, -32, 6, 67, 0, 14,
+        71, 0, 20, 74, 0, 26, 77, 0, 32, 80, 0, 42, 85, 6, 50, 89, 6, 56, 92, 5,
+        66, 97, 6, 74, 101, 6, 80, 104, 11, 84, 106, 20, 76, 102, 6, 70, 99, 5, 60,
+        94, 6, 52, 90, 5, 44, 86, 4, 34, 81, 5, 26, 77, 5, 20, 74, 6, 10, 69, 5,
+        2, 65, 7, 0, 64, 42, -112, 66, 123, 11, 68, 0, 72, 63, 126, 4, 66, 0, 43,
+        -32, 0, 63, 6, 0, 60, 7, 0, 56, 6, 0, 53, 5, 0, 49, 5, 0, 43, 4, 0, 37, 3,
+        0, 30, 3, 0, 25, 3, 0, 19, 3, 0, 13, 4, 0, 8, 4, 0, 2, 4, 0, 0, 70, 0, 3,
+        5, 0, 9, 3, 0, 14, 7, 0, 16, 25, 0, 21, 5, 0, 25, 7, 0, 28, 5, 0, 32, 5,
+        0, 36, 5, 0, 41, 6, 0, 46, 5, 0, 50, 5, 0, 53, 4, 0, 58, 7, 0, 61, 7, 0,
+        64, 117, -112, 63, 0, 0, -1, 47, 0
+    };
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SequencerState.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,272 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.IOException;
+import java.io.InputStream;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiDevice;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+
+/**
+ * @test
+ * @bug 4913027
+ * @summary several Sequencer methods should specify behaviour on closed Sequencer
+ */
+public class SequencerState {
+
+    private static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        out("4913027: several Sequencer methods should should specify behaviour on closed Sequencer");
+        if (hasSequencer()) {
+            boolean passed = testAll();
+            if (passed) {
+                out("Test PASSED.");
+            } else {
+                throw new Exception("Test FAILED.");
+            }
+        }
+    }
+
+    /**
+     * Execute the test on all available Sequencers.
+     *
+     * @return true if the test passed for all Sequencers, false otherwise
+     */
+    private static boolean testAll() throws Exception {
+        boolean result = true;
+        MidiDevice.Info[] devices = MidiSystem.getMidiDeviceInfo();
+        for (int i = 0; i < devices.length; i++) {
+            MidiDevice device = MidiSystem.getMidiDevice(devices[i]);
+            if (device instanceof Sequencer) {
+                result &= testSequencer((Sequencer) device);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Execute the test on the passed Sequencer.
+     *
+     * @return true if the test is passed this Sequencer, false otherwise
+     */
+    private static boolean testSequencer(Sequencer seq) throws Exception {
+        boolean result = true;
+
+        out("testing: " + seq);
+        /* test calls in closed state.
+         */
+        if (seq.isOpen()) {
+            out("Sequencer is already open, cannot test!");
+            return result;
+        }
+
+        try {
+            seq.start();
+            out("closed state: start() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.stop();
+            out("closed state: stop() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.startRecording();
+            out("closed state: startRecording() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        try {
+            seq.stopRecording();
+            out("closed state: stopRecording() does not throw IllegalStateException!");
+            result = false;
+        } catch (IllegalStateException e) {
+        }
+
+        Sequence sequence = createSequence();
+        if (sequence == null) {
+            out("created Sequence is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(sequence);
+        } catch (IllegalStateException e) {
+            out("closed state: setSequence(Sequence) throws IllegalStateException!");
+            result = false;
+        }
+
+        InputStream inputStream = createSequenceInputStream();
+        if (inputStream == null) {
+            out("created InputStream is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(inputStream);
+        } catch (IllegalStateException e) {
+            out("closed state: setSequence(InputStream) throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.getSequence();
+        } catch (IllegalStateException e) {
+            out("closed state: getSequence() throws IllegalStateException!");
+            result = false;
+        }
+
+        /* test calls in open state.
+         */
+        seq.open();
+        if (! seq.isOpen()) {
+            out("Sequencer is not open, cannot test!");
+            return result;
+        }
+
+        try {
+            seq.start();
+        } catch (IllegalStateException e) {
+            out("open state: start() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.stop();
+        } catch (IllegalStateException e) {
+            out("open state: stop() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.startRecording();
+        } catch (IllegalStateException e) {
+            out("open state: startRecording() throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.stopRecording();
+        } catch (IllegalStateException e) {
+            out("open state: stopRecording() throws IllegalStateException!");
+            result = false;
+        }
+
+        sequence = createSequence();
+        if (sequence == null) {
+            out("created Sequence is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(sequence);
+        } catch (IllegalStateException e) {
+            out("open state: setSequence(Sequence) throws IllegalStateException!");
+            result = false;
+        }
+
+        inputStream = createSequenceInputStream();
+        if (inputStream == null) {
+            out("created InputStream is null, cannot test!");
+            return result;
+        }
+        try {
+            seq.setSequence(inputStream);
+        } catch (IllegalStateException e) {
+            out("open state: setSequence(InputStream) throws IllegalStateException!");
+            result = false;
+        }
+
+        try {
+            seq.getSequence();
+        } catch (IllegalStateException e) {
+            out("open state: getSequence() throws IllegalStateException!");
+            result = false;
+        }
+
+        seq.close();
+        return result;
+    }
+
+    /**
+     * Create a new Sequence for testing.
+     *
+     * @return a dummy Sequence, or null, if a problem occured while creating
+     *         the Sequence
+     */
+    private static Sequence createSequence() {
+        Sequence sequence = null;
+        try {
+            sequence = new Sequence(Sequence.PPQ, 480, 1);
+        } catch (InvalidMidiDataException e) {
+            // DO NOTHING
+        }
+        return sequence;
+    }
+
+    /**
+     * Create a new InputStream containing a Sequence for testing.
+     *
+     * @return an InputStream containing a dummy Sequence, or null, if a problem
+     *         occured while creating the InputStream
+     */
+    private static InputStream createSequenceInputStream() {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        Sequence sequence = createSequence();
+        if (sequence == null) {
+            return null;
+        }
+        try {
+            MidiSystem.write(sequence, 0, baos);
+            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+            return bais;
+        } catch (IOException e) {
+            return null;
+        }
+    }
+
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/SetTickPosition.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,139 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4493775
+ * @summary Sequncer method, setTickPosition(long) doesnot set the Tick position
+ */
+public class SetTickPosition {
+        private static boolean testPassed = true;
+
+        public void runTest()
+        {
+            Sequencer theSequencer = null;
+            try
+            {
+                System.out.print("Getting Sequencer...");
+                theSequencer = MidiSystem.getSequencer();
+                System.out.println("got "+theSequencer);
+
+                if(!(theSequencer.isOpen()))
+                {
+                    System.out.println("Opening Sequencer...");
+                    theSequencer.open();
+
+                    if(!(theSequencer.isOpen()))
+                    {
+                        System.out.println("Unable to open the Sequencer. Test NOT FAILED.");
+                        return;
+                    }
+                }
+
+                System.out.println("theSequencer is open!\n");
+
+                System.out.println("Creating New Sequence...");
+                Sequence theSequence = new Sequence(Sequence.PPQ, 120);
+
+                System.out.println("Adding Track To Sequence...");
+                Track theTrack = theSequence.createTrack();
+
+                int theChannel = 0;
+
+                int theNote = 60;
+                int theVelocity = 100;
+                ShortMessage theShortMessage = new ShortMessage();
+
+                for (int tick=0; tick<2000; tick+=120) {
+                    //System.out.println("Adding NOTE_ON To Track At Tick: " + tick + "...\n");
+                    theShortMessage.setMessage(ShortMessage.NOTE_ON, theChannel, theNote, theVelocity);
+                    MidiEvent theMidiEvent = new MidiEvent(theShortMessage, tick);
+                    theTrack.add(theMidiEvent);
+
+                    //System.out.println("Adding NOTE_OFF To Track At Tick: " + (tick+60) + "...\n");
+                    theShortMessage.setMessage(ShortMessage.NOTE_OFF, theChannel, theNote, theVelocity);
+                    theMidiEvent = new MidiEvent(theShortMessage, tick+60);
+                    theTrack.add(theMidiEvent);
+                }
+                theSequencer.setSequence(theSequence);
+
+                float theTempoInBPM = 120;
+                theSequencer.setTempoInBPM(theTempoInBPM);
+                long theTickLengthOfSequence = theSequencer.getTickLength();
+                System.out.println("Length Of Sequence In Ticks: " + theTickLengthOfSequence);
+                System.out.println("Sequence resolution: " + theSequencer.getSequence().getResolution());
+
+                theSequencer.start();
+                for(long theTickPosition = 0; theTickPosition < theTickLengthOfSequence; theTickPosition += (theTickLengthOfSequence / 10))
+                {
+                    System.out.println("Now Setting Tick Position To: " + theTickPosition);
+                    theSequencer.setTickPosition(theTickPosition);
+
+                    long theCurrentTickPosition = theSequencer.getTickPosition();
+                    long theCurrentMsPosition = (long) (theSequencer.getMicrosecondPosition()/1000);
+                    System.out.println("IsRunning()=" + theSequencer.isRunning());
+                    System.out.println("Now Current Tick Position Is: " + theCurrentTickPosition);
+                    //System.out.println("Now Current micro Position Is: " + theCurrentMsPosition);
+                    System.out.println("");
+
+                    try {
+                        Thread.sleep(800);
+                    } catch (InterruptedException ie) {}
+
+                    // last time, set tick pos to 0
+                    if (theTickPosition>0 && theTickPosition<(theTickLengthOfSequence / 10)) {
+                        theTickPosition=(theTickLengthOfSequence / 10);
+                    }
+
+                    // 30 = 1/4 * 120, the resolution of the sequence
+                    if(Math.abs(theCurrentTickPosition - theTickPosition) > 30) {
+                        System.out.println("theCurrentTickPosition != theTickPosition!");
+                        testPassed = false;
+                    }
+                }
+
+            }
+            catch (Exception ex) { ex.printStackTrace(); }
+            if (theSequencer != null) {
+                theSequencer.close();
+            }
+            if (testPassed) {
+                System.out.println("Test Passed.");
+            }
+        }
+
+    public static void main(String[] args) throws Exception {
+        SetTickPosition thisTest = new SetTickPosition();
+        thisTest.runTest();
+        if (!testPassed) {
+            throw new Exception("Test FAILED");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Sequencer/TickLength.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,211 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaEventListener;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4427890
+ * @run main/othervm TickLength
+ * @summary Sequencer.getTickLength() and Sequence.getTickLength() report the
+ *          wrong length
+ */
+public class TickLength implements MetaEventListener {
+    private Sequence          theSequence;
+    private Sequencer         theSequencer;
+
+    public TickLength() {
+     this.initMidiCompoments();
+     System.out.println("Got Sequencer "+theSequencer);
+     theSequence = this.generateSequence();
+     try {
+       theSequencer.setSequence(theSequence);
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"\tCannot set sequence to sequencer ("+e+")");
+       return;
+     }
+    }
+
+    public  void start() {
+     theSequencer.start();
+    }
+
+    /*
+     instantiate the necessary midi components
+    */
+    private boolean initMidiCompoments() {
+
+
+     try {
+       theSequencer = MidiSystem.getSequencer();
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"\tSequencer Device not supported"+e+")");
+       return false;
+     }
+
+     try {
+       theSequencer.open();
+     }
+     catch(Exception e) {
+       System.out.println(this.getClass()+"Cannot open Sequencer Device");
+       return false;
+     }
+     if(!theSequencer.addMetaEventListener(this)) {
+       System.out.println(this.getClass()+"\tCould not register MetaEventListener - there will be problems with scrolling! ");
+       return false;
+     }
+     return true;
+    }
+
+    static int lastTick = 0;
+
+    private Sequence generateSequence() {
+     MidiEvent dummyMidiEvent;
+     ShortMessage dummyShortMessage;
+     Sequence dummySequence        = null;
+     Track[] allTracks ;
+     Track theTrack;
+
+     try {
+       dummySequence = new Sequence(Sequence.PPQ,1500);
+     }
+     catch(InvalidMidiDataException e) {
+       System.out.println("O o "+e);
+     }
+
+     dummySequence.createTrack();
+     allTracks = dummySequence.getTracks();
+     theTrack = allTracks[0];
+    lastTick = 0;
+     for(int i=0;i<20; i++) {
+       theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_ON, 2, 30+i, 100,100+1000*i));
+       theTrack.add(this.createMetaMidiEvent(1,"start",100+1000*i));
+       lastTick = (1000*i)+600;
+       theTrack.add(this.createShortMidiEvent(ShortMessage.NOTE_OFF, 2, 30+i, 100, lastTick));
+       theTrack.add(this.createMetaMidiEvent(1,"end",lastTick));
+     }
+
+     return dummySequence;
+    }
+
+    /*
+     A method to create a short midi event (sound)
+    */
+
+    public MidiEvent createShortMidiEvent(int theCommand, int theChannel, int theData1, int theData2, long theTime) {
+     ShortMessage dummyShortMessage;
+     MidiEvent    dummyMidiEvent;
+
+     try {
+       dummyShortMessage = new ShortMessage();
+       dummyShortMessage.setMessage(theCommand, theChannel, theData1, theData2);
+       dummyMidiEvent    = new MidiEvent(dummyShortMessage,theTime);
+     }
+     catch (Exception e) {
+       System.out.println(this.getClass()+"\t"+e);
+       return null;
+     }
+
+     return dummyMidiEvent;
+    }
+
+    /*
+     A method to create a meta midi event (used in  meta() method)
+    */
+    public MidiEvent createMetaMidiEvent(int theType, String theData1, long theTime) {
+     MetaMessage  dummyMetaMessage;
+     MidiEvent    dummyMidiEvent;
+
+     try {
+       dummyMetaMessage = new MetaMessage();
+       dummyMetaMessage.setMessage(theType, theData1.getBytes(), theData1.length());
+       dummyMidiEvent    = new MidiEvent(dummyMetaMessage,theTime);
+     }
+     catch (Exception e) {
+       System.out.println(e);
+       return null;
+     }
+
+     return dummyMidiEvent;
+    }
+
+    /*
+     the method is activated by each meta midi event
+     it puts out the actual tick position, as well as the WRONG total tick length and the RIGHT
+     tick length using the work around by dividing the total length by 64
+    */
+    public void meta(MetaMessage p1) {
+     if(p1.getType() ==47) {
+       return;
+     }
+     System.out.println("getTickPosition:\t"+theSequencer.getTickPosition()
+         +"\t Sequencer.getTickLength:\t"+theSequencer.getTickLength()
+         +"\tReal Length:\t"+lastTick
+         +"\t Sequence.getTickLength:\t"+theSequence.getTickLength()
+         //(theSequencer.getTickLength()/64));
+         );
+    }
+
+    public void checkLengths() throws Exception {
+        System.out.println("Sequencer.getTickLength() = "+theSequencer.getTickLength());
+        System.out.println("Sequence.getTickLength() = "+theSequence.getTickLength());
+        long diff = theSequencer.getTickLength() - theSequence.getTickLength();
+        if (diff > 100 || diff < -100) {
+                throw new Exception("Difference too large! Failed.");
+        }
+        System.out.println("Passed");
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!hasSequencer()) {
+            return;
+        }
+         TickLength tlt = new TickLength();
+         //tlt.start();
+         tlt.checkLengths();
+    }
+
+    static boolean hasSequencer() {
+        try {
+            Sequencer seq = MidiSystem.getSequencer();
+            if (seq != null) {
+                seq.open();
+                seq.close();
+                return true;
+            }
+        } catch (Exception e) {}
+        System.out.println("No sequencer available! Cannot execute test.");
+        return false;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,71 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4851018
+ * @summary MidiMessage.getLength and .getData return wrong values.
+ *          also: 4890405: Reading MidiMessage byte array fails in 1.4.2
+ */
+public class FastShortMessage {
+    public static void main(String args[]) throws Exception {
+        int[] dataMes =  {ShortMessage.NOTE_ON | 9, 0x24, 0x50};
+        int res = 240;
+        Sequence midiData = new Sequence(Sequence.PPQ, res);
+
+        Track track = midiData.createTrack();
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        track.add(new MidiEvent(msg, 0));
+
+        // save sequence to outputstream
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        MidiSystem.write(midiData, 0, baos);
+
+        // reload that sequence
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        Sequence seq = MidiSystem.getSequence(is);
+
+        track = seq.getTracks()[0];
+        msg = (ShortMessage) (track.get(0).getMessage());
+        byte[] msgData = msg.getMessage();
+
+        if (msgData.length != dataMes.length
+         || (msgData[0] & 0xFF) != dataMes[0]
+         || (msgData[1] & 0xFF) != dataMes[1]
+         || (msgData[2] & 0xFF) != dataMes[2]) {
+            throw new Exception("test failed. read length="+msgData.length);
+        }
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/ShortMessage/FastShortMessage2.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 5011306
+ * @summary FastShortMessage.setMessage does not use the data2 parameter
+ */
+public class FastShortMessage2 {
+
+    public static void main(String args[]) throws Exception {
+        int[] dataMes =  {ShortMessage.NOTE_ON | 9, 0x24, 0x50};
+
+        Sequence midiData = new Sequence(Sequence.PPQ, 240);
+        Track track = midiData.createTrack();
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        track.add(new MidiEvent(msg, 0));
+        // save sequence to outputstream
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        MidiSystem.write(midiData, 0, baos);
+        // reload that sequence
+        InputStream is = new ByteArrayInputStream(baos.toByteArray());
+        Sequence seq = MidiSystem.getSequence(is);
+        track = seq.getTracks()[0];
+        msg = (ShortMessage) (track.get(0).getMessage());
+        if (!msg.getClass().toString().contains("FastShortMessage")) {
+            System.out.println("msg is not FastShortMessage, this test is useless then..."+msg.getClass());
+        }
+
+        msg.setMessage(dataMes[0], dataMes[1], dataMes[2]);
+        byte[] msgData = msg.getMessage();
+
+        if (msgData.length != dataMes.length
+         || (msgData[0] & 0xFF) != dataMes[0]
+         || (msgData[1] & 0xFF) != dataMes[1]
+         || (msgData[2] & 0xFF) != dataMes[2]) {
+            System.out.println("status="+(msgData[0] & 0xFF)+" and expected "+dataMes[0]);
+            System.out.println("data1="+(msgData[1] & 0xFF)+" and expected "+dataMes[1]);
+            System.out.println("data2="+(msgData[2] & 0xFF)+" and expected "+dataMes[2]);
+            throw new Exception("Test FAILED!");
+        }
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Soundbanks/ExtraCharInSoundbank.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,123 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.Instrument;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4429762
+ * @summary Some instrument names in some soundbanks include bad extra characters
+ */
+public class ExtraCharInSoundbank {
+
+    private static void printName(String loadedName)
+    {
+        System.out.println("Loaded Name: " + loadedName);
+        byte[] theLoadedNameByteArray = loadedName.getBytes();
+
+        System.out.print("Name Bytes: ");
+        for(int i = 0; i < theLoadedNameByteArray.length; i++)
+            System.out.print((Integer.toHexString((int)theLoadedNameByteArray[i]).toUpperCase()) + " ");
+        System.out.println("");
+        System.out.println("");
+    }
+
+    private static boolean containsControlChar(String name) {
+        byte[] bytes = name.getBytes();
+        for (int i = 0; i < bytes.length; i++) {
+            if (bytes[i] < 32) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean checkInstrumentNames(Synthesizer theSynthesizer)
+    {
+        boolean containsControlCharacters = false;
+
+        Instrument[] theLoadedInstruments = theSynthesizer.getLoadedInstruments();
+
+        System.out.println("Checking soundbank...");
+        for(int theInstrumentIndex = 0; theInstrumentIndex < theLoadedInstruments.length; theInstrumentIndex++) {
+            String name = theLoadedInstruments[theInstrumentIndex].getName();
+            if (containsControlChar(name)) {
+                containsControlCharacters = true;
+                System.out.print("Instrument[" + theInstrumentIndex + "] contains unexpected control characters: ");
+                printName(name);
+            }
+        }
+        return !containsControlCharacters;
+    }
+
+    public static void main(String[] args) throws Exception {
+        // the internal synthesizer needs a soundcard to work properly
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+        Synthesizer theSynth = MidiSystem.getSynthesizer();
+        System.out.println("Got synth: "+theSynth);
+        theSynth.open();
+        try {
+            Soundbank theSoundbank = theSynth.getDefaultSoundbank();
+            System.out.println("Got soundbank: "+theSoundbank);
+            theSynth.loadAllInstruments(theSoundbank);
+            try {
+                    if (!checkInstrumentNames(theSynth)) {
+                            throw new Exception("Test failed");
+                    }
+            } finally {
+                    theSynth.unloadAllInstruments(theSoundbank);
+            }
+        } finally {
+            theSynth.close();
+        }
+        System.out.println("Test passed.");
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Soundbanks/GetSoundBankIOException.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,85 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 4629810
+ * @summary MidiSystem.getSoundbank() throws unexpected IOException
+ */
+public class GetSoundBankIOException {
+
+    public static void main(String args[]) throws Exception {
+        boolean failed = false;
+        try {
+            String filename = "GetSoundBankIOException.java";
+            System.out.println("Opening "+filename+" as soundbank...");
+            File midiFile = new File(System.getProperty("test.src", "."), filename);
+            MidiSystem.getSoundbank(midiFile);
+            //Soundbank sBank = MidiSystem.getSoundbank(new NonMarkableIS());
+            System.err.println("InvalidMidiDataException was not thrown!");
+            failed = true;
+        } catch (InvalidMidiDataException invMidiEx) {
+            System.err.println("InvalidMidiDataException was thrown. OK.");
+        } catch (IOException ioEx) {
+            System.err.println("Unexpected IOException was caught!");
+            System.err.println(ioEx.getMessage());
+            ioEx.printStackTrace();
+            failed = true;
+        }
+
+        if (failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    private static class NonMarkableIS extends InputStream {
+        int counter = 0;
+
+        public NonMarkableIS() {
+        }
+
+        public int read() throws IOException {
+            if (counter > 1000) return -1;
+            return (++counter) % 256;
+        }
+
+        public synchronized void mark(int readlimit) {
+            System.out.println("Called mark with readlimit= "+readlimit);
+        }
+
+        public synchronized void reset() throws IOException {
+            throw new IOException("mark/reset not supported");
+        }
+
+        public boolean markSupported() {
+            return false;
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/AsynchronousMidiChannel.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+import java.io.PrintStream;
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiChannel;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4987585
+ * @summary Some MidiChannel methods are asynchronous
+ */
+public class AsynchronousMidiChannel {
+    static PrintStream log = System.err;
+    static PrintStream ref = System.out;
+
+    public static void main(String args[]) {
+        doIt(args);
+    }
+
+    public static void doIt(String args[]) {
+        Synthesizer synth = null;
+        MidiChannel mChanArr[];
+        MidiChannel chan = null;
+        boolean failed = false;
+        int i = 0;
+        int chanNum = 0;
+
+        int val = 1;
+        int contr = 0;
+        Soundbank sBank;
+        Instrument[] insArr;
+        Instrument instr = null;
+        Object ev = new Object();
+
+        try {
+            synth = MidiSystem.getSynthesizer();
+            System.out.println("Got synth: "+synth);
+            synth.open();
+
+            int latency = (int) synth.getLatency();
+            System.out.println("  -> latency: "
+                               +latency
+                               +" microseconds");
+
+            mChanArr = synth.getChannels();
+            while ((i < mChanArr.length) && (chan == null)) {
+                chanNum = i;
+                chan = mChanArr[i++];
+            }
+            if (chan == null) {
+                System.out.println("No channels in "
+                                   +"this synthesizer!");
+                return;
+            }
+            System.out.println("Got MidiChannel: "+chan);
+
+
+            sBank = synth.getDefaultSoundbank();
+            if (sBank == null) {
+                System.out.println("No default sound bank!");
+                return;
+            }
+
+
+            insArr = sBank.getInstruments();
+            for (int j = 0; j < insArr.length; j++) {
+                if (insArr[j].getPatch().getBank() == val) {
+                    instr = insArr[j];
+                    synth.loadInstrument(instr);
+                }
+            }
+            if (instr == null) {
+                System.out.println("No instr. with this bank!");
+                return;
+            }
+
+            chan.controlChange(contr, val);
+
+            // need to respect the synthesizer's latency
+            if (latency > 0) {
+                try {
+                    Thread.sleep(latency/1000);
+                } catch (InterruptedException inEx) {
+                }
+            }
+
+            if (chan.getController(contr) != val) {
+                failed = true;
+                System.err.println("getController() does not "
+                                   +"return proper value: "
+                + chan.getController(contr));
+            }  else {
+                System.out.println("getController("
+                + contr + ") returns proper value: "
+                + chan.getController(contr));
+            }
+
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was "
+                               +"thrown: " + mue);
+            System.out.println("could not test.");
+            return;
+        } catch(SecurityException se) {
+            se.printStackTrace();
+            System.err.println("Sound access is not denied but "
+            + "SecurityException was thrown!");
+            return;
+
+        } finally {
+            if (synth != null) synth.close();
+        }
+
+
+        if (failed == true) {
+            System.out.println("test failed");
+        } else {
+            System.out.println("OKAY");
+        }
+        return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/Receiver/bug6186488.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiDevice;
+import javax.sound.midi.MidiMessage;
+import javax.sound.midi.MidiSystem;
+
+/**
+ * @test
+ * @bug 6186488
+ * @summary Tests that software Java Syntesizer processed
+ *          non-ShortMessage-derived messages
+ * @run main/manual=yesno bug6186488
+ */
+public class bug6186488 {
+    public static void main(String[] args) throws Exception {
+        MidiDevice/*Synthesizer*/ synth = null;
+
+        try {
+            synth = MidiSystem.getSynthesizer();
+            //synth = MidiSystem.getMidiDevice(infos[0]);
+
+            System.out.println("Synthesizer: " + synth.getDeviceInfo());
+            synth.open();
+            MidiMessage msg = new GenericMidiMessage(0x90, 0x3C, 0x40);
+            //ShortMessage msg = new ShortMessage();
+            //msg.setMessage(0x90, 0x3C, 0x40);
+
+            synth.getReceiver().send(msg, 0);
+            Thread.sleep(2000);
+
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            throw ex;
+        } finally {
+            if (synth != null && synth.isOpen())
+                synth.close();
+        }
+        System.out.print("Did you heard a note? (enter 'y' or 'n') ");
+        int result = System.in.read();
+        System.in.skip(1000);
+        if (result == 'y' || result == 'Y')
+        {
+            System.out.println("Test passed sucessfully.");
+        }
+        else
+        {
+            System.out.println("Test FAILED.");
+            throw new RuntimeException("Test failed.");
+        }
+    }
+
+    private static class GenericMidiMessage extends MidiMessage {
+        GenericMidiMessage(int... message) {
+            super(new byte[message.length]);
+            for (int i=0; i<data.length; i++) {
+                data[i] = (byte)(0xFF & message[i]);
+            }
+        }
+
+        GenericMidiMessage(byte... message) {
+            super(message);
+        }
+
+        public Object clone() {
+            return new GenericMidiMessage((byte[])data.clone());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/SynthesizerGetLatency.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 5029790
+ * @summary Synthesizer.getLatency returns wrong value
+ */
+public class SynthesizerGetLatency {
+
+    public static void main(String args[]) throws Exception {
+        Synthesizer synth = null;
+        boolean failed = false;
+        boolean notexec = false;
+        try {
+            synth = MidiSystem.getSynthesizer();
+            System.out.println("Got synth: "+synth);
+            synth.open();
+
+            int latency = (int) synth.getLatency();
+            System.out.println("  -> latency: "
+                               +latency
+                               +" microseconds");
+            if (latency < 5000 && latency > 0) {
+                System.out.println("## This latency is VERY small, probably due to this bug.");
+                System.out.println("## This causes failure of this test.");
+                failed = true;
+            }
+        } catch (MidiUnavailableException mue) {
+            System.err.println("MidiUnavailableException was "
+                               +"thrown: " + mue);
+            System.out.println("could not test.");
+            notexec = true;
+        } catch(SecurityException se) {
+            se.printStackTrace();
+            System.err.println("Sound access is not denied but "
+            + "SecurityException was thrown!");
+            notexec = true;
+        } finally {
+            if (synth != null) synth.close();
+        }
+
+
+        if (failed) {
+            throw new Exception("Test FAILED!");
+        }
+        if (notexec) {
+            System.out.println("Test not failed.");
+        } else {
+            System.out.println("Test Passed.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Synthesizer/bug4685396.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.Instrument;
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.Soundbank;
+import javax.sound.midi.Synthesizer;
+
+/**
+ * @test
+ * @bug 4685396
+ * @summary Tests that Synthesizer.remapInstrument works
+ * @run main bug4685396
+ * @key headful
+ */
+public class bug4685396 {
+
+    static Synthesizer synth = null;
+
+    public static boolean isInstrumentExist(Instrument inst, Instrument[] insts) {
+        for (int i = 0; i < insts.length; i++) {
+            if (inst.equals(insts[i]))
+                return true;
+        }
+        return false;
+    }
+
+    static boolean test(
+            boolean reloadInstr,    // reload all instruments?
+            boolean unloadFrom,     // unload "from" instrument?
+            boolean unloadTo        // unload "to" instrument?
+            ) throws Exception
+    {
+        log("Starting test: reloadInstr=" + reloadInstr
+                + ", unloadFrom=" + unloadFrom
+                + ", unloadTo=" + unloadTo
+                + "");
+
+        log("  creating synthesizer...");
+        synth = MidiSystem.getSynthesizer();
+        log("  opening synthesizer...");
+        synth.open();
+
+        Soundbank sbank = synth.getDefaultSoundbank();
+        if (sbank == null)
+            throw new RuntimeException("ERROR: Could not get default soundbank");
+
+        if (reloadInstr) {
+            synth.unloadAllInstruments(sbank);
+            synth.loadAllInstruments(sbank);
+        }
+
+        Instrument[] instrs = synth.getLoadedInstruments();
+
+        log("  " + instrs.length + " instruments loaded.");
+
+        if (instrs.length < 2)
+            throw new RuntimeException("ERROR: need at least 2 loaded instruments");
+
+        Instrument from = instrs[0];
+        Instrument to = instrs[instrs.length - 1];
+
+        if (unloadFrom)
+            synth.unloadInstrument(from);
+        if (unloadTo)
+            synth.unloadInstrument(to);
+
+        log("  from instrument (" + (unloadFrom ? "UNLOADED" : "LOADED")
+                                + "): " + from.toString());
+        log("  to instrument (" + (unloadTo ? "UNLOADED" : "LOADED")
+                                + "): " + to.toString());
+
+        boolean result = false;
+        boolean excepted = false;
+        try {
+            result = synth.remapInstrument(from, to);
+            log("  remapInstrument(from, to) returns " + result);
+        } catch (IllegalArgumentException ex) {
+            excepted = true;
+            log("  EXCEPTION:");
+            ex.printStackTrace(System.out);
+        }
+
+        instrs = synth.getLoadedInstruments();
+        log("  " + instrs.length + " instruments remains loaded.");
+
+        boolean toUnloaded = !isInstrumentExist(to, instrs);
+        boolean fromUnloaded = !isInstrumentExist(from, instrs);
+
+        log("  from instrument is " + (fromUnloaded ? "UNLOADED" : "LOADED"));
+        log("  to instrument is " + (toUnloaded ? "UNLOADED" : "LOADED"));
+
+        boolean bOK = true;
+        if (result) {
+            if (unloadTo) {
+                bOK = false;
+                log("ERROR: unloaded to, but sucessfull remap");
+            }
+            if (!fromUnloaded) {
+                bOK = false;
+                log("ERROR: sucessfull remap, but from hasn't been unloaded");
+            }
+            if (toUnloaded) {
+                bOK = false;
+                log("ERROR: to has been unloaded!");
+            }
+        } else {
+            if (!excepted) {
+                bOK = false;
+                log("ERROR: remap returns false, exception hasn't been thrown");
+            }
+            if (!unloadTo) {
+                bOK = false;
+                log("ERROR: to is loaded, but remap returns false");
+            }
+            if (unloadFrom != fromUnloaded) {
+                bOK = false;
+                log("ERROR: remap returns false, but status of from has been changed");
+            }
+        }
+
+        if (bOK) {
+            log("Test result: OK\n");
+        } else {
+            log("Test result: FAIL\n");
+        }
+
+        return bOK;
+    }
+
+    static void cleanup() {
+        if (synth != null) {
+            synth.close();
+            synth = null;
+        }
+    }
+
+    static boolean runTest(
+            boolean reloadInstr,    // reload all instruments?
+            boolean unloadTo,       // unload "to" instrument?
+            boolean unloadFrom      // unload "from" instrument?
+            )
+    {
+        boolean success = false;
+        try {
+            success = test(reloadInstr, unloadFrom, unloadTo);
+        } catch (Exception ex) {
+            log("Exception: " + ex.toString());
+        }
+        cleanup();
+        return success;
+    }
+
+    public static void main(String args[]) throws Exception {
+        boolean failed = false;
+        if (!runTest(true, false, false))
+            failed = true;
+        if (!runTest(true, false, true))
+            failed = true;
+        if (!runTest(true, true, false))
+            failed = true;
+        if (!runTest(true, true, true))
+            failed = true;
+
+        if (failed) {
+            throw new RuntimeException("Test FAILED.");
+        }
+        log("Test sucessfully passed.");
+    }
+
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Track/TrackAddSameTick.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,97 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.ShortMessage;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 4941944
+ * @summary Track may not have a determined order for inserting events at same
+ *          tick time
+ */
+public class TrackAddSameTick {
+
+    static boolean failed = false;
+    static MidiEvent[] evs = new MidiEvent[10];
+
+    public static void main(String argv[]) throws Exception {
+        Sequence seq = new Sequence(Sequence.PPQ, 240);
+        Track t = seq.createTrack();
+
+        log("add 10 events in random order");
+        t.add(createEvent(10, 5));
+        t.add(createEvent(0, 0));
+        t.add(createEvent(10, 6));
+        t.add(createEvent(11, 8));
+        t.add(createEvent(10, 7));
+        t.add(createEvent(0, 1));
+        t.add(createEvent(0, 2));
+        t.add(createEvent(15, 9));
+        t.add(createEvent(0, 3));
+        t.add(createEvent(1, 4));
+
+        // now compare the events.
+        // The note param will tell us the
+        // the expected position
+        long lastTick = 0;
+        for (int i = 0; i < t.size(); i++) {
+            MidiEvent ev = t.get(i);
+            if (ev.getMessage() instanceof ShortMessage) {
+                ShortMessage msg = (ShortMessage) ev.getMessage();
+                log(""+i+": ShortMessage at tick "+ev.getTick()
+                    +" with expected position "+msg.getData1());
+                if (ev.getTick() < lastTick) {
+                    log("  FAILED: last tick is larger than this event's tick!");
+                    failed = true;
+                }
+                if (i != msg.getData1()) {
+                    log("  FAILED: Track did not order correctly.");
+                    failed = true;
+                }
+            }
+        }
+
+        if (failed) throw new Exception("Test FAILED!");
+        log("Test passed.");
+    }
+
+    public static MidiEvent createEvent(long tick, int expectedPos)
+        throws Exception {
+        ShortMessage msg = new ShortMessage();
+        msg.setMessage(0x90, (int) expectedPos, 00);
+        MidiEvent ev = new MidiEvent(msg, tick);
+        return ev;
+    }
+
+    public static void log(String s) {
+        System.out.println(s);
+    }
+
+    public static void log(Exception e) {
+        //System.out.println(s);
+        e.printStackTrace();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Track/bug6416024.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.InvalidMidiDataException;
+import javax.sound.midi.MetaMessage;
+import javax.sound.midi.MidiEvent;
+import javax.sound.midi.Sequence;
+import javax.sound.midi.Track;
+
+/**
+ * @test
+ * @bug 6416024
+ * @summary Tests that sequence correctly handle removing of EndOfTrack event
+ * @run main bug6416024
+ */
+public class bug6416024 {
+
+    boolean test() {
+        Sequence sequence = null;
+        Track track = null;
+        MidiEvent event = null;
+
+        log("creating sequence...");
+        try {
+            sequence = new Sequence(Sequence.PPQ, 10);
+            log("  - OK: " + sequence);
+        } catch(InvalidMidiDataException e ) {
+            log("  - FAILED: got exception");
+            e.printStackTrace(System.out);
+            return false;
+        }
+
+        log("creating track...");
+        track = sequence.createTrack();
+        log("  - OK: " + track);
+        log("initial track size=" + track.size());
+
+        log("removing all track events...");
+        while (track.size() > 0) {
+            try {
+                event = track.get(0);
+                log("  ..removing event " + event);
+                track.remove(event);
+                log("    - OK, track size=" + track.size());
+            } catch (Exception e) {
+                log("  - FAILED: got exception");
+                e.printStackTrace(System.out);
+                return false;
+            }
+        }
+
+        MetaMessage newMsg = new MetaMessage();
+        MidiEvent newEvent = new MidiEvent(newMsg, 10);
+        log("adding new event...");
+        try {
+            if (!track.add(newEvent)) {
+                log("event hasn't been added");
+                return false;
+            }
+            log("    - OK, track size=" + track.size());
+        } catch (Exception e) {
+            log("  - FAILED: got exception");
+            e.printStackTrace(System.out);
+            return false;
+        }
+
+        return true;
+    }
+
+    public static void main(String args[]) throws Exception {
+        bug6416024 This = new bug6416024();
+        if (This.test()) {
+            log("Test passed sucessfully.");
+        } else {
+            log("Test FAILED!");
+            delay(1000);
+            throw new RuntimeException("Test failed!");
+        }
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/midi/Transmitter/bug6415669.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.midi.MidiSystem;
+import javax.sound.midi.MidiUnavailableException;
+import javax.sound.midi.Transmitter;
+
+/**
+ * @test
+ * @bug 6415669
+ * @summary Tests that terminating thread which got transmitter doesn't cause
+ *          JVM crash (windows)
+ * @run main bug6415669
+ */
+public class bug6415669 {
+
+    public static void main(String args[]) throws Exception {
+        String osStr = System.getProperty("os.name");
+        boolean isWin = osStr.toLowerCase().startsWith("windows");
+        log("OS: " + osStr);
+        log("Arch: " + System.getProperty("os.arch"));
+        if (!isWin) {
+            log("The test is for Windows only");
+            return;
+        }
+
+        bug6415669 This = new bug6415669();
+        if (This.test()) {
+            log("Test sucessfully passed.");
+        } else {
+            log("Test FAILED!");
+            throw new RuntimeException("Test FAILED!");
+        }
+    }
+
+    volatile Transmitter transmitter = null;
+    Thread openThread = null;
+    boolean test() {
+        openThread = new Thread(new Runnable() {
+            public void run() {
+                try {
+                    log("openThread: getting transmitter...");
+                    transmitter = MidiSystem.getTransmitter();
+                    log("openThread:   - OK: " + transmitter);
+                } catch (MidiUnavailableException ex) {
+                    log("openThread:   - Exception: ");
+                    ex.printStackTrace(System.out);
+                    log("openThread: skipping...");
+                }
+                log("openThread: exiting...");
+            }
+        });
+        log("starting openThread...");
+        openThread.start();
+
+        while (openThread.isAlive())
+            delay(500);
+        // make additional delay
+        delay(500);
+
+        if (transmitter == null) {
+            return true;   // midi is not available, just ignore
+        }
+
+        log("closing transmitter");
+        transmitter.close();
+        log("  - OK");
+
+        return true;
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+                + (time < 10 ? "0" : "") + time
+                + ":" + (min < 10 ? "0" : "") + min
+                + ":" + (sec < 10 ? "0" : "") + sec
+                + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+                + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/AudioFileFormatToString.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,235 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4672864
+ * @summary AudioFileFormat.toString() throws unexpected NullPointerException
+ */
+public class AudioFileFormatToString {
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+    static final int STATUS_TEMP = 95;
+
+    public static void main(String argv[]) throws Exception {
+        int testExitStatus = run(argv, System.out);
+        if (testExitStatus != STATUS_PASSED) {
+            throw new Exception("Test FAILED " + testExitStatus);
+        }
+        System.out.println("Test passed.");
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) {
+        int testResult = STATUS_PASSED;
+
+        out.println("\n==> Test for AudioFileFormat class:");
+
+        AudioFormat testAudioFormat =
+         new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,  // AudioFormat.Encoding
+                         (float) 44100.0, // float SampleRate
+                         (int) 8, // int sampleSizeInBits
+                         (int) 2, // int channels
+                         (int) 2,    // int frameSize
+                         (float) 110.0,    // float frameRate
+                         true    // boolean bigEndian
+                         );
+        AudioFormat nullAudioFormat = null;
+
+        AudioFileFormat.Type testAudioFileFormatType = AudioFileFormat.Type.WAVE;
+        AudioFileFormat.Type nullAudioFileFormatType = null;
+
+        AudioFileFormat testedAudioFileFormat = null;
+        out.println("\n>> public AudioFileFormat constructor for AudioFileFormat.Type = null: ");
+        try {
+         testedAudioFileFormat =
+             new AudioFileFormat(nullAudioFileFormatType,  // AudioFileFormat.Type
+                                 testAudioFormat, // AudioFormat
+                                 (int) 1024 // int frameLength
+                                 );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getType():");
+         try {
+             AudioFileFormat.Type producedType = testedAudioFileFormat.getType();
+             out.println(">   PASSED: producedType = " + producedType);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> public AudioFileFormat constructor for AudioFormat = null: ");
+        try {
+         testedAudioFileFormat =
+             new AudioFileFormat(testAudioFileFormatType,  // AudioFileFormat.Type
+                                 nullAudioFormat, // AudioFormat
+                                 (int) 1024 // int frameLength
+                                 );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getFormat():");
+         try {
+             AudioFormat producedFormat = testedAudioFileFormat.getFormat();
+             out.println(">   PASSED: producedFormat = " + producedFormat);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+            out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+            illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+            out.println(">   PASSED: expected NullPointerException was thrown:");
+            nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+            out.println("##  FAILED: unexpected Exception was thrown:");
+            thrown.printStackTrace(out);
+            testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> protected AudioFileFormat constructor for AudioFileFormat.Type = null: ");
+        try {
+         testedAudioFileFormat =
+             new TestAudioFileFormat(nullAudioFileFormatType,  // AudioFileFormat.Type
+                                     (int) 1024, // byteLength
+                                     testAudioFormat, // AudioFormat
+                                     (int) 1024 // int frameLength
+                                     );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getType():");
+         try {
+             AudioFileFormat.Type producedType = testedAudioFileFormat.getType();
+             out.println(">   PASSED: producedType = " + producedType);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> protected AudioFileFormat constructor for AudioFormat = null: ");
+        try {
+         testedAudioFileFormat =
+             new TestAudioFileFormat(testAudioFileFormatType,  // AudioFileFormat.Type
+                                     (int) 1024, // byteLength
+                                     nullAudioFormat, // AudioFormat
+                                     (int) 1024 // int frameLength
+                                     );
+         out.println(">  No any Exception was thrown!");
+         out.println(">  testedAudioFileFormat.getFormat():");
+         try {
+             AudioFormat producedFormat = testedAudioFileFormat.getFormat();
+             out.println(">   PASSED: producedFormat = " + producedFormat);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+         out.println(">  testedAudioFileFormat.toString():");
+         try {
+             String producedString = testedAudioFileFormat.toString();
+             out.println(">   PASSED: producedString = " + producedString);
+         } catch (Throwable thrown) {
+             out.println("##  FAILED: unexpected Exception was thrown:");
+             thrown.printStackTrace(out);
+             testResult = STATUS_FAILED;
+         }
+        } catch (IllegalArgumentException illegArgExcept) {
+         out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+         illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+         out.println(">   PASSED: expected NullPointerException was thrown:");
+         nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+         out.println("##  FAILED: unexpected Exception was thrown:");
+         thrown.printStackTrace(out);
+         testResult = STATUS_FAILED;
+        }
+
+        if (testResult == STATUS_FAILED) {
+            out.println("\n==> test FAILED!");
+        } else {
+            out.println("\n==> test PASSED!");
+        }
+        return testResult;
+    }
+}
+
+class TestAudioFileFormat extends AudioFileFormat {
+
+    TestAudioFileFormat(AudioFileFormat.Type type, int byteLength,
+                        AudioFormat format, int frameLength) {
+        super(type, byteLength, format, frameLength);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/Properties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,144 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.sound.midi.MidiFileFormat;
+import javax.sound.midi.Sequence;
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4666845
+ * @summary RFE: Add properties to AudioFileFormat and MidiFileFormat
+ */
+public class Properties {
+
+    static boolean g_failed = false;
+
+    // all of p1 need to be in p2
+    static boolean compare(Map p1, Map p2) {
+        boolean failed = false;
+        for(String key: (Set<String>) p1.keySet()) {
+            out("  testing key: "+key);
+            if (!p2.containsKey(key)) {
+                out("  missing property: '"+key+"'. Failed");
+                failed = true;
+            }
+            Object v1 = p1.get(key);
+            Object v2 = p2.get(key);
+            if (((v1 == null) && (v2 != null))
+                || ((v1 != null) && (v2 == null))
+                || !(v1.equals(v2))) {
+                out("  property '"+key+"' is different: "
+                    +"expected='"+v1+"'  "
+                    +"actual='"+v2+"'. Failed");
+                failed = true;
+            }
+        }
+        // test if we can modify p2
+        try {
+             int oldSize = p2.size();
+             p2.clear();
+             if (oldSize > 0 && p2.size() == 0) {
+                 out("  could clear the properties! Failed.");
+                 failed = true;
+             }
+        } catch (Exception e) {
+            // correct
+        }
+        return failed;
+    }
+
+    public static void main(String argv[]) throws Exception {
+        // don't need to catch exceptions: any exception is a
+        // failure of this test
+
+        Map<String, Object> p = new HashMap<String,Object>();
+        p.put("author", "Florian");
+        p.put("duration", new Long(1000));
+        p.put("MyProp", "test");
+
+        out("Testing AudioFileFormat properties:");
+        // create an AudioFileFormat with properties
+        AudioFormat format = new AudioFormat( 44100.0f, 16, 2, true, false);
+        AudioFileFormat aff =
+            new AudioFileFormat(AudioFileFormat.Type.WAVE,
+                                format, 1000, p);
+        // test that it has the properties
+        boolean failed = compare(p, aff.properties());
+        // test getProperty()
+        Object o = aff.getProperty("author");
+        if (o == null || !o.equals("Florian")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = aff.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+
+
+        out("Testing MidiFileFormat properties:");
+        // create a MidiFileFormat with properties
+        MidiFileFormat mff =
+            new MidiFileFormat(0, Sequence.PPQ, 240,
+                               1000, 100, p);
+        // test that it has the properties
+        failed = compare(p, mff.properties());
+        // test getProperty()
+        o = mff.getProperty("author");
+        if (o == null || !o.equals("Florian")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = mff.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+
+        if (g_failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFileFormat/TypeEquals.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFileFormat;
+
+/**
+ * @test
+ * @bug 4925483
+ * @summary RFE: equals() should compare string in Encoding and Type
+ */
+public class TypeEquals {
+
+    public static void main(String argv[]) throws Exception {
+        // first test that we can create our own type
+        // (the constructor was made public)
+        AudioFileFormat.Type myType = new AudioFileFormat.Type("WAVE", "wav");
+
+        // then check if this one equals this new one
+        // with the static instance in AudioFileFormat.Type
+        if (!myType.equals(AudioFileFormat.Type.WAVE)) {
+         throw new Exception("Types do not equal!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/AudioFormatBitSize.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 4754759
+ * @summary AudioFormat does not handle uncommon bit sizes correctly
+ */
+
+import javax.sound.sampled.AudioFormat;
+
+public class AudioFormatBitSize {
+
+    public static void main(String[] args) throws Exception {
+        int bits = 18;
+        AudioFormat format = new AudioFormat(44100.0f, bits, 1, true, false);
+        if (format.getFrameSize() * 8 < bits) {
+            System.out.println("bits = "+bits+" do not fit into a "+format.getFrameSize()+" bytes sample!");
+            throw new Exception("Test failed");
+        } else
+            System.out.println("bits = "+bits+" fit OK into a "+format.getFrameSize()+" bytes sample!");
+            System.out.println("Test passed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/EncodingEquals.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4925483
+ * @summary RFE: equals() should compare string in Encoding and Type
+ */
+public class EncodingEquals {
+
+    public static void main(String argv[]) throws Exception {
+         // first test that we can create our own encoding
+         // (the constructor was made public)
+         AudioFormat.Encoding myType = new AudioFormat.Encoding("PCM_SIGNED");
+
+         // then check if this one equals this new one
+         // with the static instance in AudioFormat.Encoding
+         if (!myType.equals(AudioFormat.Encoding.PCM_SIGNED)) {
+             throw new Exception("Encodings do not equal!");
+         }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioFormat/Properties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.sound.sampled.AudioFormat;
+
+/**
+ * @test
+ * @bug 4925767
+ * @summary RFE: Add Properties to AudioFormat
+ */
+public class Properties {
+
+    static boolean g_failed = false;
+
+    // all of p1 need to be in p2
+    static boolean compare(Map p1, Map p2) {
+        boolean failed = false;
+        for(String key: (Set<String>) p1.keySet()) {
+            out("  testing key: "+key);
+            if (!p2.containsKey(key)) {
+                out("  missing property: '"+key+"'. Failed");
+                failed = true;
+            }
+            Object v1 = p1.get(key);
+            Object v2 = p2.get(key);
+            if (((v1 == null) && (v2 != null))
+                || ((v1 != null) && (v2 == null))
+                || !(v1.equals(v2))) {
+                out("  property '"+key+"' is different: "
+                    +"expected='"+v1+"'  "
+                    +"actual='"+v2+"'. Failed");
+                failed = true;
+            }
+        }
+        // test if we can modify p2
+        try {
+             int oldSize = p2.size();
+             p2.clear();
+             if (oldSize > 0 && p2.size() == 0) {
+                 out("  could clear the properties! Failed.");
+                 failed = true;
+             }
+        } catch (Exception e) {
+            // correct
+        }
+        return failed;
+    }
+
+
+    public static void main(String argv[]) throws Exception {
+        // don't need to catch exceptions: any exception is a
+        // failure of this test
+
+        Map<String, Object> p = new HashMap<String,Object>();
+        p.put("bitrate", new Integer(128));
+        p.put("quality", new Integer(10));
+        p.put("MyProp", "test");
+
+        out("Testing AudioFileFormat properties:");
+        // create an AudioFileFormat with properties
+        AudioFormat format =
+            new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
+                            44100.0f, 16, 2, 4, 44100.0f, false, p);
+        // test that it has the properties
+        boolean failed = compare(p, format.properties());
+        // test getProperty()
+        Object o = format.getProperty("MyProp");
+        if (o == null || !o.equals("test")) {
+            out("  getProperty did not report an existing property!");
+            failed = true;
+        }
+        o = format.getProperty("does not exist");
+        if (o != null) {
+            out("  getProperty returned something for a non-existing property!");
+            failed = true;
+        }
+        if (!failed) {
+            out("  OK");
+        } else {
+            g_failed = true;
+        }
+
+        if (g_failed) throw new Exception("Test FAILED!");
+        System.out.println("Test passed.");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioInputStream/AISReadFraction.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,237 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4948663
+ * @summary AudioInputStream does not use the original stream passed to its constructor
+ */
+public class AISReadFraction {
+
+    static int failed = 0;
+    static byte[] testData = new byte[256];
+    static boolean DEBUG = false;
+
+    static AudioFormat[] formats = {
+        new AudioFormat(44100.0f, 8, 1, false, false), // frameSize = 1
+        new AudioFormat(44100.0f, 8, 2, false, false), // frameSize = 2
+        new AudioFormat(44100.0f, 16, 1, true, false), // frameSize = 2
+        new AudioFormat(44100.0f, 24, 1, true, false), // frameSize = 3
+        new AudioFormat(44100.0f, 16, 2, true, false), // frameSize = 4
+        new AudioFormat(44100.0f, 8, 5, false, false), // frameSize = 5
+        new AudioFormat(44100.0f, 16, 3, true, false), // frameSize = 6
+        new AudioFormat(44100.0f, 8, 7, false, false), // frameSize = 7
+        new AudioFormat(44100.0f, 32, 2, true, false)  // frameSize = 8
+    };
+
+
+    public static void main(String args[]) throws Exception {
+        for (int i = 0; i<testData.length; i++) {
+                testData[i] = (byte) (i % 128);
+        }
+
+        for (int f = 0; f < formats.length; f++) {
+                // first test without marking
+                doTest(formats[f], false);
+                // then with marking
+                doTest(formats[f], true);
+        }
+
+        out(""+failed+" failures.");
+        if (failed>0) throw new Exception("Test FAILED!");
+        out("Test passed.");
+    }
+
+    static void doTest(AudioFormat format, boolean doMark) {
+        out("Test with"+(doMark?"":"out")+" marking. Audio format: "
+            +"sampleSize="+format.getSampleSizeInBits()+"bits "
+            +"channels="+format.getChannels()+" "
+            +"frameSize="+format.getFrameSize()+"byte(s)");
+        int maxReadBytes = (testData.length / format.getFrameSize()) * format.getFrameSize();
+        InputStream is = new FractionalIS(testData, doMark);
+        AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED);
+        // first some general tests
+        if (ais.markSupported() && !doMark) {
+                out("  #AIS reports markSupported, but underlying stream cannot! FAILED");
+                failed ++;
+        }
+        if (!ais.markSupported() && doMark) {
+                out("  #AIS does not report markSupported, but underlying stream can mark! FAILED");
+                failed++;
+        }
+        byte[] data = new byte[1000];
+        int frameSize = format.getFrameSize();
+        int counter = 5;
+        int totalReadBytes = 0;
+        boolean hasRead0 = false;
+        boolean hasMarked = false;
+        boolean hasReset = false;
+        int markPos = 0;
+        while (true) {
+            try {
+                int toBeRead = frameSize * counter;
+                counter += 3;
+                if (counter > 14) {
+                        counter -= 14;
+                }
+                int read = ais.read(data, 0, toBeRead);
+                if (DEBUG) out("  -> ais.read(data, 0, "+toBeRead+"): "+read+"  (frameSize="+frameSize+")");
+                if ((totalReadBytes == maxReadBytes) && (read != -1)
+                     && ((read > 0) || hasRead0)) {
+                        if (read == 0) {
+                            out("  #stream was read to the end ("+maxReadBytes+"), but ais.read returned repeatedly 0 bytes. FAILED");
+                        } else {
+                            out("  #stream was read to the end ("+maxReadBytes+"), but ais.read returned "+read+" bytes... FAILED");
+                        }
+                        failed++;
+                        break;
+                }
+                if (read > 0) {
+                        verifyReadBytes(data, totalReadBytes, read);
+                        if ((read % frameSize) != 0) {
+                                out("  #Read non-integral number of frames: "+read+" bytes, frameSize="+frameSize+" bytes. FAILED");
+                                failed++;
+                        }
+                        totalReadBytes += read;
+                        hasRead0 = false;
+                }
+                else if (read == 0) {
+                        //out("  wanted to read "+toBeRead+" at position "+totalReadBytes+", but got 0 bytes!");
+                        if (hasRead0) {
+                                out("  read 0 twice in a row! FAILED");
+                                failed++;
+                                break;
+                        }
+                        hasRead0 = true;
+                } else {
+                        // end of stream
+                        out("  End of stream reached. Total read bytes: "+totalReadBytes);
+                        if (totalReadBytes != maxReadBytes) {
+                                out("  #Failed: should have read "+maxReadBytes+" bytes! FAILED.");
+                                failed++;
+                        }
+                        break;
+                }
+
+                // test marking
+                if (totalReadBytes > 50 && !hasMarked && !hasReset && doMark) {
+                        out("  Marking at position "+totalReadBytes);
+                        hasMarked = true;
+                        ais.mark(0);
+                        markPos = totalReadBytes;
+                }
+                if (totalReadBytes > 100 && hasMarked && !hasReset && doMark) {
+                        out("  Resetting at position "+totalReadBytes+" back to "+markPos);
+                        hasReset = true;
+                        ais.reset();
+                        totalReadBytes = markPos;
+                }
+
+            } catch (IOException e) {
+                out("  #caught unexpected exception:");
+                e.printStackTrace();
+                failed++;
+            }
+        }
+    }
+
+    static void verifyReadBytes(byte[] data, int offset, int len) {
+        int firstWrongByte = -1;
+        for (int i = 0; i < len; i++) {
+                int expected = ((offset + i) % 128);
+                if (data[i] != expected) {
+                        out("  read data is not correct! offset="+offset+"  expected="+expected+"  actual="+data[i]);
+                        failed++;
+                        break;
+                }
+        }
+    }
+
+
+    public static void out(String s) {
+        System.out.println(s);
+    }
+
+
+    static class FractionalIS extends InputStream {
+        byte[] data;
+        int pos = 0;
+        boolean canMark;
+        // a counter how many bytes are not returned
+        int missingBytes = 0;
+        int markPos = -1;
+
+        FractionalIS(byte[] data, boolean canMark) {
+                this.data = data;
+                this.canMark = canMark;
+        }
+
+        public int read() throws IOException {
+                if (pos >= data.length) {
+                        return -1;
+                }
+                return data[pos++] & 0xFF;
+        }
+
+        public int read(byte[] b, int off, int len) throws IOException {
+                if (++missingBytes > 5) {
+                        missingBytes = 0;
+                }
+                int reducedLen = len - missingBytes;
+                if (reducedLen <= 0) reducedLen = 1;
+                if (DEBUG) out("  FIS.read(data, 0, "+len+"): reducing len to "+reducedLen+" bytes.");
+                int ret = super.read(b, off, reducedLen);
+                if (DEBUG) out("                              returning "+ret+" bytes. Now at pos="+pos);
+                return ret;
+        }
+
+        public void mark(int readlimit) {
+                markPos = pos;
+                if (DEBUG) out("  FIS.mark(): marking at "+pos);
+        }
+
+        public void reset() throws IOException {
+                if (!canMark) {
+                        throw new IOException("reset not supported!");
+                }
+                if (markPos == -1) {
+                        throw new IOException("Mark position not set!");
+                }
+                pos = markPos;
+                if (DEBUG) out("  FIS.reset(): now back at "+pos);
+        }
+
+        public boolean markSupported() {
+                return canMark;
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioInputStream/bug6188860.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 6188860
+ * @summary Tests that method AudioInputStream.read() returns right value
+ */
+public class bug6188860 {
+
+    public static void main(String[] args) throws Exception {
+        byte[] testData = new byte[256];
+
+        // fill data
+        for (int i = 0; i < testData.length; i++)
+            testData[i] = (byte) (i % 128);
+
+        InputStream streamSrc = new TestInputStream(testData);
+        AudioFormat format = new AudioFormat(44100.0f, 8, 1, false, false); // frameSize = 1
+        AudioInputStream streamAudio = new AudioInputStream(streamSrc, format, AudioSystem.NOT_SPECIFIED);
+
+        int nErrCount = 0;
+        int nTotal = 0;
+
+        int dataSrc, dataRead;
+        while (nTotal < (testData.length - 1)) {
+            dataRead = streamAudio.read();
+            if (dataRead < 0) {
+                System.out.println("end of stream");
+                break;
+            }
+
+            dataSrc = testData[nTotal];
+
+            if (dataRead != dataSrc) {
+                System.out.println("" + nTotal + " - mismatch :" + dataRead + " <> " + dataSrc);
+                nErrCount++;
+            }
+            nTotal++;
+        }
+
+        System.out.println("Total: " + nTotal + "; Mismatches: " + nErrCount);
+
+        if (nErrCount > 0) {
+            throw new RuntimeException("test failed: " + nErrCount + " mismatches of total " + nTotal + " bytes.");
+        }
+        System.out.println("Test sucessfully passed.");
+    }
+
+
+    static class TestInputStream extends InputStream {
+        byte[] data;
+        int pos = 0;
+
+        TestInputStream(byte[] data) {
+            this.data = data;
+        }
+
+        public int read() throws IOException {
+            if (pos >= data.length) {
+                return -1;
+            }
+            return data[pos++] & 0xFF;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/AudioFileTypeUniqueness.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,52 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4883060
+ * @summary AudioSystem.getAudioFileTypes returns duplicates
+ */
+public class AudioFileTypeUniqueness {
+
+    public static void main(String[] args) throws Exception {
+        boolean foundDuplicates = false;
+        AudioFileFormat.Type[]  aTypes = AudioSystem.getAudioFileTypes();
+        for (int i = 0; i < aTypes.length; i++)
+        {
+            for (int j = 0; j < aTypes.length; j++)
+            {
+                if (aTypes[i].equals(aTypes[j]) && i != j) {
+                    foundDuplicates = true;
+                }
+            }
+        }
+        if (foundDuplicates) {
+            throw new Exception("Test failed");
+        } else {
+            System.out.println("Test passed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/AudioFileTypes/ShowAudioFileTypes.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4303037
+ * @summary Shows the existing audio file types of AudioSystem and checks
+ *          whether there are some at all
+ */
+public class ShowAudioFileTypes {
+
+    public static void main(String[] args) throws Exception {
+        AudioFileFormat.Type[]  aTypes = AudioSystem.getAudioFileTypes();
+        System.out.println(aTypes.length+" supported target types:");
+        for (int i = 0; i < aTypes.length; i++)
+        {
+            System.out.println("  "+(i+1)+". " + aTypes[i]+" with ext. '"+aTypes[i].getExtension()+"'");
+        }
+        if (aTypes.length<3) {
+            throw new Exception("Test failed");
+        } else {
+            System.out.println("Test passed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/DefaultMixers.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,198 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.Port;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+import javax.sound.sampled.spi.MixerProvider;
+
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the retrieving of lines
+ *          with defaut mixer properties.
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class DefaultMixers {
+
+    private static final String ERROR_PROVIDER_CLASS_NAME = "abc";
+    private static final String ERROR_INSTANCE_NAME = "def";
+
+    private static final Class[] lineClasses = {
+        SourceDataLine.class,
+        TargetDataLine.class,
+        Clip.class,
+        Port.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        Mixer.Info[] infos;
+
+        out("Testing Mixers retrieved via AudioSystem");
+        infos = AudioSystem.getMixerInfo();
+        allOk &= testMixers(infos, null);
+
+        out("Testing MixerProviders");
+        List providers = JDK13Services.getProviders(MixerProvider.class);
+        for (int i = 0; i < providers.size(); i++) {
+            MixerProvider provider = (MixerProvider) providers.get(i);
+            infos = provider.getMixerInfo();
+            allOk &= testMixers(infos, provider.getClass().getName());
+        }
+
+        if (! allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static boolean testMixers(Mixer.Info[] infos,
+                                      String providerClassName) {
+        boolean allOk = true;
+
+        for (int i = 0; i < infos.length; i++) {
+            Mixer mixer = null;
+            try {
+                mixer = AudioSystem.getMixer(infos[i]);
+            } catch (NullPointerException e) {
+                out("Exception thrown; Test NOT failed.");
+                e.printStackTrace();
+            }
+            for (int j = 0; j < lineClasses.length; j++) {
+                if (mixer.isLineSupported(new Line.Info(lineClasses[j]))) {
+                    allOk &= testMixer(mixer, lineClasses[j],
+                                       providerClassName);
+                }
+            }
+        }
+        return allOk;
+    }
+
+    private static boolean testMixer(Mixer mixer, Class lineType,
+                                      String providerClassName) {
+        boolean allOk = true;
+        String instanceName = mixer.getMixerInfo().getName();
+
+        // no error
+        allOk &= testMixer(mixer, lineType,
+                           providerClassName, instanceName);
+
+        // erroneous provider class name, correct instance name
+        allOk &= testMixer(mixer, lineType,
+                           ERROR_PROVIDER_CLASS_NAME, instanceName);
+
+        // erroneous provider class name, no instance name
+        allOk &= testMixer(mixer, lineType,
+                           ERROR_PROVIDER_CLASS_NAME, "");
+
+        // erroneous provider class name, erroneous instance name
+        allOk &= testMixer(mixer, lineType,
+                           ERROR_PROVIDER_CLASS_NAME, ERROR_INSTANCE_NAME);
+
+        return allOk;
+    }
+
+    private static boolean testMixer(Mixer mixer, Class lineType,
+                                     String providerClassName,
+                                     String instanceName) {
+        boolean allOk = true;
+
+        try {
+            String propertyValue = (providerClassName != null) ? providerClassName: "" ;
+            propertyValue += "#" + instanceName;
+            out("property value: " + propertyValue);
+            System.setProperty(lineType.getName(), propertyValue);
+            Line line = null;
+            Line.Info info = null;
+            Line.Info[] infos;
+            AudioFormat format = null;
+            if (lineType == SourceDataLine.class || lineType == Clip.class) {
+                infos = mixer.getSourceLineInfo();
+                format = getFirstLinearFormat(infos);
+                info = new DataLine.Info(lineType, format);
+            } else if (lineType == TargetDataLine.class) {
+                infos = mixer.getTargetLineInfo();
+                format = getFirstLinearFormat(infos);
+                info = new DataLine.Info(lineType, format);
+            } else if (lineType == Port.class) {
+                /* Actually, a Ports Mixer commonly has source infos
+                   as well as target infos. We ignore this here, since we
+                   just need a random one. */
+                infos = mixer.getSourceLineInfo();
+                for (int i = 0; i < infos.length; i++) {
+                    if (infos[i] instanceof Port.Info) {
+                        info = infos[i];
+                        break;
+                    }
+                }
+            }
+            out("Line.Info: " + info);
+            line = AudioSystem.getLine(info);
+            out("line: " + line);
+            if (! lineType.isInstance(line)) {
+                out("type " + lineType + " failed: class should be '" +
+                    lineType + "' but is '" + line.getClass() + "'!");
+                allOk = false;
+            }
+        } catch (Exception e) {
+            out("Exception thrown; Test NOT failed.");
+            e.printStackTrace();
+        }
+        return allOk;
+    }
+
+    private static AudioFormat getFirstLinearFormat(Line.Info[] infos) {
+        for (int i = 0; i < infos.length; i++) {
+            if (infos[i] instanceof DataLine.Info) {
+                AudioFormat[] formats = ((DataLine.Info) infos[i]).getFormats();
+                for (int j = 0; j < formats.length; j++) {
+                    AudioFormat.Encoding encoding = formats[j].getEncoding();
+                    int sampleSizeInBits = formats[j].getSampleSizeInBits();
+                    if (encoding.equals(AudioFormat.Encoding.PCM_SIGNED) &&
+                        sampleSizeInBits == 16 ||
+                        encoding.equals(AudioFormat.Encoding.PCM_UNSIGNED) &&
+                        sampleSizeInBits == 16) {
+                        return formats[j];
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/DefaultProperties.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,164 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @build DefaultProperties
+ * @run main/othervm DefaultProperties
+ * @summary RFE: Setting the default MixerProvider. Test the retrieving and
+ *          parsing of properties.
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class DefaultProperties {
+
+    private static final Class[] lineTypeClasses = {
+        javax.sound.sampled.SourceDataLine.class,
+        javax.sound.sampled.TargetDataLine.class,
+        javax.sound.sampled.Clip.class,
+        javax.sound.sampled.Port.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allOk = true;
+        File file = new File(System.getProperty("test.src", "."), "testdata");
+        System.setProperty("java.home", file.getCanonicalPath());
+
+        for (int i = 0; i < lineTypeClasses.length; i++) {
+            Class cls = lineTypeClasses[i];
+            String propertyName = cls.getName();
+            String result;
+            String provClassName;
+            String instanceName;
+
+            // properties file, both provider class name and instance name
+            provClassName = "xyz";
+            instanceName = "123";
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, no trailing hash
+            provClassName = "abc";
+            System.setProperty(propertyName, provClassName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, provider class name only, trailing hash
+            provClassName = "def";
+            System.setProperty(propertyName, provClassName + "#");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, instance name only
+            instanceName = "ghi";
+            System.setProperty(propertyName, "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, both provider class and instance name
+            provClassName = "jkl";
+            instanceName = "mno";
+            System.setProperty(propertyName, provClassName + "#" + instanceName);
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (! provClassName.equals(result)) {
+                out("type " + cls + " failed: provider class should be '" +
+                    provClassName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (! instanceName.equals(result)) {
+                out("type " + cls + " failed: instance name should be '" +
+                    instanceName + "' but is '" + result + "'!");
+                allOk = false;
+            }
+
+            // system property, empty
+            System.setProperty(propertyName, "");
+            result = JDK13Services.getDefaultProviderClassName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: provider class should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+            result = JDK13Services.getDefaultInstanceName(cls);
+            if (result != null) {
+                out("type " + cls + " failed: instance name should be " +
+                    "null but is '" + result + "'!");
+                allOk = false;
+            }
+        }
+        if (! allOk) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/ProviderCacheing.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,64 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+import com.sun.media.sound.JDK13Services;
+
+/**
+ * @test
+ * @bug 4776511
+ * @summary RFE: Setting the default MixerProvider. Test the cacheing of
+ *          providers.
+ * @modules java.desktop/com.sun.media.sound
+ */
+public class ProviderCacheing {
+
+    private static final Class[] providerClasses = {
+        javax.sound.sampled.spi.AudioFileReader.class,
+        javax.sound.sampled.spi.AudioFileWriter.class,
+        javax.sound.sampled.spi.FormatConversionProvider.class,
+        javax.sound.sampled.spi.MixerProvider.class,
+    };
+
+    public static void main(String[] args) throws Exception {
+        boolean allCached = true;
+        for (int i = 0; i < providerClasses.length; i++) {
+            List list0 = JDK13Services.getProviders(providerClasses[i]);
+            List list1 = JDK13Services.getProviders(providerClasses[i]);
+            if (list0 == list1) {
+                out("Providers should not be cached for " + providerClasses[i]);
+                allCached = false;
+            }
+        }
+
+        if (! allCached) {
+            throw new Exception("Test failed");
+        } else {
+            out("Test passed");
+        }
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/AudioSystem/testdata/conf/sound.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,27 @@
+#
+# 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
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+javax.sound.sampled.SourceDataLine=xyz#123
+javax.sound.sampled.TargetDataLine=xyz#123
+javax.sound.sampled.Clip=xyz#123
+javax.sound.sampled.Port=xyz#123
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/ClipCloseLoss.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,163 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4946913
+ * @summary DirectClip doesn't kill the thread correctly, sometimes
+ * @run main/othervm ClipCloseLoss
+ * @key headful
+ */
+public class ClipCloseLoss {
+    static int frameCount = 441000; // lets say 10 seconds
+    static AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);
+    static ByteArrayInputStream bais =
+    new ByteArrayInputStream(new byte[frameCount * format.getFrameSize()]);
+
+    static int success = 0;
+    static boolean failed = false;
+
+    public static void run(Mixer m) {
+        Clip clip = null;
+        try {
+            if (m == null) {
+                out("Using default mixer");
+                clip = (Clip) AudioSystem.getClip();
+            } else {
+                out("Using mixer: "+m);
+                DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED);
+                clip = (Clip) m.getLine(info);
+            }
+            out(" got clip: "+clip);
+            if (!clip.getClass().toString().contains("Direct")) {
+                out(" no direct audio clip -> do not test.");
+                return;
+            }
+
+            out(" open");
+            bais.reset();
+            clip.open(new AudioInputStream(bais, format, frameCount));
+
+            out(" clip.close()");
+            //long t = System.currentTimeMillis();
+            clip.close();
+            //if (System.currentTimeMillis() - t > 1950) {
+            //  out(" clip.close needed more than 2 seconds! Causes failure of this test.");
+            //  failed = true;
+            //}
+            out(" clip closed");
+            success++;
+        } catch (LineUnavailableException luae) {
+            // line not available, test not failed
+            System.err.println(luae);
+        } catch (IllegalArgumentException iae) {
+            // line not available, test not failed
+            System.err.println(iae);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+    }
+
+    public static int getClipThreadCount() {
+        int ret = 0;
+        ThreadGroup tg = Thread.currentThread().getThreadGroup();
+        while (tg.getParent() != null) { tg = tg.getParent(); }
+        Thread[] threads = new Thread[500];
+        int count = tg.enumerate(threads, true);
+        for (int i = 0; i < count; i++) {
+                if (threads[i].getName().contains("Direct")
+                    && threads[i].getName().contains("Clip")) {
+                        out("Found Direct Clip thread object: "+threads[i]);
+                        ret++;
+                }
+        }
+        return ret;
+    }
+
+    public static void main(String[] args) throws Exception    {
+        if (isSoundcardInstalled()) {
+            bais.mark(0);
+            run(null);
+            Mixer.Info[] infos = AudioSystem.getMixerInfo();
+            for (int i = 0; i<infos.length; i++) {
+                try {
+                    Mixer m = AudioSystem.getMixer(infos[i]);
+                    run(m);
+                } catch (Exception e) {
+                }
+            }
+            out("Waiting 1 second to dispose of all threads");
+            Thread.sleep(1000);
+            if (getClipThreadCount() > 0) {
+                out("Unused clip threads exist! Causes test failure");
+                failed = true;
+            }
+            if (failed) throw new Exception("Test FAILED!");
+            if (success > 0) {
+                out("Test passed.");
+            } else {
+                System.err.println("Test could not execute: please install an audio device");
+            }
+        }
+    }
+
+    /**
+    * Returns true if at least one soundcard is correctly installed
+    * on the system.
+    */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+
+    public static void out(String s) {
+        /*long t = System.nanoTime() / 1000000l;
+        String ts = ""+(t % 1000);
+        while (ts.length() < 3) ts = "0"+ts;
+        System.out.println(""+(t/1000)+":"+ts+" "+s);
+        System.out.flush();*/
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/ClipFlushCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,226 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4946945
+ * @summary Crash in javasound while running TicTacToe demo applet tiger b26
+ */
+public class ClipFlushCrash {
+    static int frameCount = 441000; // lets say 10 seconds
+    static AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);
+    static ByteArrayInputStream bais =
+      new ByteArrayInputStream(new byte[frameCount * format.getFrameSize()]);
+
+    static int success = 0;
+
+    public static void run(Mixer m) {
+        Clip clip = null;
+        try {
+            if (m == null) {
+                out("Using default mixer");
+                clip = (Clip) AudioSystem.getClip();
+            } else {
+                out("Using mixer: "+m);
+                DataLine.Info info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED);
+                clip = (Clip) m.getLine(info);
+            }
+            out(" got clip: "+clip);
+            if (!clip.getClass().toString().contains("Direct")) {
+                out(" no direct audio clip -> do not test.");
+                return;
+            }
+
+            out(" open");
+            bais.reset();
+            clip.open(new AudioInputStream(bais, format, frameCount));
+
+            AT at1 = new AT(clip, "flush thread", 123) {
+                public void doAction() throws Exception {
+                        log("flush");
+                        clip.flush();
+                }
+            };
+            AT at2 = new AT(clip, "setFramePosition thread", 67) {
+                public void doAction() throws Exception {
+                        int pos = (int) (Math.random() * clip.getFrameLength());
+                        log("setPosition to frame "+pos);
+                        clip.setFramePosition(pos);
+                }
+            };
+            AT at3 = new AT(clip, "start/stop thread", 300) {
+                public void doAction() throws Exception {
+                        if (clip.isRunning()) {
+                                log("stop");
+                                clip.stop();
+                        } else {
+                                log("start");
+                                clip.setFramePosition(0);
+                                clip.start();
+                        }
+                }
+            };
+            AT at4 = new AT(clip, "open/close thread", 600) {
+                public synchronized void doAction() throws Exception {
+                        log("close");
+                        clip.close();
+                        wait(50);
+                        if (!terminated) {
+                                log("open");
+                                bais.reset();
+                                clip.open(new AudioInputStream(bais, format, frameCount));
+                        }
+                }
+            };
+
+            out(" clip.start");
+            clip.start();
+            out(" for 10 seconds, call start/stop, setFramePosition, and flush from other threads");
+            at1.start();
+            at2.start();
+            at3.start();
+            at4.start();
+            try {
+                Thread.sleep(10000);
+            } catch (InterruptedException ie) {}
+            out(" finished.");
+                at1.terminate();
+                at2.terminate();
+                at3.terminate();
+                at4.terminate();
+            out(" clip.close()");
+            clip.close();
+            success++;
+        } catch (LineUnavailableException luae) {
+            // line not available, test not failed
+            System.err.println(luae);
+        } catch (IllegalArgumentException iae) {
+            // line not available, test not failed
+            System.err.println(iae);
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+    }
+
+    public static void main(String[] args) throws Exception     {
+        if (isSoundcardInstalled()) {
+                bais.mark(0);
+            run(null);
+            Mixer.Info[] infos = AudioSystem.getMixerInfo();
+            for (int i = 0; i<infos.length; i++) {
+                try {
+                        Mixer m = AudioSystem.getMixer(infos[i]);
+                        run(m);
+                } catch (Exception e) {
+                }
+            }
+            if (success > 0) {
+                out("No crash -> Test passed");
+            } else {
+                System.err.println("Test could not execute: please install an audio device");
+            }
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+
+    public static void out(String s) {
+        /*long t = System.nanoTime() / 1000000l;
+        String ts = ""+(t % 1000);
+        while (ts.length() < 3) ts = "0"+ts;
+        System.out.println(""+(t/1000)+":"+ts+" "+s);
+        System.out.flush();*/
+        System.out.println(s);
+    }
+
+    private abstract static class AT extends Thread {
+        protected boolean terminated = false;
+        protected Clip clip;
+        private int waitTime;
+
+        public AT(Clip clip, String name, int waitTime) {
+                super(name);
+                this.clip = clip;
+                this.waitTime = waitTime;
+        }
+
+        public abstract void doAction() throws Exception;
+
+                public void run() {
+                        log("start");
+                        while (!terminated) {
+                                try {
+                                        synchronized(this) {
+                                            wait(waitTime);
+                                        }
+                                        if (!terminated) {
+                                                doAction();
+                                        }
+                                } catch(Exception e) {
+                                        log("exception: "+e);
+                                }
+                        }
+                        log("exit");
+                }
+
+                public synchronized void terminate() {
+                        log("terminate");
+                        terminated = true;
+                        notifyAll();
+                }
+
+        protected void log(String s) {
+            //out("   "+Thread.currentThread().getId()+" "+getName()+": "+s);
+            out("   "+getName()+": "+s);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/Drain/ClipDrain.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,126 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4732218
+ * @summary Clip.drain does not actually block until all I/O is complete as
+ *          documented.
+ */
+public class ClipDrain {
+    static int successfulTests = 0;
+    static AudioFormat format = new AudioFormat(8000, 16, 1, true, false);
+    // create a 10-second file
+    static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 10)];
+
+    static int TOLERANCE_MS = 2500; // how many milliseconds too short is tolerated...
+
+    private static void doMixerClip(Mixer mixer) throws Exception {
+        boolean waitedEnough=false;
+        try {
+            DataLine.Info info = new DataLine.Info(Clip.class, format);
+            Clip clip = (Clip) mixer.getLine(info);
+            clip.open(format, soundData, 0, soundData.length);
+
+            // sanity
+            if (clip.getMicrosecondLength()/1000 < 9900) {
+                throw new Exception("clip's microsecond length should be at least 9900000, but it is "+clip.getMicrosecondLength());
+            }
+            long start = System.currentTimeMillis();
+
+            System.out.println(" ---------- start --------");
+            clip.start();
+            // give time to actually start it. ALSA implementation needs that...
+            Thread.sleep(300);
+            System.out.println("drain ... ");
+            clip.drain();
+            long elapsedTime = System.currentTimeMillis() - start;
+            System.out.println("close ... ");
+            clip.close();
+            System.out.println("... done");
+            System.out.println("Playback duration: "+elapsedTime+" milliseconds.");
+            waitedEnough = elapsedTime >= ((clip.getMicrosecondLength() / 1000) - TOLERANCE_MS);
+        } catch (Throwable t) {
+                System.out.println("  - Caught exception. Not failed.");
+                System.out.println("  - "+t.toString());
+                return;
+        }
+        if (!waitedEnough) {
+            throw new Exception("Drain did not wait long enough to play entire clip.");
+        }
+        successfulTests++;
+    }
+
+
+    private static void doAll() throws Exception {
+        Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+        for (int i=0; i<mixers.length; i++) {
+            Mixer mixer = AudioSystem.getMixer(mixers[i]);
+            System.out.println("--------------");
+            System.out.println("Testing mixer: "+mixers[i]);
+            doMixerClip(mixer);
+        }
+        if (mixers.length==0) {
+            System.out.println("No mixers available!");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+        doAll();
+        if (successfulTests==0) {
+            System.out.println("Could not execute any of the tests. Test NOT failed.");
+        } else {
+            System.out.println("Test PASSED.");
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/Duration/ClipDuration.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4237703
+ * @summary Check that Clip.getMicrosecondLength() returns correct value.
+ */
+public class ClipDuration {
+
+    public static int run(Mixer m) {
+        int res=1; // failed
+        int frameCount = 441000; // lets say 10 seconds
+        AudioFormat f = new AudioFormat(44100.0f, 16, 2, true, false);
+        AudioInputStream audioInputStream =
+            new AudioInputStream(new ByteArrayInputStream(new byte[frameCount * f.getFrameSize()]),
+                                 f, frameCount);
+        AudioFormat     format = audioInputStream.getFormat();
+        Clip m_clip = null;
+        try {
+            if (m == null) {
+                m_clip = (Clip) AudioSystem.getClip();
+            } else {
+                DataLine.Info   info = new DataLine.Info(Clip.class, format, AudioSystem.NOT_SPECIFIED);
+                m_clip = (Clip) m.getLine(info);
+            }
+            System.out.println("Got clip: "+m_clip);
+            m_clip.open(audioInputStream);
+            long microseconds=m_clip.getMicrosecondLength();
+            System.out.println("getFrameLength()="+m_clip.getFrameLength()+" frames");
+            System.out.println("getMicrosecondLength()="+microseconds+" us");
+            if (Math.abs(microseconds-10000000)<50) {
+                System.out.println("->Clip OK");
+                res=0; // passes if less than 50us error
+            }
+        } catch (LineUnavailableException luae) {
+            System.err.println(luae);
+            res = 3; // line not available, test not failed
+        } catch (Throwable t) {
+            System.out.println("->Exception:"+t);
+            t.printStackTrace();
+            res=2; // exception
+        }
+        if (m_clip != null) {
+            m_clip.close();
+        }
+        return res;
+    }
+
+
+
+    public static void main(String[] args) throws Exception     {
+        if (isSoundcardInstalled()) {
+            int res=3;
+            res = run(null);
+            Mixer.Info[] infos = AudioSystem.getMixerInfo();
+            for (int i = 0; i<infos.length; i++) {
+                try {
+                        Mixer m = AudioSystem.getMixer(infos[i]);
+                        int r = run(m);
+                        if (r == 1) res = 1;
+                } catch (Exception e) {
+                }
+            }
+            if (res!=1) {
+                System.out.println("Test passed");
+            } else {
+                if (res==2) {
+                    System.err.println("Test could not execute: test threw unexpected Exception.");
+                    throw new Exception("Test threw exception");
+                }
+                else if (res==3) {
+                    System.err.println("Test could not execute: please install an audio device");
+                    return;
+                }
+                throw new Exception("Test returned wrong length");
+            }
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/Endpoint/ClipSetEndPoint.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4385928
+ * @summary Verify that an endpoint -1 in Clip does not throw an exception
+ */
+//public class test048 extends TRTest
+public class ClipSetEndPoint {
+
+    private Clip theClip;
+
+    boolean testPassed = true;
+
+    //_______________________________________________
+    //      Method: runTest
+    //_______________________________________________
+    public boolean runTest() {
+        AudioInputStream theAudioInputStream = new AudioInputStream(
+                new ByteArrayInputStream(new byte[2000]),
+                new AudioFormat(8000.0f, 8, 1, false, false), 2000); //
+
+        AudioFormat theAudioFormat = theAudioInputStream.getFormat();
+
+        DataLine.Info info = new DataLine.Info(Clip.class, theAudioFormat,
+                                               AudioSystem.NOT_SPECIFIED);
+        try {
+            theClip = (Clip) AudioSystem.getLine(info);
+            theClip.open(theAudioInputStream);
+
+            int theStartLoopPoint = 0;
+            int theEndLoopPoint = -1;       //      -1 signifies the last frame
+
+            theClip.setLoopPoints(theStartLoopPoint, theEndLoopPoint);
+            //theClip.start();
+        } catch (LineUnavailableException e) {
+            e.printStackTrace();
+            testPassed = true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            testPassed = false;
+        }
+        return testPassed;
+    }
+
+    //_______________________________________________
+    //      Method: main
+    //_______________________________________________
+    public static void main(String[] args) throws Exception {
+        if (isSoundcardInstalled()) {
+            ClipSetEndPoint thisTest = new ClipSetEndPoint();
+            boolean testResult = thisTest.runTest();
+            if (testResult) {
+                System.out.println("Test passed");
+            } else {
+                System.out.println("Test failed");
+                throw new Exception("Test failed");
+            }
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: " + e);
+        }
+        if (!result) {
+            System.err.println(
+                    "Soundcard does not exist or sound drivers not installed!");
+            System.err.println(
+                    "This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/Open/ClipOpenBug.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.FloatControl;
+
+/**
+ * @test
+ * @bug 4479444
+ * @summary Verify that the error string of Clip.open() is meaningful
+ */
+public class ClipOpenBug {
+
+    public static void main(String args[]) throws Exception {
+        boolean res = true;
+        try {
+            AudioInputStream ais = new AudioInputStream(
+                    new ByteArrayInputStream(new byte[2000]),
+                    new AudioFormat(8000.0f, 8, 1, false, false), 2000); //
+            AudioFormat format = ais.getFormat();
+            DataLine.Info info = new DataLine.Info(Clip.class, format,
+                                                   ((int) ais.getFrameLength()
+                                                            * format
+                                                           .getFrameSize()));
+            Clip clip = (Clip) AudioSystem.getLine(info);
+            clip.open();
+            FloatControl rateControl = (FloatControl) clip.getControl(
+                    FloatControl.Type.SAMPLE_RATE);
+            int c = 0;
+            while (c++ < 10) {
+                clip.stop();
+                clip.setFramePosition(0);
+                clip.start();
+                for (float frq = 22000; frq < 44100; frq = frq + 100) {
+                    try {
+                        Thread.currentThread().sleep(20);
+                    } catch (Exception e) {
+                        break;
+                    }
+                    rateControl.setValue(frq);
+                }
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            res = ex.getMessage().indexOf(
+                    "This method should not have been invoked!") < 0;
+        }
+        if (res) {
+            System.out.println("Test passed");
+        } else {
+            System.out.println("Test failed");
+            throw new Exception("Test failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioFormat.Encoding;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.LineUnavailableException;
+
+/**
+ * @test
+ * @bug 8167435
+ */
+public final class OpenNonIntegralNumberOfSampleframes {
+
+    /**
+     * We will try to use all formats, in this case all our providers will be
+     * covered by supported/unsupported formats.
+     */
+    private static final List<AudioFormat> formats = new ArrayList<>(2900);
+
+    private static final Encoding[] encodings = {
+            Encoding.ALAW, Encoding.ULAW, Encoding.PCM_SIGNED,
+            Encoding.PCM_UNSIGNED, Encoding.PCM_FLOAT
+    };
+
+    private static final int[] sampleRates = {
+            8000, 11025, 16000, 32000, 44100
+    };
+
+    private static final int[] sampleBits = {
+            4, 8, 11, 16, 20, 24, 32, 48, 64, 128
+    };
+
+    private static final int[] channels = {
+            1, 2, 3, 4, 5, 6
+    };
+
+    static {
+        for (final Boolean end : new boolean[]{false, true}) {
+            for (final int sampleSize : sampleBits) {
+                for (final int sampleRate : sampleRates) {
+                    for (final int channel : channels) {
+                        final int frameSize = ((sampleSize + 7) / 8) * channel;
+                        if (frameSize == 1) {
+                            // frameSize=1 is ok for any buffers, skip it
+                            continue;
+                        }
+                        for (final Encoding enc : encodings) {
+                            formats.add(
+                                    new AudioFormat(enc, sampleRate, sampleSize,
+                                                    channel, frameSize,
+                                                    sampleRate, end));
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public static void main(final String[] args) {
+        for (final AudioFormat af : formats) {
+            try (Clip clip = AudioSystem.getClip()) {
+                final int bufferSize = af.getFrameSize() + 1;
+                try {
+                    clip.open(af, new byte[100], 0, bufferSize);
+                } catch (final IllegalArgumentException ignored) {
+                    // expected exception
+                    continue;
+                } catch (final LineUnavailableException e) {
+                    // should not occur, we passed incorrect bufferSize
+                    e.printStackTrace();
+                }
+                System.err.println("af = " + af);
+                System.err.println("bufferSize = " + bufferSize);
+                throw new RuntimeException("Expected exception is not thrown");
+            } catch (final LineUnavailableException ignored) {
+                // the test is not applicable
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/bug5070081.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,107 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+
+/*
+ * @test
+ * @bug 5070081
+ * @summary Tests that javax.sound.sampled.Clip does not loses position through
+ *          stop/start
+ * @key headful
+ */
+public class bug5070081 {
+
+    static AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
+    // create a 3-second file
+    static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 3)];
+
+    static final int LOOP_COUNT = 5;
+
+    static boolean test() throws Exception {
+        DataLine.Info info = new DataLine.Info(Clip.class, format);
+        Clip clip = (Clip)AudioSystem.getLine(info);
+        clip.open(format, soundData, 0, soundData.length);
+
+        boolean bSuccess = true;
+
+        long nLengthMS = clip.getMicrosecondLength()/1000;
+
+        System.out.println("  Clip length:");
+        System.out.println("    frames: " + clip.getFrameLength());
+        System.out.println("    seconds: " + nLengthMS/1000.0);
+
+        clip.start();                               // start playing
+        Thread.sleep(1000);                         // wait a sec
+        long time1 = System.currentTimeMillis();
+        long pos1 = clip.getFramePosition();        // store the position
+        System.out.println("  Position before stop: " + pos1);
+        clip.stop();                                // and then stop
+        long pos2 = clip.getFramePosition();        // 2nd try
+        long time2 = System.currentTimeMillis();
+        System.out.println("  Position after stop: " + pos2);
+
+        System.out.println("  d(time): " + Math.abs(time2-time1) + " ms;"
+                + "d(clip pos): " + Math.abs(pos2 - pos1) + " ms.");
+
+        long nDerivation = Math.abs(pos2 - pos1) - Math.abs(time2-time1);
+        // add 50 ms for deviation (delay for stopping and errors due timer precision)
+        if (nDerivation > 50) {
+            System.out.println("  ERROR(1): The deviation is too much: " + nDerivation + " ms");
+            bSuccess = false;
+        }
+
+        Thread.sleep(1000);
+        clip.start();                               // start again
+        Thread.sleep(100);
+        while(clip.isRunning());                    // wait for the sound to finish
+
+        int nEndPos = clip.getFramePosition();
+        System.out.println("  Position at end: " + nEndPos);
+        if (nEndPos > clip.getFrameLength()) {
+            System.out.println("  ERROR(2): end position if out of range");
+            bSuccess = false;
+        }
+
+        clip.close();
+
+        return bSuccess;
+    }
+
+    public static void main(String[] args) throws Exception {
+        for (int count=1; count <= LOOP_COUNT; count++)
+        {
+            System.out.println("loop " + count + "/" + LOOP_COUNT);
+            if (!test())
+            {
+                System.out.println("Test FAILED");
+                throw new RuntimeException("Test FAILED.");
+            }
+        }
+
+        System.out.println("Test passed sucessfully");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Clip/bug6251460.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+import javax.sound.sampled.LineUnavailableException;
+
+/**
+ * @test
+ * @bug 6251460 8047222
+ * @requires (os.family == "windows" | os.family == "mac")
+ * @summary Tests that JavaSound plays short sounds (less then 1 second)
+ */
+public class bug6251460 {
+    private static final class MutableBoolean {
+        public boolean value;
+
+        public MutableBoolean(boolean initialValue) {
+            value = initialValue;
+        }
+    }
+
+    // static helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        return System.nanoTime() / 1000000L;
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+            + (time < 10 ? "0" : "") + time
+            + ":" + (min < 10 ? "0" : "") + min
+            + ":" + (sec < 10 ? "0" : "") + sec
+            + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+            + " " + s);
+    }
+
+
+    static private int countErrors = 0;
+    static private final int LOOP_COUNT = 30;
+
+    static AudioFormat format = new AudioFormat(8000, 16, 1, true, false);
+    // create a 250-ms clip
+    static byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * 0.25)];
+
+    static protected void test()
+            throws LineUnavailableException, InterruptedException {
+        DataLine.Info info = new DataLine.Info(Clip.class, format);
+        Clip clip = (Clip)AudioSystem.getLine(info);
+        final MutableBoolean clipStoppedEvent = new MutableBoolean(false);
+        clip.addLineListener(new LineListener() {
+            @Override
+            public void update(LineEvent event) {
+                if (event.getType() == LineEvent.Type.STOP) {
+                    synchronized (clipStoppedEvent) {
+                        clipStoppedEvent.value = true;
+                        clipStoppedEvent.notifyAll();
+                    }
+                }
+            }
+        });
+        clip.open(format, soundData, 0, soundData.length);
+
+        long lengthClip = clip.getMicrosecondLength() / 1000;
+        log("Clip length " + lengthClip + " ms");
+        log("Playing...");
+        for (int i=1; i<=LOOP_COUNT; i++) {
+            long startTime = currentTimeMillis();
+            log(" Loop " + i);
+            clip.start();
+
+            synchronized (clipStoppedEvent) {
+                while (!clipStoppedEvent.value) {
+                    clipStoppedEvent.wait();
+                }
+                clipStoppedEvent.value = false;
+            }
+
+            long endTime = currentTimeMillis();
+            long lengthPlayed = endTime - startTime;
+
+            if (lengthClip > lengthPlayed + 20) {
+                log(" ERR: Looks like sound didn't play: played " + lengthPlayed + " ms instead " + lengthClip);
+                countErrors++;
+            } else {
+                log(" OK: played " + lengthPlayed + " ms");
+            }
+            clip.setFramePosition(0);
+
+        }
+        log("Played " + LOOP_COUNT + " times, " + countErrors + " errors detected.");
+    }
+
+    public static void main(String[] args) throws InterruptedException {
+        try {
+            test();
+        } catch (LineUnavailableException | IllegalArgumentException
+                | IllegalStateException ignored) {
+            System.out.println("Test is not applicable. Automatically passed");
+            return;
+        }
+        if (countErrors > 0) {
+            throw new RuntimeException(
+                    "Test FAILED: " + countErrors + " error detected (total "
+                            + LOOP_COUNT + ")");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Controls/CompoundControl/ToString.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,98 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.CompoundControl;
+import javax.sound.sampled.Control;
+
+/**
+ * @test
+ * @bug 4629190
+ * @summary CompoundControl: getMemberControls() and toString() throw
+ *          NullPointerException
+ */
+public class ToString {
+    public static void main(String args[]) throws Exception {
+        System.out.println();
+        System.out.println();
+        System.out.println("4629190: CompoundControl: getMemberControls() and toString() throw NullPointerException");
+
+        String firstControlTypeName = "first_Control_Type_Name";
+        String secondControlTypeName = "second_Control_Type_Name";
+        String thirdControlTypeName = "third_Control_Type_Name";
+
+        Control.Type firstControlType = new TestControlType(firstControlTypeName);
+        Control.Type secondControlType = new TestControlType(secondControlTypeName);
+        Control.Type thirdControlType = new TestControlType(thirdControlTypeName);
+
+        Control firstControl = new TestControl(firstControlType);
+        Control secondControl = new TestControl(secondControlType);
+        Control thirdControl = new TestControl(thirdControlType);
+
+        String testCompoundControlTypeName = "CompoundControl_Type_Name";
+        CompoundControl.Type testCompoundControlType
+            = new TestCompoundControlType(testCompoundControlTypeName);
+
+        Control[] setControls = { firstControl, secondControl, thirdControl };
+        CompoundControl testedCompoundControl
+            = new TestCompoundControl(testCompoundControlType, setControls);
+
+        // this may throw exception if bug applies
+        Control[] producedControls = testedCompoundControl.getMemberControls();
+        System.out.println("Got "+producedControls.length+" member controls.");
+
+        // this may throw exception if bug applies
+        String producedString = testedCompoundControl.toString();
+        System.out.println("toString() returned: "+producedString);
+
+        System.out.println("Test passed.");
+    }
+
+}
+
+class TestControl extends Control {
+
+    TestControl(Control.Type type) {
+        super(type);
+    }
+}
+
+class TestControlType extends Control.Type {
+
+    TestControlType(String name) {
+        super(name);
+    }
+}
+
+class TestCompoundControl extends CompoundControl {
+
+    TestCompoundControl(CompoundControl.Type type, Control[] memberControls) {
+        super(type, memberControls);
+    }
+}
+
+class TestCompoundControlType extends CompoundControl.Type {
+
+    TestCompoundControlType(String name) {
+        super(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Controls/FloatControl/FloatControlBug.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.FloatControl;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4385654
+ * @summary Check that the MASTER_GAIN control has a valid precision
+ */
+//public class test047 extends TRTest
+public class FloatControlBug {
+
+    private Clip theClip;
+
+    boolean testPassed = true;
+
+    private AudioFormat.Encoding theEncoding = AudioFormat.Encoding.PCM_SIGNED;
+
+    private float theSampleRate = 44100;
+
+    private int theSampleSize = 16;
+
+    private int theNumberOfChannels = 1;
+
+    private int theFrameSize = 2;
+
+    private float theFrameRate = 44100;
+
+    private boolean isBigEndian = false;
+
+    //_______________________________________________
+    //      Method: runTest
+    //_______________________________________________
+    public boolean runTest() {
+        AudioInputStream theAudioInputStream = new AudioInputStream(
+                new ByteArrayInputStream(new byte[0]),
+                new AudioFormat(44100.0f, 16, 2, true, false), 441000);
+
+        AudioFormat theAudioFormat = theAudioInputStream.getFormat();
+
+        DataLine.Info info = new DataLine.Info(Clip.class, theAudioFormat,
+                                               AudioSystem.NOT_SPECIFIED);
+        try {
+            theClip = (Clip) AudioSystem.getLine(info);
+            theClip.open(theAudioInputStream);
+            FloatControl theFloatControl = (FloatControl) (theClip.getControl(
+                    FloatControl.Type.MASTER_GAIN));
+            float theFloatControlPrecision = theFloatControl.getPrecision();
+            System.out.println(
+                    "theFloatControlPrecision: " + theFloatControlPrecision);
+            System.out.println("Minimum: " + theFloatControl.getMinimum());
+            System.out.println("Maximum: " + theFloatControl.getMaximum());
+            System.out.println("Value  : " + theFloatControl.getValue());
+            testPassed = theFloatControlPrecision > 0;
+        } catch (LineUnavailableException e) {
+            e.printStackTrace();
+            testPassed = true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            testPassed = false;
+        }
+        return testPassed;
+    }
+
+    //_______________________________________________
+    //      Method: main
+    //_______________________________________________
+    public static void main(String[] args) throws Exception {
+        //test047 thisTest = new test047();
+        if (isSoundcardInstalled()) {
+            FloatControlBug thisTest = new FloatControlBug();
+            boolean testResult = thisTest.runTest();
+            if (testResult) {
+                System.out.println("Test passed");
+            } else {
+                System.out.println("Test failed");
+                throw new Exception("Test failed");
+            }
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: " + e);
+        }
+        if (!result) {
+            System.err.println(
+                    "Soundcard does not exist or sound drivers not installed!");
+            System.err.println(
+                    "This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/DataLine/DataLineInfoNegBufferSize.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 5021234
+ * @summary Using -2 for buffer size will fail retrieval of lines
+ */
+public class DataLineInfoNegBufferSize {
+
+    /**
+     * returns:
+     * 0: OK
+     * 1: IAE
+     * 2: other exception
+     * 3: line not available
+     */
+    public static int run(Mixer m, int bufferSize) {
+        int res;
+        int frameCount = 441000; // lets say 10 seconds
+        AudioFormat f = new AudioFormat(44100.0f, 16, 2, true, false);
+        Clip clip = null;
+        try {
+            System.out.println("Requesting clip from Mixer "
+                               +(m==null?"default":m.toString())
+                               +" with bufferSize"+bufferSize);
+            DataLine.Info info = new DataLine.Info(Clip.class, f, bufferSize);
+            if (m==null) {
+                clip = (Clip) AudioSystem.getLine(info);
+            } else {
+                clip = (Clip) m.getLine(info);
+            }
+            System.out.println("Got clip: "+clip+" with Buffer size "+clip.getBufferSize());
+
+            res = 0;
+        } catch (LineUnavailableException luae) {
+            System.out.println(luae);
+            res = 3; // line not available
+        } catch (IllegalArgumentException iae) {
+            System.out.println(iae);
+            res = 1;
+        } catch (Throwable t) {
+            System.out.println("->Exception:"+t);
+            t.printStackTrace();
+            res=2; // other exception
+        }
+        return res;
+    }
+
+    public static void main(String[] args) throws Exception     {
+        if (isSoundcardInstalled()) {
+            int res=0;
+            int count = 0;
+            Mixer.Info[] infos = AudioSystem.getMixerInfo();
+            for (int i = -1; i<infos.length; i++) {
+                try {
+                    Mixer m;
+                    if (i == -1) {
+                        m = null;
+                    } else {
+                        m = AudioSystem.getMixer(infos[i]);
+                    }
+                    int r = run(m, AudioSystem.NOT_SPECIFIED);
+                    // only continue if successful
+                    if (r == 0) {
+                        count++;
+                        r = run(m, -2);
+                        if (r == 1) {
+                            // only fail if IAE was thrown
+                            System.out.println("#FAILED: using -2 for buffer size does not work!");
+                            res = 1;
+                        }
+                    }
+                } catch (Exception e) {
+                }
+            }
+            if (res!=1) {
+                System.out.println("Test passed");
+            } else {
+                if (count == 0) {
+                    System.err.println("Test could not execute -- no suitable mixers installed. NOT failed");
+                }
+                throw new Exception("Test FAILED!");
+            }
+        }
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/DataLine/LineDefFormat.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 5053380
+ * @summary Verify that getting a line initializes it with the format in
+ *          DataLine.Info
+ */
+public class LineDefFormat {
+
+    final static int samplerate = 22050;
+    static int passed = 0;
+    static int failed = 0;
+
+    private static void doLine1(DataLine line, AudioFormat format) {
+        try {
+            System.out.println("  - got line: "+line);
+            System.out.println("  - line has format: "+line.getFormat());
+            if (!line.getFormat().matches(format)) {
+                System.out.println("  ## Error: expected this format: "+format);
+                failed++;
+            } else {
+                passed++;
+            }
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+        }
+    }
+
+    private static void doLine2(DataLine line, AudioFormat format) {
+        try {
+            System.out.println("  - call to open()");
+            line.open();
+            try {
+                System.out.println("  - line has format: "+line.getFormat());
+                if (!line.getFormat().matches(format)) {
+                    System.out.println("## Error: expected this format: "+format);
+                    failed++;
+                } else {
+                    passed++;
+                }
+            } finally {
+                line.close();
+                System.out.println("  - closed");
+            }
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+        }
+    }
+
+    private static void doMixerClip(Mixer mixer, AudioFormat format) {
+        if (mixer==null) return;
+        try {
+            System.out.println("Clip from mixer "+mixer+":");
+            System.out.println("   "+mixer.getMixerInfo());
+                DataLine.Info info = new DataLine.Info(
+                                          Clip.class,
+                                          format);
+
+            if (mixer.isLineSupported(info)) {
+                Clip clip = (Clip) mixer.getLine(info);
+                doLine1(clip, format);
+            } else {
+                System.out.println("  - Line not supported");
+            }
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+        }
+    }
+
+    private static void doMixerSDL(Mixer mixer, AudioFormat format) {
+        if (mixer==null) return;
+        try {
+            System.out.println("SDL from mixer "+mixer+":");
+                DataLine.Info info = new DataLine.Info(
+                                          SourceDataLine.class,
+                                          format);
+
+            if (mixer.isLineSupported(info)) {
+                SourceDataLine sdl = (SourceDataLine) mixer.getLine(info);
+                doLine1(sdl, format);
+                doLine2(sdl, format);
+            } else {
+                System.out.println("  - Line not supported");
+            }
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+        }
+    }
+
+    private static void doMixerTDL(Mixer mixer, AudioFormat format) {
+        if (mixer==null) return;
+        try {
+            System.out.println("TDL from mixer "+mixer+":");
+                DataLine.Info info = new DataLine.Info(
+                                          TargetDataLine.class,
+                                          format);
+            if (mixer.isLineSupported(info)) {
+                TargetDataLine tdl = (TargetDataLine) mixer.getLine(info);
+                doLine1(tdl, format);
+                doLine2(tdl, format);
+            } else {
+                System.out.println("  - Line not supported");
+            }
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+        }
+    }
+
+    private static void doAll() throws Exception {
+        Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+               AudioFormat pcm;
+        for (int i=0; i<mixers.length; i++) {
+            Mixer mixer = AudioSystem.getMixer(mixers[i]);
+            pcm = new AudioFormat(samplerate, 16, 1, true, false);
+            doMixerClip(mixer, pcm);
+            pcm = new AudioFormat(samplerate, 8, 1, false, false);
+            doMixerSDL(mixer, pcm);
+            pcm = new AudioFormat(samplerate, 16, 2, true, true);
+            doMixerTDL(mixer, pcm);
+        }
+        if (mixers.length==0) {
+            System.out.println("No mixers available!");
+        }
+
+    }
+
+    public static void main(String args[]) throws Exception{
+        doAll();
+        if (passed==0 && failed==0) {
+            System.out.println("Could not execute any of the tests. Test NOT failed.");
+        } else if (failed == 0) {
+            System.out.println("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/DataLine/LongFramePosition.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 5049129
+ * @summary DataLine.getLongFramePosition
+ * @key headful
+ */
+public class LongFramePosition {
+
+    public static void main(String[] args) throws Exception {
+        boolean failed = false;
+        try {
+            AudioFormat format = new AudioFormat(44100.0f, 16, 2, true, false);
+            SourceDataLine sdl = AudioSystem.getSourceDataLine(format);
+            try {
+                sdl.open(format);
+                sdl.start();
+                sdl.write(new byte[16384], 0, 16384);
+                Thread.sleep(1000);
+                int intPos = sdl.getFramePosition();
+                long longPos = sdl.getLongFramePosition();
+                System.out.println("After 1 second: getFramePosition() = "+intPos);
+                System.out.println("            getLongFramePosition() = "+longPos);
+                if (intPos <= 0 || longPos <= 0) {
+                    failed = true;
+                    System.out.println("## FAILED: frame position did not advance, or negative!");
+                }
+                if (Math.abs(intPos - longPos) > 100) {
+                    failed = true;
+                    System.out.println("## FAILED: frame positions are not the same!");
+                }
+            } finally {
+                sdl.close();
+            }
+        } catch(LineUnavailableException e){
+            System.out.println(e);
+            System.out.println("Cannot execute test.");
+            return;
+        }
+        if (failed) throw new Exception("Test FAILED!");
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/DirectAudio/TickAtEndOfPlay.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 5001959
+ * @summary Short tick sound after finished playing with SourceDataLine
+ * @run main/manual TickAtEndOfPlay
+ */
+public class TickAtEndOfPlay {
+
+    static boolean WorkAround1 = false;
+    static boolean WorkAround2 = false;
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("This test should only be run on Windows.");
+        System.out.println("Make sure that the speakers are connected and the volume is up.");
+        System.out.println("Close all other programs that may use the soundcard.");
+
+        System.out.println("You'll hear a 2-second tone. when the tone finishes,");
+        System.out.println("  there should be no noise. If you hear a short tick/noise,");
+        System.out.println("  the bug still applies.");
+
+        System.out.println("Press ENTER to continue.");
+        System.in.read();
+
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("1")) WorkAround1 = true;
+            if (args[i].equals("2")) WorkAround2 = true;
+        }
+        if (WorkAround1) System.out.println("Using work around1: appending silence");
+        if (WorkAround2) System.out.println("Using work around2: waiting before close");
+
+        int zerolen = 0; // how many 0-bytes will be appended to playback
+        if (WorkAround1) zerolen = 1000;
+        int seconds = 2;
+        int sampleRate = 8000;
+        double frequency = 1000.0;
+        double RAD = 2.0 * Math.PI;
+        AudioFormat af = new AudioFormat((float)sampleRate,8,1,true,true);
+        System.out.println("Format: "+af);
+        DataLine.Info info = new DataLine.Info(SourceDataLine.class,af);
+        SourceDataLine source = (SourceDataLine)AudioSystem.getLine(info);
+        System.out.println("Line: "+source);
+        if (source.toString().indexOf("MixerSourceLine")>=0) {
+            System.out.println("This test only applies to non-Java Sound Audio Engine!");
+            return;
+        }
+        System.out.println("Opening...");
+        source.open(af);
+        System.out.println("Starting...");
+        source.start();
+        int datalen = sampleRate * seconds;
+        byte[] buf = new byte[datalen+zerolen];
+        for (int i=0; i<datalen; i++) {
+            buf[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+        }
+        System.out.println("Writing...");
+        source.write(buf,0,buf.length);
+        System.out.println("Draining...");
+        source.drain();
+        System.out.println("Stopping...");
+        source.stop();
+        if (WorkAround2) {
+            System.out.println("Waiting 200 millis...");
+            Thread.sleep(200);
+        }
+        System.out.println("Closing...");
+        source.close();
+        System.out.println("Done.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/DirectAudio/bug6372428.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/*
+ * @test
+ * @bug 6372428
+ * @summary playback and capture doesn't interrupt after terminating thread that
+ *          calls start()
+ * @run main bug6372428
+ * @key headful
+ */
+public class bug6372428 {
+    public bug6372428() {
+    }
+
+    public static void main(final String[] args) {
+        bug6372428 pThis = new bug6372428();
+        boolean failed1 = false;
+        boolean failed2 = false;
+        log("");
+        log("****************************************************************");
+        log("*** Playback Test");
+        log("****************************************************************");
+        log("");
+        try {
+            pThis.testPlayback();
+        } catch (IllegalArgumentException | LineUnavailableException e) {
+            System.out.println("Playback test is not applicable. Skipped");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            failed1 = true;
+        }
+        log("");
+        log("");
+        log("****************************************************************");
+        log("*** Capture Test");
+        log("****************************************************************");
+        log("");
+        try {
+            pThis.testRecord();
+        } catch (IllegalArgumentException | LineUnavailableException e) {
+            System.out.println("Record test is not applicable. Skipped");
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            failed2 = true;
+        }
+        log("");
+        log("");
+        log("****************************************************************");
+        if (failed1 || failed2) {
+            String s = "";
+            if (failed1 && failed2)
+                s = "playback and capture";
+            else if (failed1)
+                s = "playback only";
+            else
+                s = "capture only";
+            throw new RuntimeException("Test FAILED (" + s + ")");
+        }
+        log("*** All tests passed successfully.");
+    }
+
+    final static int DATA_LENGTH        = 15;   // in seconds
+    final static int PLAYTHREAD_DELAY   = 5;   // in seconds
+
+    // playback test classes/routines
+
+    class PlayThread extends Thread {
+        SourceDataLine line;
+        public PlayThread(SourceDataLine line) {
+            this.line = line;
+            this.setDaemon(true);
+        }
+
+        public void run() {
+            log("PlayThread: starting...");
+            line.start();
+            log("PlayThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
+            delay(PLAYTHREAD_DELAY * 1000);
+            log("PlayThread: exiting...");
+        }
+    }
+
+    class WriteThread extends Thread {
+        SourceDataLine line;
+        byte[] data;
+        volatile int remaining;
+        volatile boolean stopRequested = false;
+        public WriteThread(SourceDataLine line, byte[] data) {
+            this.line = line;
+            this.data = data;
+            remaining = data.length;
+            this.setDaemon(true);
+        }
+
+        public void run() {
+            while (remaining > 0 && !stopRequested) {
+                int avail = line.available();
+                if (avail > 0) {
+                    if (avail > remaining)
+                        avail = remaining;
+                    int written = line.write(data, data.length - remaining, avail);
+                    remaining -= written;
+                    log("WriteThread: " + written + " bytes written");
+                } else {
+                    delay(100);
+                }
+            }
+            if (remaining == 0) {
+                log("WriteThread: all data has been written, draining");
+                line.drain();
+            } else {
+                log("WriteThread: stop requested");
+            }
+            log("WriteThread: stopping");
+            line.stop();
+            log("WriteThread: exiting");
+        }
+
+        public boolean isCompleted() {
+            return (remaining <= 0);
+        }
+
+        public void requestStop() {
+            stopRequested = true;
+        }
+    }
+
+    void testPlayback() throws LineUnavailableException {
+        // prepare audio data
+        AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
+        byte[] soundData = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
+
+        // create & open source data line
+        //SourceDataLine line = AudioSystem.getSourceDataLine(format);
+        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
+        SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
+
+        line.open(format);
+
+        // start write data thread
+        WriteThread p1 = new WriteThread(line, soundData);
+        p1.start();
+
+        // start line
+        PlayThread p2 = new PlayThread(line);
+        p2.start();
+
+        // monitor line
+        long lineTime1 = line.getMicrosecondPosition() / 1000;
+        long realTime1 = currentTimeMillis();
+        while (true) {
+            delay(500);
+            if (!line.isActive()) {
+                log("audio data played completely");
+                break;
+            }
+            long lineTime2 = line.getMicrosecondPosition() / 1000;
+            long realTime2 = currentTimeMillis();
+            long dLineTime = lineTime2 - lineTime1;
+            long dRealTime = realTime2 - realTime1;
+            log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
+            if (dLineTime < 0) {
+                throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
+            }
+            if (dRealTime < 450) {
+                // delay() has been interrupted?
+                continue;
+            }
+            lineTime1 = lineTime2;
+            realTime1 = realTime2;
+        }
+    }
+
+
+    // recording test classes/routines
+
+    class RecordThread extends Thread {
+        TargetDataLine line;
+        public RecordThread(TargetDataLine line) {
+            this.line = line;
+            this.setDaemon(true);
+        }
+
+        public void run() {
+            log("RecordThread: starting...");
+            line.start();
+            log("RecordThread: delaying " + (PLAYTHREAD_DELAY * 1000) + "ms...");
+            delay(PLAYTHREAD_DELAY * 1000);
+            log("RecordThread: exiting...");
+        }
+    }
+
+    class ReadThread extends Thread {
+        TargetDataLine line;
+        byte[] data;
+        volatile int remaining;
+        public ReadThread(TargetDataLine line, byte[] data) {
+            this.line = line;
+            this.data = data;
+            remaining = data.length;
+            this.setDaemon(true);
+        }
+
+        public void run() {
+            log("ReadThread: buffer size is " + data.length + " bytes");
+            delay(200);
+            while ((remaining > 0) && line.isOpen()) {
+                int avail = line.available();
+                if (avail > 0) {
+                    if (avail > remaining)
+                        avail = remaining;
+                    int read = line.read(data, data.length - remaining, avail);
+                    remaining -= read;
+                    log("ReadThread: " + read + " bytes read");
+                } else {
+                    delay(100);
+                }
+                if (remaining <= 0) {
+                    log("ReadThread: record buffer is full, exiting");
+                    break;
+                }
+            }
+            if (remaining > 0) {
+                log("ReadThread: line has been stopped, exiting");
+            }
+        }
+
+        public int getCount() {
+            return data.length - remaining;
+        }
+        public boolean isCompleted() {
+            return (remaining <= 0);
+        }
+    }
+
+    void testRecord() throws LineUnavailableException {
+        // prepare audio data
+        AudioFormat format = new AudioFormat(22050, 8, 1, false, false);
+
+        // create & open target data line
+        //TargetDataLine line = AudioSystem.getTargetDataLine(format);
+        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
+        TargetDataLine line = (TargetDataLine)AudioSystem.getLine(info);
+
+        line.open(format);
+
+        // start read data thread
+        byte[] data = new byte[(int) (format.getFrameRate() * format.getFrameSize() * DATA_LENGTH)];
+        ReadThread p1 = new ReadThread(line, data);
+        p1.start();
+
+        // start line
+        //new RecordThread(line).start();
+        RecordThread p2 = new RecordThread(line);
+        p2.start();
+
+        // monitor line
+        long endTime = currentTimeMillis() + DATA_LENGTH * 1000;
+
+        long realTime1 = currentTimeMillis();
+        long lineTime1 = line.getMicrosecondPosition() / 1000;
+
+        while (realTime1 < endTime && !p1.isCompleted()) {
+            delay(100);
+            long lineTime2 = line.getMicrosecondPosition() / 1000;
+            long realTime2 = currentTimeMillis();
+            long dLineTime = lineTime2 - lineTime1;
+            long dRealTime = realTime2 - realTime1;
+            log("line pos: " + lineTime2 + "ms" + ", thread is " + (p2.isAlive() ? "alive" : "DIED"));
+            if (dLineTime < 0) {
+                line.stop();
+                line.close();
+                throw new RuntimeException("ERROR: line position have decreased from " + lineTime1 + " to " + lineTime2);
+            }
+            if (dRealTime < 450) {
+                // delay() has been interrupted?
+                continue;
+            }
+            lineTime1 = lineTime2;
+            realTime1 = realTime2;
+        }
+        log("stopping line...");
+        line.stop();
+        line.close();
+
+        /*
+        log("");
+        log("");
+        log("");
+        log("recording completed, delaying 5 sec");
+        log("recorded " + p1.getCount() + " bytes, " + DATA_LENGTH + " seconds: " + (p1.getCount() * 8 / DATA_LENGTH) + " bit/sec");
+        log("");
+        log("");
+        log("");
+        delay(5000);
+        log("starting playing...");
+        playRecorded(format, data);
+        */
+    }
+
+    void playRecorded(AudioFormat format, byte[] data) throws Exception {
+        //SourceDataLine line = AudioSystem.getSourceDataLine(format);
+        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
+        SourceDataLine line = (SourceDataLine)AudioSystem.getLine(info);
+
+        line.open();
+        line.start();
+
+        int remaining = data.length;
+        while (remaining > 0) {
+            int avail = line.available();
+            if (avail > 0) {
+                if (avail > remaining)
+                    avail = remaining;
+                int written = line.write(data, data.length - remaining, avail);
+                remaining -= written;
+                log("Playing: " + written + " bytes written");
+            } else {
+                delay(100);
+            }
+        }
+
+        line.drain();
+        line.stop();
+    }
+
+    // helper routines
+    static long startTime = currentTimeMillis();
+    static long currentTimeMillis() {
+        //return System.nanoTime() / 1000000L;
+        return System.currentTimeMillis();
+    }
+    static void log(String s) {
+        long time = currentTimeMillis() - startTime;
+        long ms = time % 1000;
+        time /= 1000;
+        long sec = time % 60;
+        time /= 60;
+        long min = time % 60;
+        time /= 60;
+        System.out.println(""
+            + (time < 10 ? "0" : "") + time
+            + ":" + (min < 10 ? "0" : "") + min
+            + ":" + (sec < 10 ? "0" : "") + sec
+            + "." + (ms < 10 ? "00" : (ms < 100 ? "0" : "")) + ms
+            + " (" + Thread.currentThread().getName() + ") " + s);
+    }
+    static void delay(int millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/FileTypeExtension/FileTypeExtensionTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,62 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFileFormat;
+
+/**
+ * @test
+ * @bug 4300529
+ * @summary Filename extension test. The filename extensions for file types
+ *          AIFF-C, SND, and WAVE should not include a ".".
+ */
+public class FileTypeExtensionTest {
+
+    public static void main(String[] args) throws Exception {
+
+        AudioFileFormat.Type[] types = { AudioFileFormat.Type.AIFC,
+                                         AudioFileFormat.Type.AIFF,
+                                         AudioFileFormat.Type.AU,
+                                         AudioFileFormat.Type.SND,
+                                         AudioFileFormat.Type.WAVE };
+
+        boolean failed = false;
+
+        System.out.println("\nDefined file types and extensions:");
+
+        for (int i = 0; i < types.length; i++) {
+            System.out.println("\n");
+            System.out.println("  file type: " + types[i]);
+            System.out.println("  extension: " + types[i].getExtension());
+            if( types[i].getExtension().charAt(0) == '.' ) {
+                failed = true;
+            }
+        }
+
+        if (failed) {
+            System.err.println("Failed!");
+            throw new Exception("File type extensions begin with .");
+        } else {
+            System.err.println("Passed!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/LineEvent/LineInfoNPE.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,177 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.Control;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+
+/**
+ * @test
+ * @bug 4672865
+ * @summary LineEvent.toString() throws unexpected NullPointerException
+ */
+public class LineInfoNPE {
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+    static final int STATUS_TEMP = 95;
+
+    public static void main(String argv[]) throws Exception {
+        int testExitStatus = run(argv, System.out);
+        if (testExitStatus != STATUS_PASSED) {
+            throw new Exception("test FAILED!");
+        }
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) {
+        int testResult = STATUS_PASSED;
+
+        out.println("\n==> Test for LineEvent class:");
+
+        Line testLine = new TestLine();
+        Line nullLine = null;
+
+        LineEvent.Type testLineEventType = LineEvent.Type.OPEN;
+        LineEvent.Type nullLineEventType = null;
+
+        LineEvent testedLineEvent = null;
+        out.println("\n>> LineEvent constructor for Line = null: ");
+        try {
+            testedLineEvent =
+                new LineEvent(nullLine,  // the source Line of this event
+                                testLineEventType, // LineEvent.Type - the event type
+                                (long) 1000 // position - the number processed of sample frames
+                                );
+            out.println(">  No any Exception was thrown!");
+            out.println(">  testedLineEvent.getType():");
+            try {
+                Line producedLine = testedLineEvent.getLine();
+                out.println(">   PASSED: producedLine = " + producedLine);
+            } catch (Throwable thrown) {
+                out.println("##  FAILED: unexpected Exception was thrown:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+            }
+            out.println(">  testedLineEvent.toString():");
+            try {
+                String producedString = testedLineEvent.toString();
+                out.println(">   PASSED: producedString = " + producedString);
+            } catch (Throwable thrown) {
+                out.println("##  FAILED: unexpected Exception was thrown:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+            }
+        } catch (IllegalArgumentException illegArgExcept) {
+            out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+            illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+            out.println(">   PASSED: expected NullPointerException was thrown:");
+            nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+            out.println("##  FAILED: unexpected Exception was thrown:");
+            thrown.printStackTrace(out);
+            testResult = STATUS_FAILED;
+        }
+
+        out.println("\n>> LineEvent constructor for LineEvent.Type = null: ");
+        try {
+            testedLineEvent =
+                new LineEvent(testLine,  // the source Line of this event
+                                nullLineEventType, // LineEvent.Type - the event type
+                                (long) 1000 // position - the number processed of sample frames
+                                );
+            out.println(">  No any Exception was thrown!");
+            out.println(">  testedLineEvent.getType():");
+            try {
+                LineEvent.Type producedType = testedLineEvent.getType();
+                out.println(">   PASSED: producedType = " + producedType);
+            } catch (Throwable thrown) {
+                out.println("##  FAILED: unexpected Exception was thrown:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+            }
+            out.println(">  testedLineEvent.toString():");
+            try {
+                String producedString = testedLineEvent.toString();
+                out.println(">   PASSED: producedString = " + producedString);
+            } catch (Throwable thrown) {
+                out.println("##  FAILED: unexpected Exception was thrown:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+            }
+        } catch (IllegalArgumentException illegArgExcept) {
+            out.println(">   PASSED: expected IllegalArgumentException was thrown:");
+            illegArgExcept.printStackTrace(out);
+        } catch (NullPointerException nullPE) {
+            out.println(">   PASSED: expected NullPointerException was thrown:");
+            nullPE.printStackTrace(out);
+        } catch (Throwable thrown) {
+            out.println("##  FAILED: unexpected Exception was thrown:");
+            thrown.printStackTrace(out);
+            testResult = STATUS_FAILED;
+        }
+
+        if ( testResult == STATUS_FAILED ) {
+            out.println("\n==> test FAILED!");
+        } else {
+            out.println("\n==> test PASSED!");
+        }
+        return testResult;
+    }
+}    // end of test class
+
+class TestLine implements Line {
+
+    public void addLineListener(LineListener listener) {
+    }
+
+    public void close() {
+    }
+
+    public Control getControl(Control.Type control) {
+        return null;
+    }
+
+    public Control[] getControls() {
+        return new Control[0];
+    }
+
+    public Line.Info getLineInfo() {
+        return null;
+    }
+
+    public boolean isOpen() {
+        return false;
+    }
+
+    public boolean isControlSupported(Control.Type control) {
+        return false;
+    }
+
+    public void open() {
+    }
+
+    public void removeLineListener(LineListener listener) {
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/16and32KHz/Has16and32KHz.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 4479441
+ * @summary Verify that the lines report 16KHz and 32KHz capability
+ */
+public class Has16and32KHz {
+
+    public static boolean ok32=false;
+    public static boolean ok16=false;
+
+    public static void showMixerLines(Line.Info[] lineinfo) {
+        for (int j = 0; j < lineinfo.length; j++) {
+            boolean isSDL=false; // SourceDataLine
+            Line.Info thisInfo=lineinfo[j];
+            System.out.println("  " + thisInfo);
+            String impl="";
+            if (thisInfo.getLineClass().equals(SourceDataLine.class)) {
+                isSDL=true;
+                impl+="SourceDataLine";
+            }
+            if (thisInfo.getLineClass().equals(Clip.class)) {
+                impl+="Clip";
+            }
+            if (thisInfo.getLineClass().equals(DataLine.class)) {
+                impl+="DataLine";
+            }
+            if (thisInfo.getLineClass().equals(TargetDataLine.class)) {
+                impl+="TargetDataLine";
+            }
+            if (thisInfo.getLineClass().equals(Mixer.class)) {
+                impl+="Mixer";
+            }
+            System.out.println("  implements "+impl);
+            try {
+                AudioFormat[] formats = ((DataLine.Info)lineinfo[j]).getFormats();
+                for (int k = 0; k < formats.length; k++) {
+                    System.out.println("    " + formats[k] + ", "+ formats[k].getFrameSize()+" bytes/frame");
+                    if (isSDL) {
+                        if ((formats[k].getSampleRate()==AudioSystem.NOT_SPECIFIED)
+                            || (formats[k].getSampleRate()==32000.0f)) {
+                            ok32=true;
+                        }
+                        if ((formats[k].getSampleRate()==AudioSystem.NOT_SPECIFIED)
+                            || (formats[k].getSampleRate()==16000.0f)) {
+                            ok16=true;
+                        }
+                    }
+                }
+            } catch (ClassCastException e) {
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        boolean res=true;
+
+        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
+        System.out.println(mixerInfo.length+" mixers on system.");
+        if (mixerInfo.length == 0) {
+            System.out.println("Cannot execute test. Not Failed!");
+        } else {
+            for (int i = 0; i < mixerInfo.length; i++) {
+                Mixer mixer = AudioSystem.getMixer(mixerInfo[i]);
+                System.out.println();
+                System.out.println(mixer+":");
+                showMixerLines(mixer.getSourceLineInfo());
+                showMixerLines(mixer.getTargetLineInfo());
+
+
+            }
+            res=ok16 && ok32;
+        }
+        if (res) {
+            System.out.println("Test passed");
+        } else {
+            System.out.println("Test failed");
+            throw new Exception("Test failed");
+        }
+        //ystem.exit(res?0:1);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/BufferSizeCheck.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4661602
+ * @summary Buffersize is checked when re-opening line
+ */
+public class BufferSizeCheck {
+
+    public static void main(String[] args) throws Exception {
+        boolean realTest = false;
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+
+        try {
+            out("4661602: Buffersize is checked when re-opening line");
+            AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+            DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
+            SourceDataLine sdl = (SourceDataLine) AudioSystem.getLine(info);
+            out("Opening with buffersize 12000...");
+            sdl.open(format, 12000);
+            out("Opening with buffersize 11000...");
+            realTest=true;
+            sdl.open(format, 11000);
+            try {
+                sdl.close();
+            } catch(Throwable t) {}
+        } catch (Exception e) {
+            e.printStackTrace();
+            // do not fail if no audio device installed - bug 4742021
+            if (realTest || !(e instanceof LineUnavailableException)) {
+                throw e;
+            }
+        }
+        out("Test passed");
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/ChangingBuffer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,165 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4515126
+ * @summary Verify that the buffer passed to SourceDataLine.write() and
+ *          Clip.open() will not be changed
+ */
+public class ChangingBuffer {
+
+    final static int samplerate = 44100;
+    final static byte[] buffer = new byte[16384];
+    static int successfulTests = 0;
+
+    private static void makeBuffer() {
+        for (int i=0; i<buffer.length; i++) {
+            buffer[i] = (byte) (i % 128);
+        }
+    }
+
+    private static void checkBufferSDL() throws Exception {
+        successfulTests++;
+        for (int i=0; i<buffer.length; i++) {
+            if (buffer[i] != ((byte) (i % 128))) {
+                throw new Exception("Buffer was changed by SourceDataLine.write()!. Test FAILED");
+            }
+        }
+        System.out.println("  -> passed for this line");
+        System.out.println("");
+    }
+
+    private static void checkBufferClip() throws Exception {
+        for (int i=0; i<buffer.length; i++) {
+            if (buffer[i] != (i % 128)) {
+                throw new Exception("Buffer was changed by Clip.open()!. Test FAILED");
+            }
+        }
+        System.out.println("  -> passed for this clip");
+        System.out.println("");
+    }
+
+    private static boolean doMixerClip(Mixer mixer, AudioFormat format) {
+        if (mixer==null) return false;
+        try {
+            System.out.println("Trying mixer "+mixer+":");
+                DataLine.Info info = new DataLine.Info(
+                                          Clip.class,
+                                          format,
+                                          (int) samplerate);
+
+                Clip clip = (Clip) mixer.getLine(info);
+            System.out.println("  - got clip: "+clip);
+            System.out.println("  - open with format "+format);
+            clip.open(format, buffer, 0, buffer.length);
+            System.out.println("  - playing...");
+            clip.start();
+            System.out.println("  - waiting while it's active...");
+            while (clip.isActive())
+                    Thread.sleep(100);
+            System.out.println("  - waiting 100millis");
+            Thread.sleep(100);
+            System.out.println("  - drain1");
+            clip.drain();
+            System.out.println("  - drain2");
+            clip.drain();
+            System.out.println("  - stop");
+            clip.stop();
+            System.out.println("  - close");
+            clip.close();
+            System.out.println("  - closed");
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+            return false;
+        }
+        return true;
+    }
+
+    private static boolean doMixerSDL(Mixer mixer, AudioFormat format) {
+        if (mixer==null) return false;
+        try {
+            System.out.println("Trying mixer "+mixer+":");
+                DataLine.Info info = new DataLine.Info(
+                                          SourceDataLine.class,
+                                          format,
+                                          (int) samplerate);
+
+                SourceDataLine sdl = (SourceDataLine) mixer.getLine(info);
+            System.out.println("  - got sdl: "+sdl);
+            System.out.println("  - open with format "+format);
+            sdl.open(format);
+            System.out.println("  - start...");
+            sdl.start();
+            System.out.println("  - write...");
+            sdl.write(buffer, 0, buffer.length);
+            Thread.sleep(200);
+            System.out.println("  - drain...");
+            sdl.drain();
+            System.out.println("  - stop...");
+            sdl.stop();
+            System.out.println("  - close...");
+            sdl.close();
+            System.out.println("  - closed");
+        } catch (Throwable t) {
+            System.out.println("  - Caught exception. Not failed.");
+            System.out.println("  - "+t.toString());
+            return false;
+        }
+        return true;
+    }
+
+    private static void doAll(boolean bigEndian) throws Exception {
+        AudioFormat pcm = new AudioFormat(
+                            AudioFormat.Encoding.PCM_SIGNED,
+                            samplerate, 16, 1, 2, samplerate, bigEndian);
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            for (int i=0; i<mixers.length; i++) {
+                Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                makeBuffer(); if (doMixerClip(mixer, pcm)) checkBufferClip();
+                makeBuffer(); if (doMixerSDL(mixer, pcm)) checkBufferSDL();
+            }
+            if (mixers.length==0) {
+                System.out.println("No mixers available!");
+            }
+
+    }
+
+    public static void main(String args[]) throws Exception{
+        doAll(true);
+        doAll(false);
+        if (successfulTests==0) {
+            System.out.println("Could not execute any of the tests. Test NOT failed.");
+        } else {
+            System.out.println("Test PASSED.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/ClickInPlay/ClickInPlay.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * This is utility class for Test4218609.
+ */
+public class ClickInPlay {
+
+    static int sampleRate = 8000;
+    static double frequency = 2000.0;
+    static double RAD = 2.0 * Math.PI;
+
+    static byte[] audioData = new byte[sampleRate/2];
+    static DataLine.Info info;
+    static Clip source;
+
+    //static AudioInputStream ais = null;
+    static AudioFormat audioFormat;
+    //static String filename;
+
+    public static void print(String s) {
+        System.out.print(s);
+    }
+    public static void println(String s) {
+        System.out.println(s);
+    }
+
+    public static void key() {
+        println("");
+        print("Press ENTER to continue...");
+        try {
+            System.in.read();
+        } catch (IOException ioe) {
+        }
+    }
+
+    public static void play(Mixer mixer) {
+        int res = 0;
+        try {
+            println("Getting clip from mixer...");
+            source = (Clip) mixer.getLine(info);
+            println("Opening clip...");
+            source.open(audioFormat, audioData, 0, audioData.length);
+            println("Starting clip...");
+            source.loop(Clip.LOOP_CONTINUOUSLY);
+            println("Now open your ears:");
+            println("- if you hear a sine wave playing,");
+            println("  listen carefully if you can hear clicks.");
+            println("  If no, the bug is fixed.");
+            println("- if you don't hear anything, it's possible");
+            println("  that this mixer is not connected to an ");
+            println("  amplifier, or that its volume is set to 0");
+            key();
+        } catch (IllegalArgumentException iae) {
+            println("IllegalArgumentException: "+iae.getMessage());
+            println("Sound device cannot handle this audio format.");
+            println("ERROR: Test environment not correctly set up.");
+            if (source!=null) {
+                source.close();
+                source = null;
+            }
+            return;
+        } catch (LineUnavailableException lue) {
+            println("LineUnavailableException: "+lue.getMessage());
+            println("This is normal for some mixers.");
+        } catch (Exception e) {
+            println("Unexpected Exception: "+e.toString());
+        }
+        if (source != null) {
+            println("Stopping...");
+            source.stop();
+            println("Closing...");
+            source.close();
+            println("Closed.");
+            source = null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        println("This is an interactive test.");
+        println("If you can hear clicks during playback in");
+        println("any mixer, the test is failed.");
+        println("");
+        println("Make sure that you have speakers connected");
+        println("and that the system mixer is not muted.");
+        println("");
+        println("Press a key to start the test.");
+        key();
+        Mixer.Info[] mixers=null;
+
+            println("   ...using self-generated sine wave for playback");
+            audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
+            for (int i=0; i<audioData.length; i++) {
+                audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+            }
+        info = new DataLine.Info(Clip.class, audioFormat);
+
+        mixers = AudioSystem.getMixerInfo();
+        int succMixers = 0;
+        for (int i=0; i<mixers.length; i++) {
+            try {
+                Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                if (mixer.isLineSupported(info)) {
+                    succMixers++;
+                    println("  ...using mixer "+mixer.getMixerInfo());
+                    play(mixer);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (succMixers == 0) {
+                println("No mixers available! ");
+                println("Cannot run test.");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/ClickInPlay/Test4218609.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,380 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.Button;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @test
+ * @bug 4218609
+ * @summary A soft audio click is heard when playing some audio file
+ * @build ClickInPlay
+ * @run main/manual Test4218609
+ */
+public class Test4218609 {
+
+   private static void init() throws Exception {
+        //*** Create instructions for the user here ***
+
+        String[] instructions =
+        {
+         "To run the test follow these instructions:",
+         "1. Open a terminal window.",
+         "2. Type \"cd " + System.getProperty("test.classes") + "\".",
+         "3. Type \"" + System.getProperty("java.home") + "/bin/java ClickInPlay\".",
+         "4. Follow the instructions shown in the terminal window.",
+         "If no error occured during the test, and the java application ",
+         "in the termial exited successfully, press PASS, else press FAIL."
+       };
+
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+    }
+
+ /*****************************************************
+     Standard Test Machinery Section
+      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+   ******************************************************/
+   private static boolean theTestPassed = false;
+   private static boolean testGeneratedInterrupt = false;
+   private static String failureMessage = "";
+
+   private static Thread mainThread = null;
+
+   private static int sleepTime = 300000;
+
+   public static void main( String args[] ) throws Exception
+    {
+      mainThread = Thread.currentThread();
+      try
+       {
+         init();
+       }
+      catch( TestPassedException e )
+       {
+         //The test passed, so just return from main and harness will
+         // interepret this return as a pass
+         return;
+       }
+      //At this point, neither test passed nor test failed has been
+      // called -- either would have thrown an exception and ended the
+      // test, so we know we have multiple threads.
+
+      //Test involves other threads, so sleep and wait for them to
+      // called pass() or fail()
+      try
+       {
+         Thread.sleep( sleepTime );
+         //Timed out, so fail the test
+         throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
+       }
+      catch (InterruptedException e)
+       {
+         if( ! testGeneratedInterrupt ) throw e;
+
+         //reset flag in case hit this code more than once for some reason (just safety)
+         testGeneratedInterrupt = false;
+         if ( theTestPassed == false )
+          {
+            throw new RuntimeException( failureMessage );
+          }
+       }
+
+    }//main
+
+   public static synchronized void setTimeoutTo( int seconds )
+    {
+      sleepTime = seconds * 1000;
+    }
+
+   public static synchronized void pass()
+    {
+      Sysout.println( "The test passed." );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //first check if this is executing in main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //Still in the main thread, so set the flag just for kicks,
+         // and throw a test passed exception which will be caught
+         // and end the test.
+         theTestPassed = true;
+         throw new TestPassedException();
+       }
+      //pass was called from a different thread, so set the flag and interrupt
+      // the main thead.
+      theTestPassed = true;
+      testGeneratedInterrupt = true;
+      mainThread.interrupt();
+    }//pass()
+
+   public static synchronized void fail()
+    {
+      //test writer didn't specify why test failed, so give generic
+      fail( "it just plain failed! :-)" );
+    }
+
+   public static synchronized void fail( String whyFailed )
+    {
+      Sysout.println( "The test failed: " + whyFailed );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //check if this called from main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //If main thread, fail now 'cause not sleeping
+         throw new RuntimeException( whyFailed );
+       }
+      theTestPassed = false;
+      testGeneratedInterrupt = true;
+      failureMessage = whyFailed;
+      mainThread.interrupt();
+    }//fail()
+
+ }// class Orient
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+
+//************ Begin classes defined for the test ****************
+
+// make listeners in a class defined here, and instantiate them in init()
+
+/* Example of a class which may be written as part of a test
+class NewClass implements anInterface
+ {
+   static int newVar = 0;
+
+   public void eventDispatched(AWTEvent e)
+    {
+      //Counting events to see if we get enough
+      eventCount++;
+
+      if( eventCount == 20 )
+       {
+         //got enough events, so pass
+
+         Orient.pass();
+       }
+      else if( tries == 20 )
+       {
+         //tried too many times without getting enough events so fail
+
+         Orient.fail();
+       }
+
+    }// eventDispatched()
+
+ }// NewClass class
+
+*/
+
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+   Panel  buttonP = new Panel();
+   Button passB = new Button( "pass" );
+   Button failB = new Button( "fail" );
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      passB = new Button( "pass" );
+      passB.setActionCommand( "pass" );
+      passB.addActionListener( this );
+      buttonP.add( "East", passB );
+
+      failB = new Button( "fail" );
+      failB.setActionCommand( "fail" );
+      failB.addActionListener( this );
+      buttonP.add( "West", failB );
+
+      add( "South", buttonP );
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+   //catch presses of the passed and failed buttons.
+   //simply call the standard pass() or fail() static methods of
+   //DialogOrient
+   public void actionPerformed( ActionEvent e )
+    {
+      if( e.getActionCommand() == "pass" )
+       {
+         Test4218609.pass();
+       }
+      else
+       {
+         Test4218609.fail();
+       }
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/ClipOpenException.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,148 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 4679187
+ * @summary Clip.open() throws unexpected Exceptions. verifies that clip,
+ *          sourcedataline and targetdataline throw IllegalArgumentExcepotion if
+ *          any field in the format is AudioFormat.NOT_SPECIFIED
+ */
+public class ClipOpenException {
+    static boolean failed = false;
+
+    static byte[] audioData = new byte[2048];
+    static AudioFormat[] formats = {
+        new AudioFormat(AudioSystem.NOT_SPECIFIED,
+                        AudioSystem.NOT_SPECIFIED,
+                        AudioSystem.NOT_SPECIFIED,
+                        true, false),
+        new AudioFormat(0, 0, 0, true, false)
+    };
+    static AudioFormat infoFormat = new AudioFormat(44100.0f,
+                                                16,
+                                                1,
+                                                true, false);
+    static DataLine.Info clipInfo = new DataLine.Info(Clip.class, infoFormat);
+    static DataLine.Info sdlInfo = new DataLine.Info(SourceDataLine.class, infoFormat);
+    static DataLine.Info tdlInfo = new DataLine.Info(TargetDataLine.class, infoFormat);
+
+
+    public static void print(String s) {
+        System.out.print(s);
+    }
+    public static void println(String s) {
+        System.out.println(s);
+    }
+
+    public static void test(Line line) {
+        for (int format = 0; format < formats.length; format++) {
+            try {
+                println("  Opening the line with format "+(format+1));
+                if (line instanceof Clip) {
+                    ((Clip) line).open(formats[format], audioData, 0, audioData.length);
+                } else
+                if (line instanceof SourceDataLine) {
+                    ((SourceDataLine) line).open(formats[format]);
+                } else
+                if (line instanceof TargetDataLine) {
+                    ((TargetDataLine) line).open(formats[format]);
+                } else {
+                    println("    Unknown type of line: "+line.getClass());
+                    return;
+                }
+                println("    No exception! not OK.");
+                failed = true;
+            } catch (IllegalArgumentException iae) {
+                println("    IllegalArgumentException: "+iae.getMessage());
+                println("    OK");
+            } catch (LineUnavailableException lue) {
+                println("    LineUnavailableException: "+lue.getMessage());
+                println("    Probably incorrect, but may happen if the test system is correctly set up.");
+            } catch (Exception e) {
+                println("    Unexpected Exception: "+e.toString());
+                println("    NOT OK!");
+                failed = true;
+            }
+            println("    Closing line.");
+            line.close();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+        int succMixers = 0;
+        println("Using formats: ");
+        for (int i = 0 ; i<formats.length; i++) {
+                println(""+(i+1)+". "+formats[i]);
+        }
+        for (int i=0; i<mixers.length; i++) {
+            boolean succ = false;
+            try {
+                Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                println("Mixer "+mixer.getMixerInfo()+":");
+                if (mixer.isLineSupported(clipInfo)) {
+                    println("Getting clip from mixer...");
+                    Clip clip = (Clip) mixer.getLine(clipInfo);
+                    succ = true;
+                    test(clip);
+                }
+                if (mixer.isLineSupported(sdlInfo)) {
+                    println("Getting source data line from mixer...");
+                    SourceDataLine sdl = (SourceDataLine) mixer.getLine(sdlInfo);
+                    succ = true;
+                    test(sdl);
+                }
+                if (mixer.isLineSupported(tdlInfo)) {
+                    println("Getting target data line from mixer...");
+                    TargetDataLine tdl = (TargetDataLine) mixer.getLine(tdlInfo);
+                    succ = true;
+                    test(tdl);
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if (succ) {
+                succMixers++;
+            }
+        }
+        if (succMixers == 0) {
+            println("No mixers available! ");
+            println("Cannot run test. NOT FAILED");
+        }
+        else if (failed) {
+            throw new Exception("Test FAILED");
+        }
+        println("Test passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/FrameSize/FrameSizeTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4469409
+ * @summary Check that the frame size in the formats returned by lines is
+ *          correct
+ */
+public class FrameSizeTest {
+    public static void main(String[] args) throws Exception {
+        boolean res=true;
+        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
+        for (int i = 0; i < mixerInfo.length; i++) {
+            Mixer mixer = AudioSystem.getMixer(mixerInfo[i]);
+            System.out.println(mixer);
+            Line.Info[] lineinfo = mixer.getSourceLineInfo();
+            for (int j = 0; j < lineinfo.length; j++) {
+                System.out.println("  " + lineinfo[j]);
+                try {
+                    AudioFormat[] formats = ((DataLine.Info)lineinfo[j]).getFormats();
+                    for (int k = 0; k < formats.length; k++) {
+                        if ( (formats[k].getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
+                              || formats[k].getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED))
+                             && (formats[k].getFrameSize() != AudioSystem.NOT_SPECIFIED)
+                             && ((formats[k].getSampleSizeInBits() == 16) || (formats[k].getSampleSizeInBits() == 8))
+                             && ((((formats[k].getSampleSizeInBits() + 7) / 8) * formats[k].getChannels()) != formats[k].getFrameSize())) {
+                            System.out.println(" # " + formats[k] + ", getFrameSize() wrongly returns"+ formats[k].getFrameSize());
+                            res=false;
+                        }
+                    }
+                } catch (ClassCastException e) {
+                }
+            }
+        }
+
+        if (res) {
+            System.out.println("Test passed");
+        } else {
+            System.out.println("Test failed");
+            throw new Exception("Test failed");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/GetLine.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,99 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioPermission;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4932835
+ * @summary REGRESSION: IAE for supported line in AudioSystem.getLine()
+ */
+public class GetLine {
+
+    static boolean isSoundAccessDenied = false;
+    static {
+        SecurityManager securityManager = System.getSecurityManager();
+        if (securityManager != null) {
+            try {
+                securityManager.checkPermission(new AudioPermission("*"));
+            } catch (SecurityException e) {
+                isSoundAccessDenied = true;
+            }
+        }
+    }
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+    static final int STATUS_TEMP = 95;
+    static java.io.PrintStream log = System.err;
+
+    public static void main(String argv[]) throws Exception {
+        if (run(argv, System.out) == STATUS_FAILED) {
+            throw new Exception("Test FAILED");
+        }
+        System.out.println("Test passed.");
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) {
+        String testCaseID = "LineListener2001";
+
+        log.println("===== " + testCaseID + " =====");
+
+        boolean failed = false;
+        Line l = null;
+
+
+
+        // get the default SourceDataLine
+
+        DataLine.Info s_info = new DataLine.Info(SourceDataLine.class, null);
+        Line.Info infos[] = AudioSystem.getSourceLineInfo( s_info );
+
+        if( infos.length < 1 ) {
+            log.println("Line.Info array == 0");
+            return STATUS_PASSED;
+        }
+        try {
+            l = AudioSystem.getLine(infos[0]);
+        } catch(SecurityException lue) {
+            log.println("SecurityException");
+            return STATUS_PASSED;
+        } catch (LineUnavailableException e1) {
+            log.println("LUE");
+            return STATUS_PASSED;
+        } catch (IllegalArgumentException iae) {
+            log.println("IllegalArgumentException should not be thrown "
+                     + "for supported line");
+            iae.printStackTrace(log);
+            return STATUS_FAILED;
+        }
+        out.println("Passed.");
+        return STATUS_PASSED;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/SDLwrite.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,271 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4680710
+ * @summary SourceDataLine.write() behavior is not correct for not open or not
+ *          started lines
+ */
+public class SDLwrite {
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+
+    public static void main(String argv[]) throws Exception {
+        int testExitStatus = run(argv, System.out);
+        if (testExitStatus != STATUS_PASSED) {
+            throw new Exception("test FAILED!");
+        }
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) {
+        int testResult = STATUS_PASSED;
+
+        out.println
+            ("\n==> Test for SourceDataLine.write() method for not open and not started line:");
+
+        Mixer.Info[] installedMixersInfo = AudioSystem.getMixerInfo();
+
+        if ( installedMixersInfo == null ) {
+            out.println("## AudioSystem.getMixerInfo() returned unexpected result:");
+            out.println("#  expected: an array of Mixer.Info objects (may be array of length 0);");
+            out.println("#  produced: null;");
+            return STATUS_FAILED;
+        }
+
+        if ( installedMixersInfo.length == 0 ) {
+            // there are no mixers installed on the system - so this testcase can not be tested
+            return STATUS_PASSED;
+        }
+
+        Mixer testedMixer = null;
+        for (int i=0; i < installedMixersInfo.length; i++) {
+            try {
+                testedMixer = AudioSystem.getMixer(installedMixersInfo[i]);
+            } catch (SecurityException securityException) {
+                // installed Mixer is unavailable because of security restrictions
+                continue;
+            } catch (Throwable thrown) {
+                out.println("## AudioSystem.getMixer() threw unexpected exception:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                continue;
+            }
+
+            try {
+                testedMixer.open();
+            } catch (LineUnavailableException lineUnavailableException) {
+                // testedMixer is not available due to resource restrictions
+                continue;
+            } catch (SecurityException securityException) {
+                // testedMixer is not available due to security restrictions
+                continue;
+            } catch (Throwable thrown) {
+                out.println("## Mixer.open() threw unexpected exception:");
+                out.println("#  Mixer = " + testedMixer);
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                continue;
+            }
+            Line.Info supportedSourceLineInfo[] = null;
+            try {
+                supportedSourceLineInfo = testedMixer.getSourceLineInfo();
+            } catch (Throwable thrown) {
+                out.println("## Mixer.getSourceLineInfo() threw unexpected exception:");
+                out.println("#  Mixer = " + testedMixer);
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                testedMixer.close();
+                continue;
+            }
+            if ( supportedSourceLineInfo == null ) {
+                out.println("## Mixer.getSourceLineInfo() returned null array");
+                out.println("#  Mixer = " + testedMixer);
+                testResult = STATUS_FAILED;
+                testedMixer.close();
+                continue;
+            }
+            out.println("\n>>>  testedMixer["+i+"] = " + testedMixer);
+            out.println("\n>>  supportedSourceLineInfo.length = " + supportedSourceLineInfo.length);
+
+            for (int j=0; j < supportedSourceLineInfo.length; j++) {
+                Line.Info testSourceLineInfo = supportedSourceLineInfo[j];
+
+                Line testSourceLine = null;
+                try {
+                    testSourceLine = testedMixer.getLine(testSourceLineInfo);
+                } catch (LineUnavailableException lineUnavailableException) {
+                    // line is not available due to resource restrictions
+                    continue;
+                } catch (SecurityException securityException) {
+                    // line is not available due to security restrictions
+                    continue;
+                } catch (Throwable thrown) {
+                    out.println("## Mixer.getLine(Line.Info) threw unexpected Exception:");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  Line.Info = " + testSourceLineInfo);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                    continue;
+                }
+
+                out.println("\n>  testSourceLineInfo["+j+"] = " + testSourceLineInfo);
+                out.println(">  testSourceLine = " + testSourceLine);
+                if ( ! (testSourceLine instanceof SourceDataLine) ) {
+                    out.println(">  testSourceLine is not SourceDataLine");
+                    continue;
+                }
+
+                SourceDataLine testedSourceLine = (SourceDataLine)testSourceLine;
+                AudioFormat lineAudioFormat = testedSourceLine.getFormat();
+
+                int bufferSizeToWrite = 1;
+                if ( lineAudioFormat.getSampleSizeInBits() != AudioSystem.NOT_SPECIFIED ) {
+                    bufferSizeToWrite = lineAudioFormat.getSampleSizeInBits()/8;
+                    if ( lineAudioFormat.getSampleSizeInBits()%8 != 0 ) {
+                        bufferSizeToWrite++;
+                    }
+                }
+                if ( lineAudioFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED ) {
+                    bufferSizeToWrite = lineAudioFormat.getFrameSize();
+                }
+                byte[] dataToWrite = new byte[bufferSizeToWrite];
+                for (int k=0; k < bufferSizeToWrite; k++) {
+                    dataToWrite[k] = (byte)1;
+                }
+                int offsetToWrite = 0;
+
+                out.println
+                    ("\n>  check SourceDataLine.write() for not open line with correct length of data:");
+                int writtenBytes = -1;
+                try {
+                    writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
+                    out.println(">  Bytes written: number of written bytes = " + writtenBytes);
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                }
+
+                out.println
+                    ("\n>  check SourceDataLine.write() for not open line with incorrect length of data:");
+                writtenBytes = -1;
+                bufferSizeToWrite--;
+                try {
+                    writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
+                    out.println(">  Bytes written: number of written bytes = " + writtenBytes);
+                } catch (IllegalArgumentException illegalArgumentException) {
+                    out.println(">  Permissible IllegalArgumentException for the present instance is thrown:");
+                    illegalArgumentException.printStackTrace(out);
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                }
+
+                out.println
+                    ("\n>  open tested line:");
+                bufferSizeToWrite++;
+                try {
+                    testedSourceLine.open(lineAudioFormat, bufferSizeToWrite);
+                    out.println(">  OK - line is opened");
+                } catch (LineUnavailableException lineUnavailableException) {
+                    out.println(">  Line is not available due to resource restrictions:");
+                    lineUnavailableException.printStackTrace(out);
+                    continue;
+                } catch (SecurityException securityException) {
+                    out.println("> Line is not available due to security restrictions:");
+                    securityException.printStackTrace(out);
+                    continue;
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.open(AudioFormat format) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                    continue;
+                }
+
+                out.println
+                    ("\n>  check SourceDataLine.write() for not started line with correct length of data:");
+                writtenBytes = -1;
+                try {
+                    writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
+                    out.println(">  Bytes written: number of written bytes = " + writtenBytes);
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                }
+
+                out.println
+                    ("\n>  check SourceDataLine.write() for not started line with incorrect length of data:");
+                writtenBytes = -1;
+                bufferSizeToWrite--;
+                try {
+                    writtenBytes = testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
+                    out.println(">  Bytes written: number of written bytes = " + writtenBytes);
+                } catch (IllegalArgumentException illegalArgumentException) {
+                    out.println(">  Permissible IllegalArgumentException for the present instance is thrown:");
+                    illegalArgumentException.printStackTrace(out);
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + testedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                }
+                testedSourceLine.close();
+
+            }  // for (int j=0; j < supportedSourceLineInfo.length; j++)
+            testedMixer.close();
+
+        }  // for (int i=0; i < installedMixersInfo.length; i++)
+
+        if ( testResult == STATUS_FAILED ) {
+            out.println("\n==> test FAILED!");
+        } else {
+            out.println("\n==> test PASSED!");
+        }
+        return testResult;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/SourceDataLineDefaultBufferSizeCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,248 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4681384
+ * @summary SourceDataLine.write() causes Unexpected Signal 11 in native code
+ *          outside the VM
+ */
+public class SourceDataLineDefaultBufferSizeCrash {
+
+    static final int STATUS_PASSED = 0;
+    static final int STATUS_FAILED = 2;
+    static final int STATUS_TEMP = 95;
+
+    public static void main(String argv[]) throws Exception {
+        int testExitStatus = run(argv, System.out) + STATUS_TEMP;
+    }
+
+    public static int run(String argv[], java.io.PrintStream out) throws Exception {
+        int testResult = STATUS_PASSED;
+
+        int framesNumberToExceed = 2;
+        if ( argv.length > 0 ) {
+            try {
+                framesNumberToExceed = Integer.parseInt(argv[0]);
+            }
+            catch (NumberFormatException e) {
+            }
+        }
+
+        out.println
+            ("\n==> Test for SourceDataLine.write() method:");
+
+        Mixer.Info[] installedMixersInfo = AudioSystem.getMixerInfo();
+
+        if ( installedMixersInfo == null ) {
+            out.println("## AudioSystem.getMixerInfo() returned unexpected result:");
+            out.println("#  expected: an array of Mixer.Info objects (may be array of length 0);");
+            out.println("#  produced: null;");
+            return STATUS_FAILED;
+        }
+
+        if ( installedMixersInfo.length == 0 ) {
+            // there are no mixers installed on the system -
+            // so this testcase can not be tested
+            out.println("\n>>>  There are no mixers installed on the system!");
+            return STATUS_PASSED;
+        }
+
+        out.println("\n>>>  Number of mixers installed on the system = "
+            + installedMixersInfo.length);
+        Mixer installedMixer = null;
+        for (int i=0; i < installedMixersInfo.length; i++) {
+            try {
+                installedMixer = AudioSystem.getMixer(installedMixersInfo[i]);
+            } catch (SecurityException securityException) {
+                // installed Mixer is unavailable because of security restrictions
+                out.println("\n>>>  installedMixer[" + i
+                    + "] is unavailable because of security restrictions");
+                continue;
+            } catch (Throwable thrown) {
+                out.println("\n##  installedMixer[" + i + "] is unavailable because of");
+                out.println("#  AudioSystem.getMixer() threw unexpected exception:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                continue;
+            }
+
+            out.println("\n>>>  installedMixer["+i+"] = " + installedMixer);
+            try {
+                installedMixer.open();
+            } catch (LineUnavailableException lineUnavailableException) {
+                // installedMixer is not available due to resource restrictions
+                out.println(">>   installedMixer[" + i
+                    + "] is not opened because of resource restrictions");
+                continue;
+            } catch (SecurityException securityException) {
+                // installedMixer is not available due to security restrictions
+                out.println(">>   installedMixer[" + i
+                    + "] is not opened because of security restrictions");
+                continue;
+            } catch (Throwable thrown) {
+                out.println("## installedMixer.open() throws unexpected exception:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                continue;
+            }
+            Line.Info supportedSourceLineInfo[] = null;
+            try {
+                supportedSourceLineInfo = installedMixer.getSourceLineInfo();
+            } catch (Throwable thrown) {
+                out.println("## installedMixer.getSourceLineInfo() throws "
+                    + "unexpected exception:");
+                thrown.printStackTrace(out);
+                testResult = STATUS_FAILED;
+                installedMixer.close();
+                continue;
+            }
+            if ( supportedSourceLineInfo == null ) {
+                out.println("## installedMixer.getSourceLineInfo() returned null array");
+                out.println("#  Mixer = " + installedMixer);
+                testResult = STATUS_FAILED;
+                installedMixer.close();
+                continue;
+            }
+            out.println("\n>>  Number of SourceLineInfo supported by installedMixer ="
+                + supportedSourceLineInfo.length);
+
+            for (int j=0; j < supportedSourceLineInfo.length; j++) {
+                Line.Info testSourceLineInfo = supportedSourceLineInfo[j];
+
+                out.println("\n>  testSourceLineInfo["+j+"] = " + testSourceLineInfo);
+                Line testSourceLine = null;
+                try {
+                    testSourceLine = installedMixer.getLine(testSourceLineInfo);
+                } catch (LineUnavailableException lineUnavailableException) {
+                    // line is not available due to resource restrictions
+                    out.println(">  Line for this SourceLine Info is not available "
+                        + "due to resource restrictions");
+                    continue;
+                } catch (SecurityException securityException) {
+                    // line is not available due to security restrictions
+                    out.println(">  Line for this SourceLine Info is not available "
+                        + "due to security restrictions");
+                    continue;
+                } catch (Throwable thrown) {
+                    out.println("## installedMixer.getLine(testSourceLineInfo) throws"
+                        + "unexpected Exception:");
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                    continue;
+                }
+
+                out.println(">  testedSourceLine = " + testSourceLine);
+                if ( ! (testSourceLine instanceof SourceDataLine) ) {
+                    out.println(">  testSourceLine is not SourceDataLine");
+                    continue;
+                }
+
+                SourceDataLine testedSourceLine = (SourceDataLine)testSourceLine;
+                AudioFormat lineAudioFormat = testedSourceLine.getFormat();
+
+                out.println("\n>  opening tested SourceLine:");
+                try {
+                    //testedSourceLine.open(lineAudioFormat, 2048);
+                    testedSourceLine.open(lineAudioFormat);
+                    out.println(">  OK - line is opened with "+testedSourceLine.getBufferSize()+" bytes buffer");
+                } catch (LineUnavailableException lineUnavailableException) {
+                    out.println(">  Line is not available due to resource restrictions:");
+                    lineUnavailableException.printStackTrace(out);
+                    continue;
+                } catch (SecurityException securityException) {
+                    out.println("> Line is not available due to security restrictions:");
+                    securityException.printStackTrace(out);
+                    continue;
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.open(AudioFormat format) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    out.println("#  Mixer = " + installedMixer);
+                    out.println("#  SourceDataLine = " + testedSourceLine);
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                    continue;
+                }
+
+                testedSourceLine.start();
+
+                int frameSize = 1;
+                if ( lineAudioFormat.getFrameSize() != AudioSystem.NOT_SPECIFIED ) {
+                    frameSize = lineAudioFormat.getFrameSize();
+                } else {
+                    if ( lineAudioFormat.getSampleSizeInBits() != AudioSystem.NOT_SPECIFIED ) {
+                        frameSize = lineAudioFormat.getSampleSizeInBits()/8;
+                        if ( lineAudioFormat.getSampleSizeInBits()%8 != 0 ) {
+                            frameSize++;
+                        }
+                    }
+                }
+                int bufferSizeToWrite = testedSourceLine.available()
+                    + (frameSize * framesNumberToExceed);
+                byte[] dataToWrite = new byte[bufferSizeToWrite];
+                for (int k=0; k < bufferSizeToWrite; k++) {
+                    dataToWrite[k] = (byte)1;
+                }
+                int offsetToWrite = 0;
+
+                out.println("\n>  check SourceDataLine.write() to write more data "
+                    + "than can currently be written:");
+
+                out.println(">  testedSourceLine.available() = " + testedSourceLine.available());
+                out.println(">  frame size = " + frameSize);
+                out.println(">  number of bytes to write = " + bufferSizeToWrite);
+                int writtenBytes = -1;
+                try {
+                    writtenBytes =
+                        testedSourceLine.write(dataToWrite, offsetToWrite, bufferSizeToWrite);
+                    out.println(">  OK - number of written bytes = " + writtenBytes);
+                } catch (Throwable thrown) {
+                    out.println("## SourceDataLine.write(byte[] b, int off, int len) failed:");
+                    out.println("#  Unexpected Exception is thrown");
+                    thrown.printStackTrace(out);
+                    testResult = STATUS_FAILED;
+                }
+
+                testedSourceLine.close();
+
+            }  // for (int j=0; j < supportedSourceLineInfo.length; j++)
+            installedMixer.close();
+
+        }  // for (int i=0; i < installedMixersInfo.length; i++)
+
+        if ( testResult == STATUS_FAILED ) {
+            throw new Exception("Test FAILED!");
+        } else {
+            out.println("\n==> test PASSED!");
+        }
+        return testResult;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Lines/StopStart.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,282 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.util.Random;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4828556
+ * @summary stopping and starting sampled audio plays small chunk in infinite
+ *          loop
+ */
+public class StopStart implements Runnable {
+
+    static int sampleRate = 8000;
+    static double frequency = 2000.0;
+    static double RAD = 2.0 * Math.PI;
+    static Random random = new Random();
+
+    static byte[] audioData = new byte[sampleRate/2];
+    static SourceDataLine source;
+
+    static boolean terminated = false;
+
+    static int buffersWritten = 0;
+    static long bytesWritten = 0;
+    static int buffersWrittenAfter5Seconds;
+
+    static AudioInputStream ais = null;
+    static AudioFormat audioFormat;
+    static String filename;
+
+    static int executedTests=0;
+    static int successfulTests = 0;
+
+    public static void constructAIS() throws Exception {
+        ais = AudioSystem.getAudioInputStream(new File(filename));
+    }
+
+    public static void doStartStopTest1() throws Exception {
+        System.out.println("TEST 1: play for 3 seconds, stop/start/stop/start/play for 3 seconds...");
+        source.start();
+        Thread.sleep(100);
+        bytesWritten = 0;
+        System.out.println("Waiting for 3 seconds...");
+        Thread.sleep(3000);
+        buffersWrittenAfter5Seconds = buffersWritten;
+        System.out.println("Buffers Written: "+buffersWritten);
+        System.out.println("stop()->start()->stop()->start()");
+        source.stop();
+        //System.out.println("start()");
+        source.start();
+        //System.out.println("stop()2 ----------------------------------------------------------");
+        source.stop();
+        //System.out.println("start()");
+        source.start();
+        System.out.println("Buffers Written: "+buffersWritten);
+        System.out.println("Waiting for 3 seconds...");
+        Thread.sleep(3000);
+        System.out.println("Buffers Written: "+buffersWritten);
+        if (buffersWritten >= ((buffersWrittenAfter5Seconds * 2) - ((buffersWrittenAfter5Seconds / 4)))) {
+            successfulTests++;
+        }
+    }
+
+    private static int nextWaitTime() {
+        int waitTime = random.nextInt(25);
+        waitTime*=waitTime;
+        if (waitTime<20) waitTime = 0;
+        return waitTime;
+    }
+
+
+    public static void doStartStopTest2() throws Exception {
+        System.out.println("TEST 2: start and stop 100 times with random wait in between");
+        int max=100;
+        for (int i=0; i<max; i++) {
+            System.out.println("Round "+i);
+            System.out.println("Start....");
+            source.start();
+            int waitTime = nextWaitTime();
+            System.out.println("Waiting for "+waitTime+"ms...");
+            if (waitTime>0) {
+                Thread.sleep(waitTime);
+            }
+            System.out.println("stop()");
+            source.stop();
+            waitTime = nextWaitTime();
+            System.out.println("Waiting for "+waitTime+"ms...");
+            if (waitTime>0) {
+                Thread.sleep(waitTime);
+            }
+        }
+    }
+
+    public static void doStartStopTest3() throws Exception {
+        System.out.println("TEST 3: start and stop 100 times with random wait only every 10 rounds ");
+        int max=100;
+        for (int i=0; i<max; i++) {
+            System.out.println("Round "+i);
+            System.out.println("Start....");
+            source.start();
+            if (i % 10 == 9) {
+                int waitTime = nextWaitTime();
+                System.out.println("Waiting for "+waitTime+"ms...");
+                if (waitTime>0) {
+                    Thread.sleep(waitTime);
+                }
+            }
+            System.out.println("stop()");
+            source.stop();
+            if (i % 13 == 12) {
+                int waitTime = nextWaitTime();
+                System.out.println("Waiting for "+waitTime+"ms...");
+                if (waitTime>0) {
+                    Thread.sleep(waitTime);
+                }
+            }
+        }
+    }
+
+    public static void runTest(int testNum) {
+        terminated = false;
+        Thread thread = null;
+        buffersWrittenAfter5Seconds = 0;
+        // make the tests reproduceable by always seeding with same value
+        random.setSeed(1);
+        try {
+            executedTests++;
+            thread = new Thread(new StopStart());
+            thread.start();
+            switch (testNum) {
+            case 1: doStartStopTest1(); break;
+            case 2: doStartStopTest2(); break;
+            case 3: doStartStopTest3(); break;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        source.stop();
+        source.close();
+        if (thread!=null) {
+            terminated = true;
+            System.out.println("Waiting for thread to die...");
+            try {
+                thread.join();
+            } catch (InterruptedException ie) {
+                ie.printStackTrace();
+            }
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        filename = null;
+        if (args.length>0) {
+            File f = new File(args[0]);
+            if (f.exists()) {
+                filename = args[0];
+                System.out.println("Opening "+filename);
+                constructAIS();
+                audioFormat = ais.getFormat();
+            }
+        }
+        if (filename == null) {
+            audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
+            for (int i=0; i<audioData.length; i++) {
+                audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+            }
+        }
+        long startTime = System.currentTimeMillis();
+        Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+        for (int i=0; i<mixers.length; i++) {
+            try {
+                Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
+                String mixerName = mixer.getMixerInfo().getName();
+                try {
+                    source = (SourceDataLine) mixer.getLine(info);
+                    source.open(audioFormat);
+                } catch (IllegalArgumentException iae) {
+                    System.out.println("Mixer "+mixerName+" does not provide a SourceDataLine.");
+                    continue;
+                } catch (LineUnavailableException lue) {
+                    System.out.println("Mixer "+mixerName+": no lines available.");
+                    continue;
+                }
+                System.out.println("***** Testing on Mixer "+mixerName+":");
+                //runTest(2);
+                //runTest(3);
+                runTest(1);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (mixers.length==0) {
+            System.out.println("No mixers available!");
+        } else {
+            long duration = System.currentTimeMillis() - startTime;
+
+            System.out.println("Test took "+(duration/1000)+"s and "+(duration % 1000)+"ms.");
+        }
+
+        System.out.println("Exiting main()");
+        if (executedTests>0) {
+            if (successfulTests == 0) {
+                if (args.length == 0) {
+                    throw new Exception("Test FAILED");
+                }
+                System.out.println("test FAILED.");
+            } else {
+                System.out.println("test successful.");
+            }
+        } else {
+            System.out.println("Could not execute any tests - are soundcards correctly installed?");
+            System.out.println("Test NOT FAILED.");
+        }
+    }
+
+    public void run() {
+        int len = audioData.length;
+        int offset = len;
+        System.out.println("Thread: started. Beginning audio i/o");
+        while (!terminated) {
+            try {
+                //if (!source.isActive()) {
+                //      Thread.sleep(50);
+                //}
+                if (offset >= len) {
+                    offset = 0;
+                    if (ais!=null) {
+                        do {
+                            len = ais.read(audioData, 0, audioData.length);
+                            if (len < 0) {
+                                constructAIS();
+                            }
+                        } while (len < 0);
+                    }
+                }
+                int toWrite = len - offset;
+                int written = source.write(audioData, offset, toWrite);
+                offset+=written;
+                bytesWritten += written;
+                buffersWritten = (int) (bytesWritten / audioData.length);
+            } catch (Exception e) {
+                e.printStackTrace();
+                terminated = true;
+            }
+        }
+        System.out.println("Thread: closing line");
+        source.stop();
+        source.close();
+        System.out.println("Thread finished");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/LinuxBlock/PlaySine.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,269 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4834461
+ * @summary Applet hang when you load it during sound card is in use
+ * @run main/manual PlaySine
+ */
+public class PlaySine {
+
+    static int sampleRate = 8000;
+    static double frequency = 2000.0;
+    static double RAD = 2.0 * Math.PI;
+
+    static byte[] audioData = new byte[sampleRate/2];
+    static SourceDataLine source;
+    static Mixer mixer = null;
+
+    static AudioInputStream ais = null;
+    static AudioFormat audioFormat;
+    static String filename;
+
+    public static void constructAIS() {
+        try {
+            ais = AudioSystem.getAudioInputStream(new File(filename));
+        } catch (Exception e) {
+            println("ERROR: could not open "+filename+": "+e.getMessage());
+        }
+    }
+
+    public static void print(String s) {
+        System.out.print(s);
+    }
+    public static void println(String s) {
+        System.out.println(s);
+    }
+
+    public static void key() {
+        println("");
+        print("Press ENTER to continue...");
+        try {
+            System.in.read();
+        } catch (IOException ioe) {
+        }
+    }
+
+    static int audioLen = -1;
+    static int audioOffset = -1;
+
+    public static void writeData() {
+        if (audioLen == -1) {
+            audioLen = audioData.length;
+        }
+        if (audioOffset < 0) {
+            audioOffset = audioLen;
+        }
+        try {
+            if (audioOffset >= audioLen) {
+                audioOffset = 0;
+                if (ais!=null) {
+                    do {
+                        audioLen = ais.read(audioData, 0, audioData.length);
+                        if (audioLen < 0) {
+                            constructAIS();
+                        }
+                    } while (audioLen < 0);
+                }
+            }
+            int toWrite = audioLen - audioOffset;
+            int written = source.write(audioData, audioOffset, toWrite);
+            audioOffset+=written;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    public static int play(boolean shouldPlay) {
+        int res = 0;
+        DataLine.Info info = new DataLine.Info(SourceDataLine.class, audioFormat);
+        try {
+            println("Getting line from mixer...");
+            source = (SourceDataLine) mixer.getLine(info);
+            println("Opening line...");
+            println("  -- if the program is hanging here, kill the process that has blocks the audio device now.");
+            source.open(audioFormat);
+            println("Starting line...");
+            source.start();
+            println("Writing audio data for 1 second...");
+            long startTime = System.currentTimeMillis();
+            while (System.currentTimeMillis() - startTime < 1000) {
+                writeData();
+                Thread.sleep(100);
+            }
+            res = 1;
+        } catch (IllegalArgumentException iae) {
+            println("IllegalArgumentException: "+iae.getMessage());
+            println("Sound device cannot handle this audio format.");
+            println("ERROR: Test environment not correctly set up.");
+            if (source!=null) {
+                source.close();
+            }
+            return 3;
+        } catch (LineUnavailableException lue) {
+            println("LineUnavailableException: "+lue.getMessage());
+            if (shouldPlay) {
+                println("ERROR: the line should be available now!.");
+                println("       Verify that you killed the other audio process.");
+            } else {
+                println("Correct behavior! the bug is fixed.");
+            }
+            res = 2;
+        } catch (Exception e) {
+            println("Unexpected Exception: "+e.toString());
+        }
+        if (source != null) {
+            println("Draining...");
+            try {
+                source.drain();
+            } catch (NullPointerException npe) {
+                println("(NullPointerException: bug fixed in J2SE 1.4.2");
+            }
+            println("Stopping...");
+            source.stop();
+            println("Closing...");
+            source.close();
+            source = null;
+        }
+        return res;
+    }
+
+    public static void main(String[] args) throws Exception {
+        println("This is an interactive test. You can run it with a filename as argument");
+        println("It is only meant to be run on linux, with the (old) OSS kernel drivers (/dev/dsp)");
+        println("This test should not be run on systems with ALSA installed, or kernel 2.6 or higher.");
+        println("");
+        println("The test verifies that Java Sound fails correctly if another process is blocking");
+        println("the audio device.");
+        println("");
+        println("Checking sanity...");
+        Mixer.Info[] mixers=null;
+
+        mixers = AudioSystem.getMixerInfo();
+        for (int i=0; i<mixers.length; i++) {
+            try {
+                Mixer thisMixer = AudioSystem.getMixer(mixers[i]);
+                String mixerName = thisMixer.getMixerInfo().getName();
+                if (mixerName.indexOf("Java Sound")>=0
+                    && mixerName.indexOf("Engine")>=0) {
+                    mixer = thisMixer;
+                    break;
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        if (mixer == null) {
+            if (mixers.length==0) {
+                System.out.println("ERROR: No mixers available!");
+            } else {
+                println("ERROR: Java Sound Engine could not be found.");
+            }
+            println("Cannot run this test.");
+            return;
+        }
+        println("  ...using mixer "+mixer.getMixerInfo());
+
+        String osname = System.getProperty("os.name");
+        if ((osname == null) || (osname.toLowerCase().indexOf("linux")<0)) {
+            println("ERROR: not running on linux (you are running on "+osname+")");
+            return;
+        }
+        println("  ...running on "+osname);
+        println("  ...sanity test OK.");
+
+        filename = null;
+        if (args.length>0) {
+            File f = new File(args[0]);
+            if (f.exists()) {
+                filename = args[0];
+                println("Opening "+filename);
+                constructAIS();
+                if (ais!=null) {
+                    audioFormat = ais.getFormat();
+                }
+            }
+        }
+        if (ais == null) {
+            println("Using self-generated sine wave for playback");
+            audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
+            for (int i=0; i<audioData.length; i++) {
+                audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+            }
+        }
+
+        println("");
+        println("Now, on a second console, run the following command:");
+        println("    cat - < /dev/zero > /dev/dsp");
+        key();
+        println("After you press ENTER now, the mixer will be opened.");
+        println("There are 3 possible cases that can occur:");
+        println("1) you'll hear a sine wave");
+        println("   -> you are running with mixing OSS drivers. ");
+        println("      Some soundcards only provide mixing OSS drivers.");
+        println("      Test environment not valid. ");
+        println("      Repeat on another machine where you can reproduce the bug first.");
+        println("2) this program stops doing anything after 'Opening line...'");
+        println("   -> this is the bug.");
+        println("      Kill the command on the other console with Ctrl-C, this program");
+        println("      should continue working then.");
+        println("3) this program reports a LineUnavailableException");
+        println("   -> bug is fixed.");
+        println("      OR you run with non-blocking OSS drivers.");
+        println("      make sure that you can reproduce this bug first with e.g. J2SE 1.4.1");
+        key();
+        int playedFirst = play(false);
+        int playedSecond = 0;
+
+        if (playedFirst == 2) {
+            println("");
+            println("Now kill the other process with Ctrl-C.");
+            println("After that, this program should be able to play ");
+            println("the sine wave without problems.");
+            key();
+            playedSecond = play(true);
+        }
+        println("");
+        if (playedFirst == 1) {
+            println("Test FAILED.");
+        }
+        else if (playedFirst == 2 && playedSecond == 1) {
+            println("Test SUCCESSFUL");
+        } else {
+            println("Test not failed (but not successful either...).");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,163 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+
+/**
+ * @test
+ * @bug 4498848
+ * @summary Sound causes crashes on Linux (part 1)
+ */
+public class ClipLinuxCrash {
+
+    static Clip clip;
+
+    public static long bytes2Ms(long bytes, AudioFormat format) {
+        return (long) (bytes / format.getFrameRate() * 1000
+                               / format.getFrameSize());
+    }
+
+    static int staticLen = 1000;
+
+    static boolean addLen = true;
+
+    public static long start() throws Exception {
+        AudioFormat fmt = new AudioFormat(44100, 16, 2, true, false);
+        if (addLen) {
+            staticLen += (int) (staticLen / 5) + 1000;
+        } else {
+            staticLen -= (int) (staticLen / 5) + 1000;
+        }
+        if (staticLen > 8 * 44100 * 4) {
+            staticLen = 8 * 44100 * 4;
+            addLen = !addLen;
+        }
+        if (staticLen < 1000) {
+            staticLen = 1000;
+            addLen = !addLen;
+        }
+        int len = staticLen;
+        len -= (len % 4);
+        byte[] fakedata = new byte[len];
+        InputStream is = new ByteArrayInputStream(fakedata);
+        AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
+                                             44100, 16, 2, 4, 44100, false);
+        AudioInputStream ais = new AudioInputStream(is, format, fakedata.length
+                / format.getFrameSize());
+
+        out("    preparing to play back " + len + " bytes == " + bytes2Ms(len,
+                                                                          format)
+                    + "ms audio...");
+
+        DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
+        clip = (Clip) AudioSystem.getLine(info);
+        clip.addLineListener(new LineListener() {
+            public void update(LineEvent e) {
+                if (e.getType() == LineEvent.Type.STOP) {
+                    out("    calling close() from event dispatcher thread");
+                    ((Clip) e.getSource()).close();
+                } else if (e.getType() == LineEvent.Type.CLOSE) {
+                }
+            }
+        });
+
+        out("    opening...");
+        try {
+            clip.open(ais);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            clip.close();
+            clip = null;
+        }
+        ais.close();
+        if (clip != null) {
+            out("    starting...");
+            clip.start();
+        }
+        return bytes2Ms(fakedata.length, format);
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (AudioSystem.getMixerInfo().length == 0) {
+            System.out.println("Cannot execute test: no mixers installed!");
+            System.out.println("Not Failed.");
+            return;
+        }
+        try {
+            int COUNT = 10;
+            out();
+            out("4498848 Sound causes crashes on Linux (testing with Clip)");
+            if (args.length > 0) {
+                COUNT = Integer.parseInt(args[0]);
+            }
+            for (int i = 0; i < COUNT; i++) {
+                out("  trial " + (i + 1) + "/" + COUNT);
+                start();
+                int waitTime = 500 + (1000 * (i
+                                                      % 2)); // every second
+                // time wait 1500, rather than 500ms.
+                out("    waiting for " + waitTime
+                            + " ms for audio playback to stop...");
+                Thread.sleep(waitTime);
+                out("    calling close() from main thread");
+                if (clip != null) {
+                    clip.close();
+                }
+                // let the subsystem enough time to actually close the soundcard
+                out("    waiting for 2 seconds...");
+                Thread.sleep(2000);
+                out();
+            }
+            out("  waiting for 1 second...");
+            Thread.sleep(1000);
+        } catch (Exception e) {
+            e.printStackTrace();
+            out("  waiting for 1 second");
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ie) {
+            }
+            throw e;
+        }
+        out("Test passed");
+    }
+
+    static void out() {
+        out("");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+        System.out.flush();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/LinuxCrash/ClipLinuxCrash2.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,188 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4498848
+ * @summary Sound causes crashes on Linux (part 3)
+ */
+public class ClipLinuxCrash2 implements LineListener{
+    Clip clip;
+    int stopOccured;
+    static final Object lock = new Object();
+
+    public static long bytes2Ms(long bytes, AudioFormat format) {
+        return (long) (bytes/format.getFrameRate()*1000/format.getFrameSize());
+    }
+
+    static int staticLen=1000;
+    static boolean addLen=true;
+
+    ClipLinuxCrash2() {
+    }
+
+    public void update(LineEvent e) {
+        if (e.getType() == LineEvent.Type.STOP) {
+            stopOccured++;
+            out("  Test program: receives STOP event for clip="+clip.toString()+" no."+stopOccured);
+            out("  Test program: Calling close() in event dispatcher thread");
+            clip.close();
+            synchronized (lock) {
+                lock.notifyAll();
+            }
+        }
+        else if (e.getType() == LineEvent.Type.CLOSE) {
+            out("  Test program: receives CLOSE event for "+clip.toString());
+            synchronized (lock) {
+                lock.notifyAll();
+            }
+        }
+        else if (e.getType() == LineEvent.Type.START) {
+            out("  Test program: receives START event for "+clip.toString());
+        }
+        else if (e.getType() == LineEvent.Type.OPEN) {
+            out("  Test program: receives OPEN event for "+clip.toString());
+        }
+    }
+
+    public long start() throws Exception {
+        AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+
+        if (addLen) {
+            staticLen+=(int) (staticLen/5)+1000;
+        } else {
+            staticLen-=(int) (staticLen/5)+1000;
+        }
+        if (staticLen>8*44100*4) {
+            staticLen = 8*44100*4;
+            addLen=!addLen;
+        }
+        if (staticLen<1000) {
+            staticLen = 1000;
+            addLen=!addLen;
+        }
+        int len = staticLen;
+        len -= (len % 4);
+        out("  Test program: preparing to play back "+len+" bytes == "+bytes2Ms(len, format)+"ms audio...");
+
+        byte[] fakedata=new byte[len];
+        InputStream is = new ByteArrayInputStream(fakedata);
+        AudioInputStream ais = new AudioInputStream(is, format, fakedata.length/format.getFrameSize());
+
+        DataLine.Info info = new DataLine.Info(Clip.class, ais.getFormat());
+        clip = (Clip) AudioSystem.getLine(info);
+        clip.addLineListener(this);
+
+        out("  Test program: opening clip="+((clip==null)?"null":clip.toString()));
+        clip.open(ais);
+        ais.close();
+        out("  Test program: starting clip="+((clip==null)?"null":clip.toString()));
+        clip.start();
+        return bytes2Ms(fakedata.length, format);
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+
+        try {
+            int COUNT=10;
+            out();
+            out("4498848 Sound causes crashes on Linux");
+            if (args.length>0) {
+                COUNT=Integer.parseInt(args[0]);
+            }
+            for (int i=0; i<COUNT; i++) {
+                out("trial "+(i+1)+"/"+COUNT);
+                ClipLinuxCrash2 t = new ClipLinuxCrash2();
+                t.start();
+                int waitTime = 300+(1300*(i % 2)); // every 2nd time wait 1600, rather than 300ms.
+                out("  Test program: waiting for "+waitTime+" ms for audio playback to stop...");
+                Thread.sleep(waitTime);
+                out("  Test program: calling close() from main thread");
+                t.clip.close();
+                // let the subsystem enough time to actually close the soundcard
+                //out("  Test program: waiting for 2 seconds...");
+                //Thread.sleep(2000);
+                //out();
+            }
+            out("  Test program: waiting for 1 second...");
+            Thread.sleep(1000);
+        } catch (Exception e) {
+            e.printStackTrace();
+            out("  Test program: waiting for 1 second");
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ie) {}
+            // do not fail if no audio device installed - bug 4742021
+            if (!(e instanceof LineUnavailableException)) {
+                throw e;
+            }
+        }
+        out("Test passed");
+    }
+
+    static void out() {
+        out("");
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/LinuxCrash/SDLLinuxCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,317 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineEvent;
+import javax.sound.sampled.LineListener;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * @test
+ * @bug 4498848
+ * @summary Sound causes crashes on Linux (part 2)
+ */
+public class SDLLinuxCrash implements Runnable {
+    SourceDataLine sdl;
+    int size;
+
+    SDLLinuxCrash(SourceDataLine sdl, int size) {
+        this.sdl = sdl;
+        this.size = size - (size % 4);
+    }
+
+    public void run() {
+        int written=0;
+        //byte[] buffer = new byte[4096];
+        byte[] buffer = data;
+        out("    starting data line feed thread.");
+        try {
+            while (written<size) {
+                int toWrite = buffer.length;
+                if (toWrite+written > size) {
+                    toWrite = size-written;
+                }
+                toWrite -= (toWrite % 4);
+                //out("    writing "+toWrite+" bytes.");
+                int thisWritten = sdl.write(buffer, 0, toWrite);
+                if (thisWritten<toWrite) {
+                    out("    only wrote "+thisWritten+" bytes instead of "+toWrite);
+                }
+                if (thisWritten<=0) {
+                    break;
+                }
+                written += thisWritten;
+            }
+        } catch (Throwable t) {
+            t.printStackTrace();
+        }
+        out("    leaving data line feed thread.");
+    }
+
+    public static long bytes2Ms(long bytes, AudioFormat format) {
+        return (long) (bytes/format.getFrameRate()*1000/format.getFrameSize());
+    }
+
+    static int staticLen=1000;
+    static boolean addLen=true;
+
+    public static SourceDataLine start() throws Exception {
+        AudioFormat format = new AudioFormat(44100, 16, 2, true, false);
+        if (addLen) {
+            staticLen+=(int) (staticLen/5)+1000;
+        } else {
+            staticLen-=(int) (staticLen/5)+1000;
+        }
+        if (staticLen>8*44100*4) {
+            staticLen = 8*44100*4;
+            addLen=!addLen;
+        }
+        if (staticLen<1000) {
+            staticLen = 1000;
+            addLen=!addLen;
+        }
+        int len = staticLen;
+        len -= (len % 4);
+        out("    preparing to play back "+len+" bytes == "+bytes2Ms(len, format)+"ms audio...");
+
+        DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
+        SourceDataLine sdl = (SourceDataLine) AudioSystem.getLine(info);
+        sdl.addLineListener(new LineListener() {
+                public void update(LineEvent e) {
+                    if (e.getType() == LineEvent.Type.STOP) {
+                        out("    calling close() from event dispatcher thread");
+                        ((SourceDataLine) e.getSource()).close();
+                    }
+                    else if (e.getType() == LineEvent.Type.CLOSE) {
+                    }
+                }
+            });
+
+        out("    opening...");
+        sdl.open();
+        out("    starting...");
+        sdl.start();
+        (new Thread(new SDLLinuxCrash(sdl, len))).start();
+        return sdl;
+    }
+
+    public static void main(String[] args) throws Exception {
+        if (!isSoundcardInstalled()) {
+            return;
+        }
+
+        try {
+            int COUNT=10;
+            out();
+            out("4498848 Sound causes crashes on Linux (testing with SourceDataLine)");
+            if (args.length>0) {
+                COUNT=Integer.parseInt(args[0]);
+            }
+            for (int i=0; i<COUNT; i++) {
+                out("  trial "+(i+1)+"/"+COUNT);
+                SourceDataLine sdl = start();
+                int waitTime = 500+(1000*(i % 2)); // every 2nd time wait 1500, rather than 500ms.
+                out("    waiting for "+waitTime+" ms for audio playback to stop...");
+                Thread.sleep(waitTime);
+                out("    calling close() from main thread");
+                sdl.close();
+                // let the subsystem enough time to actually close the soundcard
+                out("    waiting for 2 seconds...");
+                Thread.sleep(2000);
+                out();
+            }
+            out("  waiting for 1 second...");
+            Thread.sleep(1000);
+        } catch (Exception e) {
+            e.printStackTrace();
+            out("  waiting for 1 second");
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ie) {}
+            // do not fail if no audio device installed - bug 4742021
+            if (!(e instanceof LineUnavailableException)) {
+                throw e;
+            }
+        }
+        out("Test passed");
+    }
+
+    static void out() {
+        out("");
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+
+    /**
+     * Returns true if at least one soundcard is correctly installed
+     * on the system.
+     */
+    public static boolean isSoundcardInstalled() {
+        boolean result = false;
+        try {
+            Mixer.Info[] mixers = AudioSystem.getMixerInfo();
+            if (mixers.length > 0) {
+                result = AudioSystem.getSourceDataLine(null) != null;
+            }
+        } catch (Exception e) {
+            System.err.println("Exception occured: "+e);
+        }
+        if (!result) {
+            System.err.println("Soundcard does not exist or sound drivers not installed!");
+            System.err.println("This test requires sound drivers for execution.");
+        }
+        return result;
+    }
+
+
+
+    static final byte[] data = new byte[] {
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120,
+        123, 110, 100, 60, 11, 10, 10, 10, 9, 9,
+        9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6,
+        7, 7, 7, 7, 8, 8, 8, 8, 9, 9,
+        9, 9, 10, 10, 10, 11, 11, 60, 100, 110, 120, 122, 122
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/BogusMixers.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,71 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4667064
+ * @summary Java Sound provides bogus SourceDataLine and TargetDataLine
+ */
+public class BogusMixers {
+
+    public static void main(String[] args) throws Exception {
+        try {
+            out("4667064: Java Sound provides bogus SourceDataLine and TargetDataLine");
+
+            Mixer.Info[]    aInfos = AudioSystem.getMixerInfo();
+            out("  available Mixers:");
+            for (int i = 0; i < aInfos.length; i++) {
+                if (aInfos[i].getName().startsWith("Java Sound Audio Engine")) {
+                    Mixer mixer = AudioSystem.getMixer(aInfos[i]);
+                    Line.Info[] tlInfos = mixer.getTargetLineInfo();
+                    for (int ii = 0; ii<tlInfos.length; ii++) {
+                        if (tlInfos[ii].getLineClass() == DataLine.class) {
+                            throw new Exception("Bogus TargetDataLine with DataLine info present!");
+                        }
+                    }
+                }
+                if (aInfos[i].getName().startsWith("WinOS,waveOut,multi threaded")) {
+                    throw new Exception("Bogus mixer 'WinOS,waveOut,multi threaded' present!");
+                }
+                out(aInfos[i].getName());
+            }
+            if (aInfos.length == 0)
+            {
+                out("[No mixers available] - not a failure of this test case.");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw e;
+        }
+        out("Test passed");
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/BothEndiansAndSigns.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4936397
+ * @summary Verify that there'll for a given endianness, there's also the little
+ *          endian version
+ */
+public class BothEndiansAndSigns {
+    static boolean failed = false;
+    static int testedFormats = 0;
+
+    public static void main(String[] args) throws Exception {
+        out("4936397: Verify that there'll for a given endianness, there's also the little endian version");
+        out("         and the same for signed'ness for 8-bit formats");
+
+        Mixer.Info[] aInfos = AudioSystem.getMixerInfo();
+        for (int i = 0; i < aInfos.length; i++) {
+            try {
+                Mixer mixer = AudioSystem.getMixer(aInfos[i]);
+                out("Mixer "+aInfos[i]);
+                checkLines(mixer, mixer.getSourceLineInfo());
+                checkLines(mixer, mixer.getTargetLineInfo());
+            } catch (Exception e) {
+                out("Unexpected exception when getting a mixer: "+e);
+            }
+        }
+        if (testedFormats == 0) {
+            out("[No appropriate lines available] - cannot exercise this test.");
+        } else {
+            if (failed) {
+                throw new Exception("Test FAILED!");
+            }
+            out("Test passed");
+        }
+    }
+
+    public static void checkLines(Mixer mixer, Line.Info[] infos) {
+        for (int i = 0; i<infos.length; i++) {
+            try {
+                if (infos[i] instanceof DataLine.Info) {
+                    DataLine.Info info = (DataLine.Info) infos[i];
+                    System.out.println(" Line "+info+" (max. "+mixer.getMaxLines(info)+" simultaneously): ");
+                    AudioFormat[] formats = info.getFormats();
+                    for (int f = 0; f < formats.length; f++) {
+                        try {
+                            AudioFormat otherEndianOrSign = getOtherEndianOrSign(formats[f]);
+                            if (otherEndianOrSign != null) {
+                                checkFormat(formats, otherEndianOrSign);
+                            }
+                        } catch (Exception e1) {
+                            out("  Unexpected exception when getting a format: "+e1);
+                        }
+                    }
+                }
+            } catch (Exception e) {
+                out(" Unexpected exception when getting a line: "+e);
+            }
+        }
+    }
+
+    public static void checkFormat(AudioFormat[] formats, AudioFormat format) {
+        for (int i = 0; i < formats.length; i++) {
+            testedFormats++;
+            if (formats[i].matches(format)) {
+                return;
+            }
+        }
+        out("  ## expected this format: "+format
+            +" ("+format.getChannels()+" channels, "
+            +"frameSize="+format.getFrameSize()+", "
+            +(format.isBigEndian()?"big endian":"little endian")
+            +")");
+        failed = true;
+    }
+
+    public static AudioFormat getOtherEndianOrSign(AudioFormat format) {
+        AudioFormat.Encoding newEnc = null;
+        boolean newEndian = format.isBigEndian();
+        boolean isSigned = format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED);
+        boolean isUnsigned = format.getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED);
+        if ((isSigned || isUnsigned) && format.getSampleSizeInBits() > 0) {
+            if (format.getSampleSizeInBits() == 8) {
+                // return the other signed'ness
+                if (isSigned) {
+                    newEnc = AudioFormat.Encoding.PCM_UNSIGNED;
+                } else {
+                    newEnc = AudioFormat.Encoding.PCM_SIGNED;
+                }
+            } else {
+                newEnc = format.getEncoding();
+                newEndian = !newEndian;
+            }
+            if (newEnc != null) {
+                return new AudioFormat(newEnc, format.getSampleRate(),
+                                       format.getSampleSizeInBits(),
+                                       format.getChannels(),
+                                       format.getFrameSize(),
+                                       format.getFrameRate(),
+                                       newEndian);
+            }
+        }
+        return null;
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/DirectSoundRepeatingBuffer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * This is utility class for Test4997635.
+ */
+public class DirectSoundRepeatingBuffer {
+
+    static int sampleRate = 8000;
+    static double frequency = 1000.0;
+    static double RAD = 2.0 * Math.PI;
+
+    static byte[] audioData = new byte[sampleRate/8];
+    static DataLine.Info info;
+    static SourceDataLine source;
+
+    //static AudioInputStream ais = null;
+    static AudioFormat audioFormat;
+    //static String filename;
+
+    public static void print(String s) {
+        System.out.print(s);
+    }
+    public static void println(String s) {
+        System.out.println(s);
+    }
+
+    public static void key() {
+        println("");
+        print("Press ENTER to continue...");
+        try {
+            System.in.read();
+        } catch (IOException ioe) {
+        }
+        println("");
+    }
+
+    public static void play(Mixer mixer) {
+        int res = 0;
+        try {
+            println("Getting SDL from mixer...");
+            source = (SourceDataLine) mixer.getLine(info);
+            println("Opening SDL...");
+            source.open(audioFormat);
+            println("Writing data to SDL...");
+            source.write(audioData, 0, audioData.length);
+            println("Starting SDL...");
+            source.start();
+            println("Now open your ears:");
+            println("- you should have heard a short tone,");
+            println("  followed by silence.");
+            println("- if after a while you hear repeated tones,");
+            println("  the bug is NOT fixed.");
+            println("- if the program remains silent after the ");
+            println("  initial tone, the bug is fixed.");
+            key();
+        } catch (IllegalArgumentException iae) {
+            println("IllegalArgumentException: "+iae.getMessage());
+            println("Sound device cannot handle this audio format.");
+            println("ERROR: Test environment not correctly set up.");
+            if (source!=null) {
+                source.close();
+                source = null;
+            }
+            return;
+        } catch (LineUnavailableException lue) {
+            println("LineUnavailableException: "+lue.getMessage());
+            println("This is normal for some mixers.");
+        } catch (Exception e) {
+            println("Unexpected Exception: "+e.toString());
+        }
+        if (source != null) {
+            println("Stopping...");
+            source.stop();
+            println("Closing...");
+            source.close();
+            println("Closed.");
+            source = null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        println("This is an interactive test for DirectAudio.");
+        println("If the tone repeats, the test is failed.");
+        println("");
+        println("Make sure that you have speakers connected");
+        println("and that the system mixer is not muted.");
+        println("");
+        println("Press a key to start the test.");
+        key();
+        Mixer.Info[] mixers=null;
+
+            println("   ...using self-generated sine wave for playback");
+            audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
+            for (int i=0; i<audioData.length; i++) {
+                audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+            }
+        info = new DataLine.Info(SourceDataLine.class, audioFormat);
+
+        mixers = AudioSystem.getMixerInfo();
+        int succMixers = 0;
+        for (int i=0; i<mixers.length; i++) {
+            println(""+mixers[i]+":");
+            if ((mixers[i].getName()+mixers[i].getDescription()+mixers[i].getVendor()).indexOf("Direct") < 0) {
+                println("  ->not a DirectAudio Mixer!");
+            } else {
+            try {
+                Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                if (!mixer.isLineSupported(info)) {
+                        println("  ->doesn't support SourceDataLine!");
+                } else {
+                    succMixers++;
+                    println("  -> is getting tested.");
+                    play(mixer);
+                }
+            } catch (Exception e) {
+                println("  -> Exception occured: "+e);
+                e.printStackTrace();
+            }
+          }
+        }
+        if (succMixers == 0) {
+                println("No DirectAudio mixers available! ");
+                println("Cannot run test.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundRepeatingBuffer/Test4997635.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,381 @@
+/*
+ * 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.
+ */
+
+import java.awt.Button;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @test
+ * @bug 4997635
+ * @summary Win: SourceDataLine playback loops endlessly unless you manually
+ *          stop()
+ * @build DirectSoundRepeatingBuffer
+ * @run main/manual Test4997635
+ */
+public class Test4997635 {
+
+   private static void init() throws Exception {
+        //*** Create instructions for the user here ***
+
+        String[] instructions =
+        {
+         "To run the test follow these instructions:",
+         "1. Open a terminal window.",
+         "2. Type \"cd " + System.getProperty("test.classes") + "\".",
+         "3. Type \"" + System.getProperty("java.home") + "/bin/java DirectSoundRepeatingBuffer\".",
+         "4. Follow the instructions shown in the terminal window.",
+         "If no error occured during the test, and the java application ",
+         "in the termial exited successfully, press PASS, else press FAIL."
+       };
+
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+    }
+
+ /*****************************************************
+     Standard Test Machinery Section
+      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+   ******************************************************/
+   private static boolean theTestPassed = false;
+   private static boolean testGeneratedInterrupt = false;
+   private static String failureMessage = "";
+
+   private static Thread mainThread = null;
+
+   private static int sleepTime = 300000;
+
+   public static void main( String args[] ) throws Exception
+    {
+      mainThread = Thread.currentThread();
+      try
+       {
+         init();
+       }
+      catch( TestPassedException e )
+       {
+         //The test passed, so just return from main and harness will
+         // interepret this return as a pass
+         return;
+       }
+      //At this point, neither test passed nor test failed has been
+      // called -- either would have thrown an exception and ended the
+      // test, so we know we have multiple threads.
+
+      //Test involves other threads, so sleep and wait for them to
+      // called pass() or fail()
+      try
+       {
+         Thread.sleep( sleepTime );
+         //Timed out, so fail the test
+         throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
+       }
+      catch (InterruptedException e)
+       {
+         if( ! testGeneratedInterrupt ) throw e;
+
+         //reset flag in case hit this code more than once for some reason (just safety)
+         testGeneratedInterrupt = false;
+         if ( theTestPassed == false )
+          {
+            throw new RuntimeException( failureMessage );
+          }
+       }
+
+    }//main
+
+   public static synchronized void setTimeoutTo( int seconds )
+    {
+      sleepTime = seconds * 1000;
+    }
+
+   public static synchronized void pass()
+    {
+      Sysout.println( "The test passed." );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //first check if this is executing in main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //Still in the main thread, so set the flag just for kicks,
+         // and throw a test passed exception which will be caught
+         // and end the test.
+         theTestPassed = true;
+         throw new TestPassedException();
+       }
+      //pass was called from a different thread, so set the flag and interrupt
+      // the main thead.
+      theTestPassed = true;
+      testGeneratedInterrupt = true;
+      mainThread.interrupt();
+    }//pass()
+
+   public static synchronized void fail()
+    {
+      //test writer didn't specify why test failed, so give generic
+      fail( "it just plain failed! :-)" );
+    }
+
+   public static synchronized void fail( String whyFailed )
+    {
+      Sysout.println( "The test failed: " + whyFailed );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //check if this called from main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //If main thread, fail now 'cause not sleeping
+         throw new RuntimeException( whyFailed );
+       }
+      theTestPassed = false;
+      testGeneratedInterrupt = true;
+      failureMessage = whyFailed;
+      mainThread.interrupt();
+    }//fail()
+
+ }// class Orient
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+
+//************ Begin classes defined for the test ****************
+
+// make listeners in a class defined here, and instantiate them in init()
+
+/* Example of a class which may be written as part of a test
+class NewClass implements anInterface
+ {
+   static int newVar = 0;
+
+   public void eventDispatched(AWTEvent e)
+    {
+      //Counting events to see if we get enough
+      eventCount++;
+
+      if( eventCount == 20 )
+       {
+         //got enough events, so pass
+
+         Orient.pass();
+       }
+      else if( tries == 20 )
+       {
+         //tried too many times without getting enough events so fail
+
+         Orient.fail();
+       }
+
+    }// eventDispatched()
+
+ }// NewClass class
+
+*/
+
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+   Panel  buttonP = new Panel();
+   Button passB = new Button( "pass" );
+   Button failB = new Button( "fail" );
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      passB = new Button( "pass" );
+      passB.setActionCommand( "pass" );
+      passB.addActionListener( this );
+      buttonP.add( "East", passB );
+
+      failB = new Button( "fail" );
+      failB.setActionCommand( "fail" );
+      failB.addActionListener( this );
+      buttonP.add( "West", failB );
+
+      add( "South", buttonP );
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+   //catch presses of the passed and failed buttons.
+   //simply call the standard pass() or fail() static methods of
+   //DialogOrient
+   public void actionPerformed( ActionEvent e )
+    {
+      if( e.getActionCommand() == "pass" )
+       {
+         Test4997635.pass();
+       }
+      else
+       {
+         Test4997635.fail();
+       }
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/DirectSoundUnderrunSilence.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,161 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+
+/**
+ * This is utility class for Test5032020.
+ */
+public class DirectSoundUnderrunSilence {
+
+    static int sampleRate = 8000;
+    static double frequency = 1000.0;
+    static double RAD = 2.0 * Math.PI;
+
+    static byte[] audioData = new byte[sampleRate/8];
+    static DataLine.Info info;
+    static SourceDataLine source;
+
+    //static AudioInputStream ais = null;
+    static AudioFormat audioFormat;
+    //static String filename;
+
+    public static void print(String s) {
+        System.out.print(s);
+    }
+    public static void println(String s) {
+        System.out.println(s);
+    }
+
+    public static void key() {
+        println("");
+        print("Press ENTER to continue...");
+        try {
+            System.in.read();
+        } catch (IOException ioe) {
+        }
+        println("");
+    }
+
+    public static void play(Mixer mixer) {
+        int res = 0;
+        try {
+            println("Getting SDL from mixer...");
+            source = (SourceDataLine) mixer.getLine(info);
+            println("Opening SDL...");
+            source.open(audioFormat);
+            println("Writing data to SDL...");
+            source.write(audioData, 0, audioData.length);
+            println("Starting SDL...");
+            source.start();
+            println("Now open your ears:");
+            println("You should have heard a short tone,");
+            println("followed by silence (no repeating tones).");
+            key();
+            source.write(audioData, 0, audioData.length);
+            println("Now you should have heard another short tone.");
+            println("If you did not hear a second tone, or more than 2 tones,");
+            println("the test is FAILED.");
+            println("otherwise, if you heard a total of 2 tones, the bug is fixed.");
+            key();
+        } catch (IllegalArgumentException iae) {
+            println("IllegalArgumentException: "+iae.getMessage());
+            println("Sound device cannot handle this audio format.");
+            println("ERROR: Test environment not correctly set up.");
+            if (source!=null) {
+                source.close();
+                source = null;
+            }
+            return;
+        } catch (LineUnavailableException lue) {
+            println("LineUnavailableException: "+lue.getMessage());
+            println("This is normal for some mixers.");
+        } catch (Exception e) {
+            println("Unexpected Exception: "+e.toString());
+        }
+        if (source != null) {
+            println("Stopping...");
+            source.stop();
+            println("Closing...");
+            source.close();
+            println("Closed.");
+            source = null;
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        println("This is an interactive test for DirectAudio.");
+        println("If it's impossible to play data after an underun, the test fails.");
+        println("");
+        println("Make sure that you have speakers connected");
+        println("and that the system mixer is not muted.");
+        println("Also stop all other programs playing sounds:");
+        println("It has been seen that it alters the results.");
+        println("");
+        println("Press a key to start the test.");
+        key();
+        Mixer.Info[] mixers=null;
+
+        println("   ...using self-generated sine wave for playback");
+        audioFormat = new AudioFormat((float)sampleRate, 8, 1, true, true);
+        for (int i=0; i<audioData.length; i++) {
+            audioData[i] = (byte)(Math.sin(RAD*frequency/sampleRate*i)*127.0);
+        }
+        info = new DataLine.Info(SourceDataLine.class, audioFormat);
+
+        mixers = AudioSystem.getMixerInfo();
+        int succMixers = 0;
+        for (int i=0; i<mixers.length; i++) {
+            println(""+mixers[i]+":");
+            if ((mixers[i].getName()+mixers[i].getDescription()+mixers[i].getVendor()).indexOf("Direct") < 0) {
+                println("  ->not a DirectAudio Mixer!");
+            } else {
+                try {
+                    Mixer mixer = AudioSystem.getMixer(mixers[i]);
+                    if (!mixer.isLineSupported(info)) {
+                        println("  ->doesn't support SourceDataLine!");
+                    } else {
+                        succMixers++;
+                        println("  -> is getting tested.");
+                        play(mixer);
+                    }
+                } catch (Exception e) {
+                    println("  -> Exception occured: "+e);
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (succMixers == 0) {
+            println("No DirectAudio mixers available! ");
+            println("Cannot run test.");
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/DirectSoundUnderrunSilence/Test5032020.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,380 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.Button;
+import java.awt.Dialog;
+import java.awt.Frame;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @test
+ * @bug 5032020
+ * @summary Win: Direct Audio is silent after underrun
+ * @build DirectSoundUnderrunSilence
+ * @run main/manual Test5032020
+ */
+public class Test5032020 {
+
+   private static void init() throws Exception {
+        //*** Create instructions for the user here ***
+
+        String[] instructions =
+        {
+         "To run the test follow these instructions:",
+         "1. Open a terminal window.",
+         "2. Type \"cd " + System.getProperty("test.classes") + "\".",
+         "3. Type \"" + System.getProperty("java.home") + "/bin/java DirectSoundUnderrunSilence\".",
+         "4. Follow the instructions shown in the terminal window.",
+         "If no error occured during the test, and the java application ",
+         "in the termial exited successfully, press PASS, else press FAIL."
+       };
+
+      Sysout.createDialog( );
+      Sysout.printInstructions( instructions );
+
+    }
+
+ /*****************************************************
+     Standard Test Machinery Section
+      DO NOT modify anything in this section -- it's a
+      standard chunk of code which has all of the
+      synchronisation necessary for the test harness.
+      By keeping it the same in all tests, it is easier
+      to read and understand someone else's test, as
+      well as insuring that all tests behave correctly
+      with the test harness.
+     There is a section following this for test-defined
+      classes
+   ******************************************************/
+   private static boolean theTestPassed = false;
+   private static boolean testGeneratedInterrupt = false;
+   private static String failureMessage = "";
+
+   private static Thread mainThread = null;
+
+   private static int sleepTime = 300000;
+
+   public static void main( String args[] ) throws Exception
+    {
+      mainThread = Thread.currentThread();
+      try
+       {
+         init();
+       }
+      catch( TestPassedException e )
+       {
+         //The test passed, so just return from main and harness will
+         // interepret this return as a pass
+         return;
+       }
+      //At this point, neither test passed nor test failed has been
+      // called -- either would have thrown an exception and ended the
+      // test, so we know we have multiple threads.
+
+      //Test involves other threads, so sleep and wait for them to
+      // called pass() or fail()
+      try
+       {
+         Thread.sleep( sleepTime );
+         //Timed out, so fail the test
+         throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
+       }
+      catch (InterruptedException e)
+       {
+         if( ! testGeneratedInterrupt ) throw e;
+
+         //reset flag in case hit this code more than once for some reason (just safety)
+         testGeneratedInterrupt = false;
+         if ( theTestPassed == false )
+          {
+            throw new RuntimeException( failureMessage );
+          }
+       }
+
+    }//main
+
+   public static synchronized void setTimeoutTo( int seconds )
+    {
+      sleepTime = seconds * 1000;
+    }
+
+   public static synchronized void pass()
+    {
+      Sysout.println( "The test passed." );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //first check if this is executing in main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //Still in the main thread, so set the flag just for kicks,
+         // and throw a test passed exception which will be caught
+         // and end the test.
+         theTestPassed = true;
+         throw new TestPassedException();
+       }
+      //pass was called from a different thread, so set the flag and interrupt
+      // the main thead.
+      theTestPassed = true;
+      testGeneratedInterrupt = true;
+      mainThread.interrupt();
+    }//pass()
+
+   public static synchronized void fail()
+    {
+      //test writer didn't specify why test failed, so give generic
+      fail( "it just plain failed! :-)" );
+    }
+
+   public static synchronized void fail( String whyFailed )
+    {
+      Sysout.println( "The test failed: " + whyFailed );
+      Sysout.println( "The test is over, hit  Ctl-C to stop Java VM" );
+      //check if this called from main thread
+      if ( mainThread == Thread.currentThread() )
+       {
+         //If main thread, fail now 'cause not sleeping
+         throw new RuntimeException( whyFailed );
+       }
+      theTestPassed = false;
+      testGeneratedInterrupt = true;
+      failureMessage = whyFailed;
+      mainThread.interrupt();
+    }//fail()
+
+ }// class Orient
+
+//This exception is used to exit from any level of call nesting
+// when it's determined that the test has passed, and immediately
+// end the test.
+class TestPassedException extends RuntimeException
+ {
+ }
+
+//*********** End Standard Test Machinery Section **********
+
+
+//************ Begin classes defined for the test ****************
+
+// make listeners in a class defined here, and instantiate them in init()
+
+/* Example of a class which may be written as part of a test
+class NewClass implements anInterface
+ {
+   static int newVar = 0;
+
+   public void eventDispatched(AWTEvent e)
+    {
+      //Counting events to see if we get enough
+      eventCount++;
+
+      if( eventCount == 20 )
+       {
+         //got enough events, so pass
+
+         Orient.pass();
+       }
+      else if( tries == 20 )
+       {
+         //tried too many times without getting enough events so fail
+
+         Orient.fail();
+       }
+
+    }// eventDispatched()
+
+ }// NewClass class
+
+*/
+
+
+//************** End classes defined for the test *******************
+
+
+
+
+/****************************************************
+ Standard Test Machinery
+ DO NOT modify anything below -- it's a standard
+  chunk of code whose purpose is to make user
+  interaction uniform, and thereby make it simpler
+  to read and understand someone else's test.
+ ****************************************************/
+
+/**
+ This is part of the standard test machinery.
+ It creates a dialog (with the instructions), and is the interface
+  for sending text messages to the user.
+ To print the instructions, send an array of strings to Sysout.createDialog
+  WithInstructions method.  Put one line of instructions per array entry.
+ To display a message for the tester to see, simply call Sysout.println
+  with the string to be displayed.
+ This mimics System.out.println but works within the test harness as well
+  as standalone.
+ */
+
+class Sysout
+ {
+   private static TestDialog dialog;
+
+   public static void createDialogWithInstructions( String[] instructions )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      dialog.printInstructions( instructions );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+   public static void createDialog( )
+    {
+      dialog = new TestDialog( new Frame(), "Instructions" );
+      String[] defInstr = { "Instructions will appear here. ", "" } ;
+      dialog.printInstructions( defInstr );
+      dialog.show();
+      println( "Any messages for the tester will display here." );
+    }
+
+
+   public static void printInstructions( String[] instructions )
+    {
+      dialog.printInstructions( instructions );
+    }
+
+
+   public static void println( String messageIn )
+    {
+      dialog.displayMessage( messageIn );
+    }
+
+ }// Sysout  class
+
+/**
+  This is part of the standard test machinery.  It provides a place for the
+   test instructions to be displayed, and a place for interactive messages
+   to the user to be displayed.
+  To have the test instructions displayed, see Sysout.
+  To have a message to the user be displayed, see Sysout.
+  Do not call anything in this dialog directly.
+  */
+class TestDialog extends Dialog implements ActionListener
+ {
+
+   TextArea instructionsText;
+   TextArea messageText;
+   int maxStringLength = 80;
+   Panel  buttonP = new Panel();
+   Button passB = new Button( "pass" );
+   Button failB = new Button( "fail" );
+
+   //DO NOT call this directly, go through Sysout
+   public TestDialog( Frame frame, String name )
+    {
+      super( frame, name );
+      int scrollBoth = TextArea.SCROLLBARS_BOTH;
+      instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
+      add( "North", instructionsText );
+
+      messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
+      add("Center", messageText);
+
+      passB = new Button( "pass" );
+      passB.setActionCommand( "pass" );
+      passB.addActionListener( this );
+      buttonP.add( "East", passB );
+
+      failB = new Button( "fail" );
+      failB.setActionCommand( "fail" );
+      failB.addActionListener( this );
+      buttonP.add( "West", failB );
+
+      add( "South", buttonP );
+      pack();
+
+      show();
+    }// TestDialog()
+
+   //DO NOT call this directly, go through Sysout
+   public void printInstructions( String[] instructions )
+    {
+      //Clear out any current instructions
+      instructionsText.setText( "" );
+
+      //Go down array of instruction strings
+
+      String printStr, remainingStr;
+      for( int i=0; i < instructions.length; i++ )
+       {
+         //chop up each into pieces maxSringLength long
+         remainingStr = instructions[ i ];
+         while( remainingStr.length() > 0 )
+          {
+            //if longer than max then chop off first max chars to print
+            if( remainingStr.length() >= maxStringLength )
+             {
+               //Try to chop on a word boundary
+               int posOfSpace = remainingStr.
+                  lastIndexOf( ' ', maxStringLength - 1 );
+
+               if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
+
+               printStr = remainingStr.substring( 0, posOfSpace + 1 );
+               remainingStr = remainingStr.substring( posOfSpace + 1 );
+             }
+            //else just print
+            else
+             {
+               printStr = remainingStr;
+               remainingStr = "";
+             }
+
+            instructionsText.append( printStr + "\n" );
+
+          }// while
+
+       }// for
+
+    }//printInstructions()
+
+   //DO NOT call this directly, go through Sysout
+   public void displayMessage( String messageIn )
+    {
+      messageText.append( messageIn + "\n" );
+    }
+
+   //catch presses of the passed and failed buttons.
+   //simply call the standard pass() or fail() static methods of
+   //DialogOrient
+   public void actionPerformed( ActionEvent e )
+    {
+      if( e.getActionCommand() == "pass" )
+       {
+         Test5032020.pass();
+       }
+      else
+       {
+         Test5032020.fail();
+       }
+    }
+
+ }// TestDialog  class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/DisabledAssertionCrash.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,90 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 4991672
+ * @summary disabled assertion at maximum thread priority causes audio crash
+ * @run main/timeout=600 DisabledAssertionCrash
+ */
+public class DisabledAssertionCrash {
+    private static final int bufferSize = 1024;
+
+    public static void main(String[] args) {
+
+        System.out.println("This program hangs if priority is set,");
+        System.out.println("and assertion is in the code.");
+        System.out.println("The program crashes the entire Windows system");
+        System.out.println("if assertions are disabled.");
+        try {
+            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
+            AudioFormat audioFormat = new AudioFormat(44100,16,1,true,true);
+            Line.Info sourceDataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat);
+            SourceDataLine sourceDataLine =
+            (SourceDataLine) AudioSystem.getLine(sourceDataLineInfo);
+            System.out.println("SourceDataLine: "+sourceDataLine);
+            sourceDataLine.open(audioFormat, bufferSize);
+            sourceDataLine.start();
+            Line.Info targetDataLineInfo =
+            new DataLine.Info(TargetDataLine.class,audioFormat);
+            TargetDataLine targetDataLine =
+            (TargetDataLine) AudioSystem.getLine(targetDataLineInfo);
+            System.out.println("TargetDataLine: "+targetDataLine);
+            targetDataLine.open(audioFormat, bufferSize);
+            targetDataLine.start();
+            byte[] data = new byte[bufferSize];
+
+            // execute for 20 seconds
+            float bufferTime = (((float) data.length) / audioFormat.getFrameSize()) / audioFormat.getFrameRate();
+            int count = (int) (20.0f / bufferTime);
+            System.out.println("Buffer time: "+(bufferTime * 1000)+" millis. "+count+" iterations.");
+            for (int i = 0; i < count; i++) {
+                int cnt = targetDataLine.read(data,0,data.length);
+                sourceDataLine.write(data,0,cnt);
+                assert cnt == data.length;
+            }
+            System.out.println("Successfully recorded/played "+count+" buffers. Passed");
+        } catch(LineUnavailableException lue) {
+            System.out.println("Audio hardware is not available!");
+            lue.printStackTrace();
+            System.out.println("Cannot execute test. NOT failed.");
+        } catch(IllegalArgumentException iae) {
+            System.out.println("No audio hardware is installed!");
+            iae.printStackTrace();
+            System.out.println("Test system not correctly setup.");
+            System.out.println("Cannot execute test. NOT failed.");
+        } catch(Exception e) {
+            System.out.println("Unexpected Exception: "+e);
+            e.printStackTrace();
+            System.out.println("Cannot execute test. NOT failed.");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/NoSimpleInputDevice.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,70 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioSystem;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4936397
+ * @summary Verify that there'll be either SimpleInputDevice OR DirectAudioDevice
+ */
+public class NoSimpleInputDevice {
+
+    public static void main(String[] args) throws Exception {
+        out("4936397: Verify that there'll be either SimpleInputDevice OR DirectAudioDevice");
+        boolean foundSimpleInputDevice = false;
+        boolean foundDirectAudioDevice = false;
+
+        Mixer.Info[] aInfos = AudioSystem.getMixerInfo();
+        for (int i = 0; i < aInfos.length; i++) {
+            try {
+                Mixer mixer = AudioSystem.getMixer(aInfos[i]);
+                String mixerClass = mixer.getClass().toString();
+                if (mixerClass.indexOf("SimpleInputDevice") >= 0) {
+                    out("Found SimpleInputDevice: "+aInfos[i]);
+                    foundSimpleInputDevice = true;
+                }
+                if (mixerClass.indexOf("DirectAudioDevice") >= 0) {
+                    out("Found DirectAudioDevice: "+aInfos[i]);
+                    foundDirectAudioDevice = true;
+                }
+            } catch (Exception e) {
+                out("Unexpected exception: "+e);
+            }
+        }
+        if (aInfos.length == 0) {
+            out("[No mixers available] - cannot exercise this test.");
+        } else {
+            if (foundSimpleInputDevice && foundDirectAudioDevice) {
+                out("Found both types of capture devices!");
+                throw new Exception("Test FAILED!");
+            }
+            out("Did not find both types of capture devices. Test passed");
+        }
+    }
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/PhantomMixers.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,91 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 4794104
+ * @summary mixers are always present, independent of available soundcards
+ * @run main/manual PhantomMixers
+ */
+public class PhantomMixers {
+
+    public static void main(String args[]) throws Exception {
+        int SDLformats = 0;
+        int TDLformats = 0;
+        Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
+        for(int i=0; i<mixerInfo.length; i++){
+            Mixer.Info thisMixerInfo = mixerInfo[i];
+            System.out.println("Mixer #"+i+": "
+                               + thisMixerInfo.getName()
+                               + ": " + thisMixerInfo.getDescription());
+            Mixer mixer = AudioSystem.getMixer(thisMixerInfo);
+            Line.Info[] srcLineInfo = mixer.getSourceLineInfo();
+            Line.Info[] dstLineInfo = mixer.getTargetLineInfo();
+            int count = srcLineInfo.length + dstLineInfo.length;
+            System.out.print(" -> " + (srcLineInfo.length + dstLineInfo.length) + " line");
+            switch (count) {
+                case 0: System.out.println("s"); break;
+                case 1: System.out.println(""); break;
+                default: System.out.println("s:"); break;
+            }
+            int l;
+            for (l = 0; l < srcLineInfo.length; l++) {
+                System.out.println("    "+srcLineInfo[l].toString());
+                if (srcLineInfo[l].getLineClass() == SourceDataLine.class
+                    && (srcLineInfo[l] instanceof DataLine.Info)) {
+                    SDLformats += ((DataLine.Info) srcLineInfo[l]).getFormats().length;
+                }
+            }
+            for (l = 0; l < dstLineInfo.length; l++) {
+                System.out.println("    "+dstLineInfo[l].toString());
+                if (dstLineInfo[l].getLineClass() == TargetDataLine.class
+                    && (dstLineInfo[l] instanceof DataLine.Info)) {
+                    TDLformats += ((DataLine.Info) dstLineInfo[l]).getFormats().length;
+                }
+            }
+        }
+        if (mixerInfo.length == 0) {
+            System.out.println("[no mixers present]");
+        }
+        System.out.println(""+SDLformats+" total formats for SourceDataLines");
+        System.out.println(""+TDLformats+" total formats for TargetDataLines");
+        System.out.println("");
+        System.out.println("If there are audio devices correctly installed on your");
+        System.out.println("system, you should see at least one Mixer, and in total");
+        System.out.println("at least each one SourceDataLine and TargetDataLine, both");
+        System.out.println("providing at least one format.");
+        System.out.println("");
+        System.out.println("Now disable your soundcard and repeat the test.");
+        System.out.println("The corresponding mixer(s) should not provide any formats");
+        System.out.println("anymore. If you disable all available soundcards");
+        System.out.println("on your computer, the number of formats above should be");
+        System.out.println("0 for both line types (although mixers are allowed to exist).");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/PlugHwMonoAnd8bitAvailable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 5013897
+ * @summary Verify that plughw: provides mono and 8-bit lines
+ */
+public class PlugHwMonoAnd8bitAvailable {
+    static int failed = 0;
+    static int testedFormats = 0;
+
+    public static void main(String[] args) throws Exception {
+        out("5013897: Verify that plughw: provides mono and 8-bit lines");
+
+        Mixer.Info[] aInfos = AudioSystem.getMixerInfo();
+        for (int i = 0; i < aInfos.length; i++) {
+            try {
+                Mixer mixer = AudioSystem.getMixer(aInfos[i]);
+                out("Mixer "+aInfos[i]);
+                if (aInfos[i].getName().contains("plughw")) {
+                    checkLines(mixer, mixer.getSourceLineInfo());
+                    checkLines(mixer, mixer.getTargetLineInfo());
+                } else {
+                    out("  -> not plughw, ignored.");
+                }
+            } catch (Exception e) {
+                out("Unexpected exception when getting a mixer: "+e);
+            }
+        }
+        if (testedFormats == 0) {
+            out("[No appropriate lines available] - cannot exercise this test.");
+        } else {
+            if (failed>0) {
+                throw new Exception("Test FAILED!");
+            }
+            out("Successfully verified "+testedFormats+" formats.");
+            out("Test passed");
+        }
+    }
+
+    public static void checkLines(Mixer mixer, Line.Info[] infos) {
+        for (int i = 0; i<infos.length; i++) {
+                try {
+                        System.out.println(" Line "+infos[i]+" (max. "+mixer.getMaxLines(infos[i])+" simultaneously): ");
+                        if (infos[i] instanceof DataLine.Info) {
+                                DataLine.Info info = (DataLine.Info) infos[i];
+                                int thisTestedFormats = testedFormats;
+                                int thisFailed = failed;
+                                AudioFormat[] formats = info.getFormats();
+                                for (int f = 0; f < formats.length; f++) {
+                                        if (formats[f].getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)
+                                        || formats[f].getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED)) {
+                                                try {
+                                                        if (formats[f].getSampleSizeInBits() > 16) {
+                                                                // if a bit size larger than 16 is available, also 16-bit must be there
+                                                                checkFormat(formats, getOtherBits(formats[f], 16));
+                                                        } else
+                                                        if (formats[f].getSampleSizeInBits() > 8) {
+                                                                // if a bit size larger than 8 is available, also 8-bit must be there
+                                                                checkFormat(formats, getOtherBits(formats[f], 8));
+                                                        }
+                                                        if (formats[f].getChannels() > 2) {
+                                                                // if more than 2 channels, also 2 channels must be there
+                                                                checkFormat(formats, getOtherChannels(formats[f], 2));
+                                                        } else
+                                                        if (formats[f].getChannels() > 1) {
+                                                                // if more than 1 channel, also 1 channel must be there
+                                                                checkFormat(formats, getOtherChannels(formats[f], 1));
+                                                        }
+                                                } catch (Exception e1) {
+                                                        out("  Unexpected exception when getting a format: "+e1);
+                                                }
+                                        }
+                                }
+                                if (testedFormats - thisTestedFormats == 0) {
+                                        out(" -->could not test any formats");
+                                } else if (failed - thisFailed == 0) {
+                                        out(" -->"+(testedFormats - thisTestedFormats)+" formats tested OK");
+                                }
+
+                        } else {
+                                out("  --> not a DataLine");
+                        }
+                } catch (Exception e) {
+                        out(" Unexpected exception when getting a line: "+e);
+                }
+        }
+    }
+
+    public static void checkFormat(AudioFormat[] formats, AudioFormat format) {
+        testedFormats++;
+        for (int i = 0; i < formats.length; i++) {
+            if (formats[i].matches(format)) {
+                return;
+            }
+        }
+        out("  ## expected this format: "+format
+            +" ("+format.getChannels()+" channels, "
+            +"frameSize="+format.getFrameSize()+", "
+            +(format.isBigEndian()?"big endian":"little endian")
+            +")");
+        failed++;
+    }
+
+    // only works for PCM encodings
+    public static AudioFormat getOtherBits(AudioFormat format, int newBits) {
+        boolean isSigned = format.getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED);
+        return new AudioFormat(format.getSampleRate(),
+                               newBits,
+                               format.getChannels(),
+                               isSigned,
+                               (newBits>8)?format.isBigEndian():false);
+    }
+
+    // only works for PCM encodings
+    public static AudioFormat getOtherChannels(AudioFormat format, int newChannels) {
+        int newFrameSize;
+        if (newChannels <= 0 || format.getChannels() <= 0 || format.getFrameSize() <= 0) {
+            newFrameSize = -1;
+        } else {
+            newFrameSize = format.getFrameSize() / format.getChannels() * newChannels;
+        }
+        return new AudioFormat(format.getEncoding(),
+                               format.getSampleRate(),
+                               format.getSampleSizeInBits(),
+                               newChannels,
+                               newFrameSize,
+                               format.getFrameRate(),
+                               format.isBigEndian());
+    }
+
+
+    static void out(String s) {
+        System.out.println(s); System.out.flush();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Mixers/UnexpectedIAE.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.Line;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+
+/**
+ * @test
+ * @bug 4964288
+ * @summary Unexpected IAE raised while getting TargetDataLine
+ */
+public class UnexpectedIAE {
+
+    public static void main(String argv[]) throws Exception {
+        boolean success = true;
+
+        Mixer.Info [] infos = AudioSystem.getMixerInfo();
+
+        for (int i=0; i<infos.length; i++) {
+            Mixer mixer = AudioSystem.getMixer(infos[i]);
+            System.out.println("Mixer is: " + mixer);
+            Line.Info [] target_line_infos = mixer.getTargetLineInfo();
+            for (int j = 0; j < target_line_infos.length; j++) {
+                try {
+                    System.out.println("Trying to get:" + target_line_infos[j]);
+                    mixer.getLine(target_line_infos[j]);
+                } catch (IllegalArgumentException iae) {
+                    System.out.println("Unexpected IllegalArgumentException raised:");
+                    iae.printStackTrace();
+                    success = false;
+                } catch (LineUnavailableException lue) {
+                    System.out.println("Unexpected LineUnavailableException raised:");
+                    lue.printStackTrace();
+                    success = false;
+                }
+            }
+        }
+        if (success) {
+            System.out.println("Test passed");
+        } else {
+            throw new Exception("Test FAILED");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/Recording/TargetDataLineFlush.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,204 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioSystem;
+import javax.sound.sampled.DataLine;
+import javax.sound.sampled.LineUnavailableException;
+import javax.sound.sampled.Mixer;
+import javax.sound.sampled.TargetDataLine;
+
+/**
+ * @test
+ * @bug 4836433
+ * @summary Windows: TargetDataLine.flush() does not work. Since this test has
+ *          some real-time variance, I disabled it by making it a manual test.
+ * @run main/manual TargetDataLineFlush
+ */
+public class TargetDataLineFlush {
+    TargetDataLine inLine;
+    int SAMPLE_RATE = 11025;
+    int BUFFER_MILLIS = 1000;
+    int WAIT_MILLIS;
+    int BITS = 16;
+    int CHANNELS = 2;
+    int bufferSize;
+    AudioFormat format;
+    Mixer.Info[] mixers;
+    static boolean failed = false;
+
+    public TargetDataLineFlush() {
+        mixers = AudioSystem.getMixerInfo();
+    }
+
+    private void init() {
+        // float sampleRate, int sampleSizeInBits, int channels, boolean signed, boolean bigEndian
+        format = new AudioFormat( (float) SAMPLE_RATE, BITS, CHANNELS, true, false);
+        bufferSize = SAMPLE_RATE * BUFFER_MILLIS / 1000 * format.getFrameSize();
+    }
+
+    boolean openInputLine(int num)  throws LineUnavailableException {
+        init();
+        DataLine.Info info = new DataLine.Info(TargetDataLine.class, format); // format is an AudioFormat object
+        // Obtain and open a outLine.
+        if (num < 0) {
+            if (!AudioSystem.isLineSupported(info)) {
+                System.out.println("TargetDataLine is not supported by default mixer.");
+                return false;
+            }
+            inLine = (TargetDataLine) AudioSystem.getLine(info);
+        } else {
+            Mixer mixer = AudioSystem.getMixer(mixers[num]);
+            if (!mixer.isLineSupported(info)) {
+                System.out.println("TargetDataLine is not supported by this mixer.");
+                return false;
+            }
+            inLine = (TargetDataLine) mixer.getLine(info);
+        }
+        inLine.open(format, bufferSize);
+        /*if (Math.abs(inLine.getBufferSize() - bufferSize) > 100) {
+                inLine.close();
+                System.out.println("TargetDataLine does not support buffer size of "+bufferSize+" bytes!");
+                return false;
+        }*/
+        bufferSize = inLine.getBufferSize();
+        /* 3/4 of buffer size ot wait */
+        WAIT_MILLIS = (int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate());
+        System.out.println("Buffer size: "+bufferSize+" bytes = "
+            +((int) (bufferSize / format.getFrameSize() * 750 / format.getFrameRate()))+" millis");
+        return true;
+    }
+
+    private String available() {
+        int avail = inLine.available();
+        int availMillis = (int) (avail / format.getFrameSize() * 1000 / format.getFrameRate());
+        return "available "+avail+" bytes = "+availMillis+" millis";
+    }
+
+    private boolean recordSound(int num)  throws LineUnavailableException {
+        if (!openInputLine(num)) {
+            return false;
+        }
+        byte data[] = new byte[1000];
+        try {
+            System.out.println("Got line: "+inLine);
+            System.out.println("Start recording" );
+            inLine.start();
+            System.out.print("Warm-up...");
+            //System.out.print("Waiting 500 millis...");
+            try { Thread.sleep(500); } catch (InterruptedException ie) {}
+            //System.out.println("done. "+available());
+            //System.out.print("Reading all data...");
+            int avail0 = inLine.available();
+            if (avail0 == 0) {
+                System.out.println("Problem: TargetDataLine did not deliver any data!");
+                System.out.println("Not a test failure, but serious failure nonetheless.");
+            } else {
+                while ((avail0 -= inLine.read(data, 0, Math.min(data.length, avail0))) > 0);
+                System.out.println("done.  "+available());
+                System.out.print("Waiting "+(WAIT_MILLIS)+" millis...");
+                try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {}
+                int avail1 = inLine.available();
+                System.out.println("done. "+available());
+
+                System.out.print("Flushing...");
+                inLine.flush();
+                System.out.println("done.            "+available());
+                System.out.print("Waiting "+(WAIT_MILLIS)+" millis...");
+                try { Thread.sleep(WAIT_MILLIS); } catch (InterruptedException ie) {}
+                int avail2 = inLine.available();
+                System.out.println("done.  "+available());
+                if (avail2 > avail1) {
+                    failed = true;
+                    System.out.println("Failed: Flushing with native flush() should "
+                                       +"result in fewer bytes available.");
+                }
+                if (avail2 == 0) {
+                    failed = true;
+                    System.out.println("Failed: Recording after flush() did not work at all!");
+                }
+            }
+        } finally {
+            System.out.print("Closing line....");
+            inLine.close();
+            System.out.println("done");
+        }
+        return true;
+    }
+
+    public void runTests(int testRuns) {
+        if (mixers.length > 0) {
+            for (int num = -1; num < mixers.length; num++) {
+                try {
+                    if (num<0) {
+                        System.out.println("------Using default line...." );
+                    } else {
+                        System.out.println("------Using line "+num+" from mixer "+mixers[num]+"...");
+                    }
+                    for (int testRun = 0; testRun < testRuns; testRun++) {
+                        if (testRuns>1) {
+                            System.out.println("--Run "+(testRun+1)+"/"+testRuns+":");
+                        }
+                        if (!recordSound(num)) {
+                            break;
+                        }
+                    }
+                } catch (Exception ex) {
+                    System.out.println("Caught " + ex );
+                }
+                System.out.println("------------------------------------------------------");
+                if (failed) {
+                    break;
+                }
+            }
+        } else {
+            System.out.println("No mixers present. Cannot execute this test.");
+        }
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Test TargetDataLineFlush");
+        System.out.println("This verifies that TargetDataLine.flush() actually");
+        System.out.println("flushes the native buffers. This is done by");
+        System.out.println("comparing a manual flush (i.e. just discarding");
+        System.out.println("everything that is currently available in the TargetDataLine)");
+        System.out.println("to a flushed line");
+        TargetDataLineFlush app = new TargetDataLineFlush();
+        int testRuns = 1;
+        if (args.length > 0) {
+            try {
+                testRuns = Integer.parseInt(args[0]);
+            } catch (NumberFormatException nfe) {
+                System.out.println("Usage: java TargetDataLineFlush [number of runs]");
+                System.out.println("Parameters ignored.");
+            }
+        }
+        app.runTests(testRuns);
+        if (failed) {
+            throw new Exception("Test FAILED");
+        }
+        // test always passes if it gets here
+        System.out.println("Test PASSED");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFCp037.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,127 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4369044
+ * @summary javax.sound.sampled.AudioSystem.getAudioInputStream() works wrong
+ *          with Cp037
+ */
+public class AIFFCp037 {
+
+    public static void main(String args[]) throws Exception {
+        System.setProperty("file.encoding", "Cp037");
+        // try to read this file with Cp037 encoding
+        AudioSystem.getAudioInputStream(new ByteArrayInputStream(SHORT_AIFF));
+        System.out.println("  test passed.");
+    }
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=getString(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    public static byte[] SHORT_AIFF = {
+        70, 79, 82, 77, 0, 0, 4, -54, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18,
+        0, 1, 0, 0, 2, 78, 0, 16, 64, 12, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78,
+        68, 0, 0, 4, -92, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -2, 0, -2, 0, 0, 0, 0, 0,
+        -3, 0, -5, 0, -2, 0, 3, 0, 1, 0, -3, 0, -5, 0, -6, 0, -6, 0, -5, 0, -2, 0,
+        -2, 0, -5, 0, -6, 0, -3, 0, 0, 0, 0, 0, -3, 0, -5, 0, -6, 0, -8, 0, -5, 0,
+        1, 0, 4, 0, 1, 0, -5, 0, -8, 0, -3, 0, 3, 0, 4, 0, 0, 0, -8, 0, -11, 0, -8,
+        0, -3, 0, 0, 0, 0, 0, 1, 0, 0, 0, -5, 0, -9, 0, -8, 0, 0, 0, 6, 0, 7, 0,
+        0, 0, -8, 0, -11, 0, -8, 0, 0, 0, 4, 0, 6, 0, 3, 0, -2, 0, -5, 0, -5, 0,
+        0, 0, 6, 0, 6, 0, 1, 0, -5, 0, -3, 0, 1, 0, 6, 0, 6, 0, 1, 0, -3, 0, -3,
+        0, 0, 0, 3, 0, 3, 0, 0, 0, -3, 0, -2, 0, 3, 0, 6, 0, 4, 0, 0, 0, -2, 0, -2,
+        0, 1, 0, 1, 0, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -3, 0, 1, 0, 6,
+        0, 6, 0, 1, 0, 0, 0, 1, 0, 0, 0, -2, 0, -2, 0, 3, 0, 4, 0, 0, 0, -5, 0, -3,
+        0, 1, 0, 4, 0, 4, 0, 0, 0, -2, 0, 1, 0, 1, 0, -2, 0, -6, 0, -6, 0, -2, 0,
+        6, 0, 7, 0, 4, 0, 0, 0, -5, 0, -6, 0, -5, 0, 0, 0, 4, 0, 4, 0, 0, 0, -5,
+        0, -8, 0, -8, 0, -5, 0, 1, 0, 3, 0, 1, 0, -3, 0, -6, 0, -6, 0, -5, 0, -5,
+        0, -3, 0, 1, 0, 3, 0, 1, 0, -2, 0, -5, 0, -5, 0, -5, 0, -3, 0, 3, 0, 6, 0,
+        6, 0, 0, 0, -3, 0, -3, 0, 0, 0, 1, 0, 0, 0, 3, 0, 4, 0, 0, 0, -3, 0, -5,
+        0, -2, 0, 1, 0, -2, 0, -2, 0, 1, 0, 4, 0, 1, 0, -3, 0, -2, 0, 0, 0, 0, 0,
+        -3, 0, -6, 0, -5, 0, 0, 0, 3, 0, 0, 0, -3, 0, -5, 0, -5, 0, -2, 0, -2, 0,
+        -5, 0, -6, 0, -3, 0, 1, 0, 1, 0, -2, 0, -8, 0, -8, 0, -3, 0, 1, 0, 3, 0,
+        1, 0, -5, 0, -8, 0, -6, 0, -2, 0, 3, 0, 4, 0, -2, 0, -5, 0, -6, 0, -3, 0,
+        -2, 0, -2, 0, -2, 0, -2, 0, -3, 0, -5, 0, -6, 0, -5, 0, -2, 0, 0, 0, 0, 0,
+        -2, 0, -3, 0, -5, 0, -5, 0, -3, 0, -3, 0, -2, 0, -2, 0, 0, 0, 1, 0, 1, 0,
+        0, 0, 1, 0, 1, 0, -2, 0, -5, 0, -3, 0, 1, 0, 4, 0, 6, 0, 4, 0, 1, 0, 0, 0,
+        0, 0, 3, 0, 4, 0, 1, 0, -3, 0, -3, 0, 1, 0, 6, 0, 4, 0, 1, 0, -3, 0, -5,
+        0, -2, 0, 3, 0, 6, 0, 7, 0, 1, 0, -5, 0, -5, 0, 1, 0, 7, 0, 6, 0, 3, 0, 1,
+        0, -2, 0, -5, 0, -5, 0, -2, 0, 3, 0, 3, 0, 3, 0, 0, 0, -3, 0, -5, 0, -3,
+        0, 0, 0, 6, 0, 9, 0, 4, 0, -2, 0, -6, 0, -5, 0, -2, 0, 3, 0, 4, 0, 3, 0,
+        -2, 0, -6, 0, -3, 0, 1, 0, 3, 0, -3, 0, -6, 0, 0, 0, 4, 0, 1, 0, -6, 0, -9,
+        0, -5, 0, 1, 0, 1, 0, 0, 0, -2, 0, -3, 0, -5, 0, -6, 0, -5, 0, 0, 0, 3, 0,
+        3, 0, -2, 0, -6, 0, -6, 0, -3, 0, -2, 0, -2, 0, -5, 0, -6, 0, -5, 0, -2,
+        0, 0, 0, -2, 0, -3, 0, -3, 0, -3, 0, -2, 0, 0, 0, 1, 0, 0, 0, -2, 0, -2,
+        0, -3, 0, -5, 0, -5, 0, -2, 0, 0, 0, 3, 0, 3, 0, 0, 0, -3, 0, -3, 0, 0, 0,
+        -2, 0, -5, 0, -3, 0, 0, 0, 1, 0, -3, 0, -8, 0, -6, 0, -2, 0, -2, 0, -6, 0,
+        -6, 0, -5, 0, -3, 0, -3, 0, -6, 0, -6, 0, -3, 0, -3, 0, -3, 0, -3, 0, 0,
+        0, 1, 0, -3, 0, -6, 0, -3, 0, 1, 0, 0, 0, -6, 0, -9, 0, -9, 0, -6, 0, -2,
+        0, 1, 0, 3, 0, -3, 0, -5, 0, -3, 0, -2, 0, -3, 0, -6, 0, -5, 0, -2, 0, -2,
+        0, -5, 0, -5, 0, -2, 0, -2, 0, -5, 0, -6, 0, -6, 0, -2, 0, -2, 0, -2, 0,
+        -3, 0, -5, 0, -5, 0, -3, 0, 1, 0, 0, 0, 1, 0, 1, 0, 3, 0, 6, 0, 6, 0, 3,
+        0, -6, 0, -12, 0, -8, 0, 1, 0, 9, 0, 7, 0, 1, 0, -3, 0, 0, 0, 3, 0, 0, 0,
+        0, 0, 3, 0, 6, 0, 7, 0, 3, 0, -3, 0, -5, 0, 0, 0, 4, 0, 4, 0, 3, 0, 1, 0,
+        3, 0, 3, 0, 0, 0, -2, 0, 0, 0, 1, 0, 1, 0, 1, 0, 3, 0, 3, 0, 1, 0, 0, 0,
+        0, 0, 3, 0, 1, 0, -2, 0, -2, 0, 1, 0, 1, 0, -3, 0, -3, 0, 0, 0, 4, 0, 6,
+        0, 6, 0, 3, 0, -3, 0, -8, 0, -5, 0, 1, 0, 3, 0, 1, 0, 1, 0, 0, 0, -3, 0,
+        -6, 0, -5, 0, 1, 0, 3, 0, -2, 0, -3, 0, 0, 0, 1, 0, 1, 0, -3, 0, -5, 0, -2,
+        0, -2, 0, -2, 0, 0, 0, 1, 0, 1, 0, -2, 0, -5, 0, -8, 0, -6, 0, -5, 0, -2,
+        0, 1, 0, 0, 0, -5, 0, -6, 0, 0, 0, 4, 0, 1, 0, -5, 0, -5, 0, -3, 0, -2, 0,
+        -3, 0, -3, 0, 0, 0, 0, 0, -2, 0, -3, 0, -2, 0, 1, 0, -2, 0, -5, 0, -3, 0,
+        0, 0, 3, 0, 0, 0, -3, 0, -3, 0, -3, 0, -3, 0, -3, 0, 0, 0, 3, 0, 4, 0, -2,
+        0, -8, 0, -8, 0, -5, 0, 3, 0, 3, 0, -2, 0, -6, 0, -8, 0, -3, 0, 1, 0, 0,
+        0, -5, 0, -5, 0, -2, 0, -2, 0, -3, 0, -5, 0, -3, 0, 0, 0, 0, 0, -2, 0, -5,
+        0, -6, 0, -5, 0, -3, 0, 0, 0, 0, 0, -3, 0, -3, 0, -5, 0, -5, 0, -6, 0, -6,
+        0, -6, 0, -5, 0, 0, 0, 1, 0, 0, 0, -5, 0, -6, 0, -5, 0, -2, 0, -2, 0, -3,
+        0, -5, 0, -8, 0, -9, 0, -6, 0, -2, 0, 0, 0, -2, 0, -5, 0, -5, 0, -2, 0, 3,
+        0, 4, 0, 0, 0, -2, 0, -2, 0, 1, 0, 1, 0, 1, 0, 3, 0
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AIFFLargeHeader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,109 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4399551
+ * @summary Repost of bug candidate: cannot replay aif file. AIFF headers were
+ *          checked for certain size also tests that ulaw encoded AIFC files can
+ *          be read.
+ */
+public class AIFFLargeHeader {
+
+    public static void main(String args[]) throws Exception {
+        System.out.println();
+        System.out.println();
+        System.out.println("4399551: Repost of bug candidate: cannot replay aif file (Review ID: 108108)");
+        // try to read this file
+        AudioSystem.getAudioInputStream(new ByteArrayInputStream(SHORT_AIFC_ULAW));
+        System.out.println("  test passed.");
+    }
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=getString(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    public static byte[] SHORT_AIFC_ULAW = {
+        70, 79, 82, 77, 0, 0, 2, 50, 65, 73, 70, 67, 70, 86, 69, 82, 0, 0, 0, 4,
+        -94, -128, 81, 64, 67, 79, 77, 77, 0, 0, 0, 30, 0, 1, 0, 1, 118, -9, 0, 16,
+        64, 12, -84, 68, 0, 0, 0, 0, 0, 0, 117, 108, 97, 119, 7, 117, 110, 107, 110,
+        111, 119, 110, 83, 83, 78, 68, 0, 0, 1, -13, 0, 0, 0, 0, 0, 0, 0, 0, 103,
+        103, 103, -1, -1, 91, 77, 103, -45, -25, 91, 77, 73, 73, 77, 103, 103, 77,
+        73, 91, -1, -1, 91, 77, 73, 65, 77, -25, -51, -25, 77, 65, 91, -45, -51,
+        -1, 65, 58, 65, 91, -1, -1, -25, -1, 77, 62, 65, -1, -59, -63, -1, 65, 58,
+        65, -1, -51, -59, -45, 103, 77, 77, -1, -59, -59, -25, 77, 91, -25, -59,
+        -59, -25, 91, 91, -1, -45, -45, -1, 91, 103, -45, -59, -51, -1, 103, 103,
+        -25, -25, -45, -45, -1, -1, -1, -1, 103, 91, -25, -59, -59, -25, -1, -25,
+        -1, 103, 103, -45, -51, -1, 77, 91, -25, -51, -51, -1, 103, -25, -25, 103,
+        73, 73, 103, -59, -63, -51, -1, 77, 73, 77, -1, -51, -51, -1, 77, 65, 65,
+        77, -25, -45, -25, 91, 73, 73, 77, 77, 91, -25, -45, -25, 103, 77, 77, 77,
+        91, -45, -59, -59, -1, 91, 91, -1, -25, -1, -45, -51, -1, 91, 77, 103, -25,
+        103, 103, -25, -51, -25, 91, 103, -1, -1, 91, 73, 77, -1, -45, -1, 91, 77,
+        77, 103, 103, 77, 73, 91, -25, -25, 103, 65, 65, 91, -25, -45, -25, 77, 65,
+        73, 103, -45, -51, 103, 77, 73, 91, 103, 103, 103, 103, 91, 77, 73, 77, 103,
+        -1, -1, 103, 91, 77, 77, 91, 91, 103, 103, -1, -25, -25, -1, -25, -25, 103,
+        77, 91, -25, -51, -59, -51, -25, -1, -1, -45, -51, -25, 91, 91, -25, -59,
+        -51, -25, 91, 77, 103, -45, -59, -63, -25, 77, 77, -25, -63, -59, -45, -25,
+        103, 77, 77, 103, -45, -45, -45, -1, 91, 77, 91, -1, -59, -68, -51, 103,
+        73, 77, 103, -45, -51, -45, 103, 73, 91, -25, -45, 91, 73, -1, -51, -25,
+        73, 62, 77, -25, -25, -1, 103, 91, 77, 73, 77, -1, -45, -45, 103, 73, 73,
+        91, 103, 103, 77, 73, 77, 103, -1, 103, 91, 91, 91, 103, -1, -25, -1, 103,
+        103, 91, 77, 77, 103, -1, -45, -45, -1, 91, 91, -1, 103, 77, 91, -1, -25,
+        91, 65, 73, 103, 103, 73, 73, 77, 91, 91, 73, 73, 91, 91, 91, 91, -1, -25,
+        91, 73, 91, -25, -1, 73, 62, 62, 73, 103, -25, -45, 91, 77, 91, 103, 91,
+        73, 77, 103, 103, 77, 77, 103, 103, 77, 73, 73, 103, 103, 103, 91, 77, 77,
+        91, -25, -1, -25, -25, -45, -59, -59, -45, 73, 56, 65, -25, -68, -63, -25,
+        91, -1, -45, -1, -1, -45, -59, -63, -1, 103, 103, -25, -25, 103, 91, -1,
+        -45, -51, -25, 103, 91, 91, 103, -25, -25, -25, 103, 73, 77, -1, -51, -45,
+        103, 91, 103, -25, -1, 91, 91, 91, -1, -45, -51, -25, 91, 77, 103, -1, -1,
+        91, -1, -1, -1, 103, 91, 91, 73, 77, 103, -25, -25, 103, 91, 103, 103, 103,
+        -1, -45, -1, 77, 77, -1
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/Aiff12bit.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,78 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4895934
+ * @summary AudioInputStream.getFrameLength returns wrong value for 12-bit AIFF
+ *          file
+ */
+public class Aiff12bit {
+
+    public static void test(byte[] file) throws Exception {
+        InputStream inputStream = new ByteArrayInputStream(file);
+        AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream);
+
+        if (aff.getFormat().getSampleSizeInBits() != 12) {
+            throw new Exception("Wrong sample size. test FAILED");
+        }
+        if (aff.getFormat().getFrameSize() != 2) {
+            throw new Exception("Wrong frame size. test FAILED");
+        }
+        if (aff.getFrameLength() != 100) {
+            throw new Exception("Wrong file length. test FAILED");
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        test(AIFF_12BIT);
+
+        System.out.println("Test passed.");
+    }
+
+    public static byte[] AIFF_12BIT = {
+        70,   79,   82,   77,    0,    0,    0,  -10,   65,   73,   70,   70,   67,   79,   77,   77,
+        0,    0,    0,   18,    0,    1,    0,    0,    0,  100,    0,   12,   64,    8,   -6,    0,
+        0,    0,    0,    0,    0,    0,   83,   83,   78,   68,    0,    0,    0,  -48,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   16,    0,   32,    0,   48,    0,   64,
+        0,   80,    0,   96,    0,  112,    0, -128,    0, -112,    0,  -96,    0,  -80,    0,  -64,
+        0,  -48,    0,  -32,    0,  -16,    1,    0,    1,   16,    1,   32,    1,   48,    1,   64,
+        1,   80,    1,   96,    1,  112,    1, -128,    1, -112,    1,  -96,    1,  -80,    1,  -64,
+        1,  -48,    1,  -32,    1,  -16,    2,    0,    2,   16,    2,   32,    2,   48,    2,   64,
+        2,   80,    2,   96,    2,  112,    2, -128,    2, -112,    2,  -96,    2,  -80,    2,  -64,
+        2,  -48,    2,  -32,    2,  -16,    3,    0,    3,   16,    3,   32,    3,   48,    3,   64,
+        3,   80,    3,   96,    3,  112,    3, -128,    3, -112,    3,  -96,    3,  -80,    3,  -64,
+        3,  -48,    3,  -32,    3,  -16,    4,    0,    4,   16,    4,   32,    4,   48,    4,   64,
+        4,   80,    4,   96,    4,  112,    4, -128,    4, -112,    4,  -96,    4,  -80,    4,  -64,
+        4,  -48,    4,  -32,    4,  -16,    5,    0,    5,   16,    5,   32,    5,   48,    5,   64,
+        5,   80,    5,   96,    5,  112,    5, -128,    5, -112,    5,  -96,    5,  -80,    5,  -64,
+        5,  -48,    5,  -32,    5,  -16,    6,    0,    6,   16,    6,   32,    6,   48,
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AuNotSpecified.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,61 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4940459
+ * @summary AudioInputStream.getFrameLength() returns 0 instead of NOT_SPECIFIED
+ */
+public class AuNotSpecified {
+    public static boolean failed = false;
+
+    public static void main(String[] params) throws Exception {
+
+        AudioInputStream is =
+            AudioSystem.getAudioInputStream(new
+                                            ByteArrayInputStream(new byte[] {
+                                                (byte)0x2E, (byte)0x73, (byte)0x6E, (byte)0x64, (byte)0x00,
+                                                (byte)0x00, (byte)0x00, (byte)0x18,
+                                                (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00,
+                                                (byte)0x00, (byte)0x00, (byte)0x03,
+                                                (byte)0x00, (byte)0x00, (byte)0x1F, (byte)0x40, (byte)0x00,
+                                                (byte)0x00, (byte)0x00, (byte)0x01,
+                                                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+                                                (byte)0x00, (byte)0x00, (byte)0x00,
+                                            }));
+        if (is.getFrameLength() != AudioSystem.NOT_SPECIFIED) {
+            System.out.println("frame length should be NOT_SPECIFIED, but is: "+is.getFrameLength());
+            failed=true;
+        }
+        //assertTrue(is.getFrameLength() == AudioSystem.NOT_SPECIFIED);
+        //assertTrue(is.read(new byte[8]) == 8);
+        //assertTrue(is.read(new byte[2]) == -1);
+        if (failed) throw new Exception("Test FAILED!");
+        System.out.println("Test Passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/AuZeroLength.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,98 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4629669
+ * @summary AU file reader: problems with empty files
+ */
+public class AuZeroLength {
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=getString(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    public static void test(byte[] file) throws Exception {
+        InputStream inputStream = new ByteArrayInputStream(file);
+        AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream);
+
+        if (aff.getFrameLength() != 0) {
+            throw new Exception("File length is "+aff.getFrameLength()+" instead of 0. test FAILED");
+        }
+        System.out.println(aff.getType()+" file length is 0.");
+    }
+
+    public static void main(String[] args) throws Exception {
+        test(ZERO_AU);
+        test(ZERO_WAV);
+        test(ZERO_AIFF);
+
+        System.out.println("Test passed.");
+    }
+
+    public static byte[] ZERO_AU = {
+        46, 115, 110, 100, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, -84, 68, 0,
+        0, 0, 1, 116, 101, 115, 116, 46, 119, 97, 118
+    };
+
+    public static byte[] ZERO_WAV = {
+        82, 73, 70, 70, 36, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0,
+        0, 1, 0, 1, 0, 68, -84, 0, 0, -120, 88, 1, 0, 2, 0, 16, 0, 100, 97, 116,
+        97, 0, 0, 0, 0
+    };
+
+    public static byte[] ZERO_AIFF = {
+        70, 79, 82, 77, 0, 0, 0, 46, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18,
+        0, 1, 0, 0, 0, 0, 0, 16, 64, 14, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78, 68,
+        0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileReader/OpenWaveFile.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,125 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4489272
+ * @summary AudioSystem.getAudioFileFormat() fails for InputStream, but works
+ *          for URL
+ */
+public class OpenWaveFile {
+
+    static void check(Object source) throws Exception {
+         AudioFileFormat aff2 = null;
+         if (source instanceof File) {
+            aff2 = AudioSystem.getAudioFileFormat((File) source);
+         }
+         else if (source instanceof InputStream) {
+            aff2 = AudioSystem.getAudioFileFormat((InputStream) source);
+         }
+         else if (source instanceof URL) {
+            aff2 = AudioSystem.getAudioFileFormat((URL) source);
+         } else throw new Exception("wrong source. Test FAILED");
+         System.out.println("Got: "+aff2);
+         if (aff2.getFormat().getSampleSizeInBits()==-1) {
+            throw new Exception("wrong audio format. Test FAILED");
+         }
+    }
+
+    public static void main(String args[]) throws Exception {
+         //check(new File(args[0]));
+         //check(new URL("file", "", args[0]));
+         check(new ByteArrayInputStream(SHORT_AU));
+         check(new ByteArrayInputStream(SHORT_WAVE));
+         check(new ByteArrayInputStream(SHORT_AIFF));
+         System.out.println("Test passed.");
+
+         //printFile(args[0]);
+     }
+
+    public static String getString(byte b) {
+        //String res = Integer.toHexString(b & 0xFF).toUpperCase();
+        //while (res.length()<2) res="0"+res;
+        //return res;
+        return String.valueOf(b);
+    }
+
+
+    public static void printFile(String filename) throws Exception {
+        File file = new File(filename);
+        FileInputStream fis = new FileInputStream(file);
+        byte[] data = new byte[(int) file.length()];
+        fis.read(data);
+        String s = "";
+        for (int i=0; i<data.length; i++) {
+            s+=getString(data[i])+", ";
+            if (s.length()>72) {
+                System.out.println(s);
+                s="";
+            }
+        }
+        System.out.println(s);
+    }
+
+    public static byte[] SHORT_WAVE = {
+        82, 73, 70, 70, -120, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0,
+        0, 0, 1, 0, 1, 0, 34, 86, 0, 0, 34, 86, 0, 0, 1, 0, 8, 0, 100, 97, 116, 97,
+        100, 0, 0, 0, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128,
+        -128, -128, -128, -128, -128, -128, -128, -128, -128, 127, 127, -128, 127,
+        127, 127, -128, -128, -128, -128, 127, 127, -128, -128, 127, -128, -128,
+        -128, 127, 127, 127, -128, -128, -128, 127, 127, 127, 127, -128, -128, -128,
+        -128, -128, -128, 127, 127, 127, -128, -128, -128, -128, -128, 127, -128,
+        -128, 127, -128, -128, 127, 127, -128, -128, 127, 127, -128, -128, -128,
+        -128, -128, 127, 127, -128, -128, -128, 127, 127, 127, -128, 127, -128, -128,
+        127, 127, 127, -128, -128, -128, 127, 127, -128, -128,
+    };
+
+    public static byte[] SHORT_AU = {
+        46, 115, 110, 100, 0, 0, 0, 24, 0, 0, 0, 100, 0, 0, 0, 2, 0, 0, 86, 34, 0,
+        0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1,
+        0, -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, -1, -1, 0, 0, 0,
+        -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, -1,
+        0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, 0, 0, 0, -1, -1, -1, 0,
+        -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, 0, 0,
+    };
+
+    public static byte[] SHORT_AIFF = {
+        70, 79, 82, 77, 0, 0, 0, -110, 65, 73, 70, 70, 67, 79, 77, 77, 0, 0, 0, 18,
+        0, 1, 0, 0, 0, 100, 0, 8, 64, 13, -84, 68, 0, 0, 0, 0, 0, 0, 83, 83, 78,
+        68, 0, 0, 0, 108, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 0,
+        -1, 0, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, -1, -1,
+        -1, 0, 0, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, -1, 0, 0, -1, -1, 0, 0, 0, 0,
+        0, -1, -1, 0, 0, 0, -1, -1, -1, 0, -1, 0, 0, -1, -1, -1, 0, 0, 0, -1, -1,
+        0, 0,
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/AUwithULAW.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,66 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4391108
+ * @summary Writing au files with ulaw encoding is broken
+ */
+public class AUwithULAW {
+    public static void main(String args[]) throws Exception {
+        System.out.println();
+        System.out.println();
+        System.out.println("4391108: Writing au files with ulaw encoding is broken");
+        byte[] fakedata=new byte[1234];
+        InputStream is = new ByteArrayInputStream(fakedata);
+        AudioFormat inFormat = new AudioFormat(AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, false);
+
+        AudioInputStream ais = new AudioInputStream(is, inFormat, fakedata.length);
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream(1500);
+        System.out.println("  ulaw data will be written as AU to stream...");
+        int t = AudioSystem.write(ais, AudioFileFormat.Type.AU, out);
+        byte[] writtenData = out.toByteArray();
+        is = new ByteArrayInputStream(writtenData);
+        System.out.println("  Get AudioFileFormat of written file");
+        AudioFileFormat fileformat = AudioSystem.getAudioFileFormat(is);
+        AudioFileFormat.Type type = fileformat.getType();
+        System.out.println("  The file format type: "+type);
+        if (fileformat.getFrameLength()!=fakedata.length
+                && fileformat.getFrameLength()!=AudioSystem.NOT_SPECIFIED) {
+            throw new Exception("The written file's frame length is "+fileformat.getFrameLength()+" but should be "+fakedata.length+" !");
+        }
+        ais = AudioSystem.getAudioInputStream(is);
+        System.out.println("  Got Stream with format: "+ais.getFormat());
+        System.out.println("  test passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/AiffSampleRate.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,96 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4914639
+ * @summary JavaSound writes wrong sample rates to AIFF files
+ */
+public class AiffSampleRate {
+
+    private static final float[] testSampleRates =
+    {8000.0F, 8000.0F + 0.011F, 8193.975F, 10000.0F, 11025.0F, 12000.0F,
+     16000.0F, 22050.0F, 24000.0F, 32000.0F, 44100.0F - 1.22222F, 44100.0F,
+     47888.888F, 48000.0F, 96000.0F, 192000.0F};
+
+    public static void main(String[] args) throws Exception {
+        boolean isTestPassed = true;
+
+        out("#4914639: JavaSound writes wrong sample rates to AIFF files");
+        for (int i = 0; i < testSampleRates.length; i++) {
+            isTestPassed &= testSampleRate(testSampleRates[i]);
+        }
+        if (isTestPassed) {
+            out("Test PASSED.");
+        } else {
+            throw new Exception("Test FAILED.");
+        }
+    }
+
+    private static boolean testSampleRate(float sampleRate) {
+        boolean result = true;
+
+        try {
+            // create AudioInputStream with sample rate of 10000 Hz
+            ByteArrayInputStream data = new ByteArrayInputStream(new byte[1]);
+            AudioFormat format = new AudioFormat(sampleRate, 8, 1, true, true);
+            AudioInputStream stream = new AudioInputStream(data, format, 1);
+
+            // write to AIFF file
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            AudioSystem.write(stream, AudioFileFormat.Type.AIFF, outputStream);
+            byte[] fileData = outputStream.toByteArray();
+            InputStream inputStream = new ByteArrayInputStream(fileData);
+            AudioFileFormat aff = AudioSystem.getAudioFileFormat(inputStream);
+            if (! equals(sampleRate, aff.getFormat().getFrameRate())) {
+                out("error for sample rate " + sampleRate);
+                result = false;
+            }
+        } catch (Exception e) {
+            out(e);
+            out("Test NOT FAILED");
+        }
+        return result;
+    }
+
+    private static boolean equals(float f1, float f2) {
+        return Math.abs(f2 - f1) < 1.0E-9;
+    }
+
+    private static void out(Throwable t) {
+        t.printStackTrace(System.out);
+    }
+
+    private static void out(String message) {
+        System.out.println(message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/RIFFHeader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4636355
+ * @summary Check that RIFF headers are written with extra data length field.
+ */
+public class RIFFHeader {
+
+    public static void main(String args[]) throws Exception {
+        System.out.println();
+        System.out.println();
+        System.out.println("4636355: Check that RIFF headers are written with extra data length field.");
+        byte[] fakedata=new byte[1234];
+        MyByteArrayInputStream is = new MyByteArrayInputStream(fakedata);
+        AudioFormat inFormat = new AudioFormat(AudioFormat.Encoding.ULAW, 8000, 8, 1, 1, 8000, true);
+
+        AudioInputStream ais = new AudioInputStream((InputStream) is, inFormat, fakedata.length);
+        ByteArrayOutputStream out = new ByteArrayOutputStream(1500);
+        System.out.println("  ulaw data will be written as WAVE to stream...");
+        int t = AudioSystem.write(ais, AudioFileFormat.Type.WAVE, out);
+        byte[] writtenData = out.toByteArray();
+        // now header must have at least 46 bytes
+        System.out.println("  Length should be "+(fakedata.length+46)+" bytes: "+writtenData.length);
+        // re-read this file
+        is = new MyByteArrayInputStream(writtenData);
+        System.out.println("  Get AudioFileFormat of written file");
+        AudioFileFormat fileformat = AudioSystem.getAudioFileFormat(is);
+        AudioFileFormat.Type type = fileformat.getType();
+        System.out.println("  The file format type: "+type);
+        if (fileformat.getFrameLength()!=fakedata.length
+            && fileformat.getFrameLength()!=AudioSystem.NOT_SPECIFIED) {
+            throw new Exception("The written file's frame length is "+fileformat.getFrameLength()+" but should be "+fakedata.length+" !");
+        }
+        ais = AudioSystem.getAudioInputStream(is);
+        System.out.println("  Got Stream with format: "+ais.getFormat());
+        if (is.getPos()<46) {
+            throw new Exception("After reading the header, stream position must be at least 46, but is "+is.getPos()+" !");
+        }
+        System.out.println("  test passed.");
+    }
+
+    static class MyByteArrayInputStream extends ByteArrayInputStream {
+
+        MyByteArrayInputStream(byte[] data) {
+            super(data);
+        }
+
+        int getPos() {
+            return pos;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WaveBigEndian.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 5001952
+ * @summary Writing WAVE with big endian data produces corrupt file. WAVE should
+ *          always write signed 16-bit, little endian, regardless of the
+ *          endianness of the input data.
+ */
+public class WaveBigEndian {
+
+    static boolean failed = false;
+
+    public static byte[] writeDataAndGetAIS(boolean bigEndian) throws Exception {
+        if (bigEndian) {
+                out("Create WAVE file from big endian data...");
+        } else {
+                out("Create WAVE file from little endian data...");
+        }
+        byte[] data = new byte[3000];
+        for (int i = 0; i < data.length; i+=2) {
+                if (bigEndian) {
+                        data[i] = (byte) i;
+                        data[i+1] = (byte) (i+1);
+                } else {
+                        data[i] = (byte) (i+1);
+                        data[i+1] = (byte) i;
+                }
+        }
+        AudioFormat format = new AudioFormat(44100.0f, 16, 1, true, bigEndian);
+        InputStream is = new ByteArrayInputStream(data);
+        AudioInputStream ais = new AudioInputStream(is, format, data.length);
+        ByteArrayOutputStream os = new ByteArrayOutputStream();
+        int written = AudioSystem.write(ais, AudioFileFormat.Type.WAVE, os);
+        data = os.toByteArray();
+        out("Wrote "+written+" bytes, got "+data.length+" bytes in written file.");
+        is = new ByteArrayInputStream(data);
+        ais = AudioSystem.getAudioInputStream(is);
+        out("Got AIS with length = "+ais.getFrameLength()+" frames.");
+        return data;
+    }
+
+
+    public static void main(String args[]) throws Exception {
+        byte[] data1 = writeDataAndGetAIS(false);
+        byte[] data2 = writeDataAndGetAIS(true);
+
+        if (data1.length != data2.length) {
+                out("# data1.length != data2.length!");
+                failed = true;
+        } else {
+                for (int i = 0 ; i < data1.length; i++) {
+                        if (data1[i] != data2[i]) {
+                                out("# At index "+i+": le="+(data1[i] & 0xFF)+" be="+(data2[i] & 0xFF)+" !");
+                                failed = true;
+                        }
+                }
+        }
+
+        if (failed) throw new Exception("Test FAILED!");
+        out("Files are identical.");
+        out("test passed");
+    }
+
+    static void out(String s) {
+        System.out.println(s);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/AudioFileWriter/WriteAuUnspecifiedLength.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,47 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+
+import javax.sound.sampled.AudioFileFormat;
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4351296
+ * @summary Cannot write AudioInputStream with unspecified length
+ */
+public class WriteAuUnspecifiedLength {
+
+    public static void main(String argv[]) throws Exception {
+        AudioFormat format = new AudioFormat(44100, 16, 2, true, true);
+        InputStream is = new ByteArrayInputStream(new byte[1000]);
+        AudioInputStream ais = new AudioInputStream(is, format, AudioSystem.NOT_SPECIFIED);
+        AudioSystem.write(ais, AudioFileFormat.Type.AU, new ByteArrayOutputStream());
+        System.out.println("Test passed.");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sound/sampled/spi/FormatConversionProvider/AlawUlaw.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,205 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.InputStream;
+import java.io.OutputStream;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+/**
+ * @test
+ * @bug 4714846
+ * @summary JavaSound ULAW (8-bit) encoder erroneously depends on endian-ness
+ */
+public class AlawUlaw {
+    static ByteArrayInputStream in;
+    static int byteLength = 1000;
+
+    static boolean failed = false;
+
+    public static void main(String[] args) throws Exception {
+        // generate some random data
+        byte[] soundData = new byte[byteLength];
+        for (int i=0; i<soundData.length; i++) {
+            soundData[i] = (byte) ((i % 256) - 128);
+        }
+
+        // create an AudioInputStream from it
+        in = new ByteArrayInputStream(soundData);
+        in.mark(1);
+
+        test1(PCM_FORMAT_1, ULAW_FORMAT_1, ULAW_FORMAT_2);
+        test1(PCM_FORMAT_2, ULAW_FORMAT_1, ULAW_FORMAT_2);
+        test2(ULAW_FORMAT_1, ULAW_FORMAT_2, PCM_FORMAT_1);
+        test2(ULAW_FORMAT_1, ULAW_FORMAT_2, PCM_FORMAT_2);
+
+        test1(PCM_FORMAT_1, ALAW_FORMAT_1, ALAW_FORMAT_2);
+        test1(PCM_FORMAT_2, ALAW_FORMAT_1, ALAW_FORMAT_2);
+        test2(ALAW_FORMAT_1, ALAW_FORMAT_2, PCM_FORMAT_1);
+        test2(ALAW_FORMAT_1, ALAW_FORMAT_2, PCM_FORMAT_2);
+
+        if (failed) {
+                throw new Exception("Test failed!");
+        }
+    }
+
+    public static String printFormat(AudioFormat format) {
+        return format.toString()+"  "+(format.isBigEndian()?"big":"little")+" endian";
+    }
+
+
+    public static void test1(AudioFormat inFormat, AudioFormat outFormat1, AudioFormat outFormat2) throws Exception {
+        AudioInputStream inStream = new AudioInputStream(in, inFormat, -1);
+        System.out.println("Input Format: " + printFormat(inStream.getFormat()));
+
+        // get a converted stream
+        AudioInputStream stream1 = AudioSystem.getAudioInputStream(outFormat1, inStream);
+        System.out.println("Output Format 1: " + printFormat(stream1.getFormat()));
+
+        // get a converted stream in big endian ulaw
+        AudioInputStream stream2 = AudioSystem.getAudioInputStream(outFormat2, inStream);
+        System.out.println("Output Format 2: " + printFormat(stream2.getFormat()));
+
+        compareStreams(stream1, stream2);
+    }
+
+    public static void test2(AudioFormat inFormat1, AudioFormat inFormat2, AudioFormat outFormat) throws Exception {
+        AudioInputStream inStream1 = new AudioInputStream(in, inFormat1, -1);
+        System.out.println("Input Format1: " + printFormat(inStream1.getFormat()));
+
+        // get a converted stream
+        AudioInputStream stream1 = AudioSystem.getAudioInputStream(outFormat, inStream1);
+        System.out.println("Output Format 1: " + printFormat(stream1.getFormat()));
+
+        AudioInputStream inStream2 = new AudioInputStream(in, inFormat2, -1);
+        System.out.println("Input Format1: " + printFormat(inStream2.getFormat()));
+
+        // get a converted stream in big endian ulaw
+        AudioInputStream stream2 = AudioSystem.getAudioInputStream(outFormat, inStream2);
+        System.out.println("Output Format 2: " + printFormat(stream2.getFormat()));
+
+        compareStreams(stream1, stream2);
+    }
+
+    public static void compareStreams(InputStream stream1, InputStream stream2) throws Exception {
+        ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
+        ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
+
+        in.reset();
+        writeDirectly(stream1, baos1);
+        in.reset();
+        writeDirectly(stream2, baos2);
+
+        if (baos1.size() != baos2.size()) {
+            System.out.println("   stream1 has length = "+baos1.size()+", stream2 has length = "+baos2.size());
+        }
+        int len = baos1.size();
+        if (len > baos2.size()) {
+                len = baos2.size();
+        }
+        byte[] data1=baos1.toByteArray();
+        byte[] data2=baos2.toByteArray();
+        for (int i=0; i<len; i++) {
+                if (data1[i] != data2[i]) {
+                        System.out.println("  FAILED! Difference encountered at position "+i);
+                        failed = true;
+                        return;
+                }
+        }
+        if (baos1.size() != baos2.size()) {
+                System.out.println("  No difference, but different length!");
+                failed = true;
+                return;
+        }
+        System.out.println("   PASSED");
+    }
+
+    public static void writeDirectly(InputStream in, OutputStream out) throws Exception {
+            // read data from the stream until we reach the end of the stream
+            byte tmp[] = new byte[16384];
+            while (true) {
+                int bytesRead = in.read(tmp, 0, tmp.length);
+                if (bytesRead == -1) {
+                        break;
+                }
+                out.write(tmp, 0, bytesRead);
+            } // while
+    }
+
+    public static final AudioFormat PCM_FORMAT_1 =
+        new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
+                         8000f, //sample rate
+                         16, //bits per sample
+                         1, //channels
+                         2, //frame size
+                         8000f, // frame rate
+                         false); //isBigEndian
+    public static final AudioFormat PCM_FORMAT_2 =
+        new AudioFormat( AudioFormat.Encoding.PCM_SIGNED,
+                         8000f, //sample rate
+                         16, //bits per sample
+                         1, //channels
+                         2, //frame size
+                         8000f, // frame rate
+                         true); //isBigEndian
+
+    public static final AudioFormat ULAW_FORMAT_1 =
+        new AudioFormat( AudioFormat.Encoding.ULAW,
+                         8000f, //sample rate
+                         8, //bits per sample
+                         1, //channels
+                         1, //frame size
+                         8000f, // frame rate
+                         false); //isBigEndian
+
+    public static final AudioFormat ULAW_FORMAT_2 =
+        new AudioFormat( AudioFormat.Encoding.ULAW,
+                         8000f, //sample rate
+                         8, //bits per sample
+                         1, //channels
+                         1, //frame size
+                         8000f, // frame rate
+                         true); //isBigEndian
+
+    public static final AudioFormat ALAW_FORMAT_1 =
+        new AudioFormat( AudioFormat.Encoding.ALAW,
+                         8000f, //sample rate
+                         8, //bits per sample
+                         1, //channels
+                         1, //frame size
+                         8000f, // frame rate
+                         false); //isBigEndian
+
+    public static final AudioFormat ALAW_FORMAT_2 =
+        new AudioFormat( AudioFormat.Encoding.ALAW,
+                         8000f, //sample rate
+                         8, //bits per sample
+                         1, //channels
+                         1, //frame size
+                         8000f, // frame rate
+                         true); //isBigEndian
+}
--- a/jdk/test/javax/swing/JMenuItem/8139169/ScreenMenuBarInputTwice.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/swing/JMenuItem/8139169/ScreenMenuBarInputTwice.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 8139169
+ * @bug 8139169 8158390
  * @summary verifies if TextArea gets input twice due to Apple's Screen Menubar
  * @requires (os.family=="mac")
  * @library ../../regtesthelpers
@@ -65,15 +65,13 @@
 
     public static void main(String[] args) throws Exception {
         robot = new Robot();
+        robot.setAutoDelay(200);
+        robot.setAutoWaitForIdle(true);
         createUIWithSeperateMenuBar();
-        robot.delay(2000);
         shortcutTestCase();
-        robot.delay(2000);
         cleanUp();
         createUIWithIntegratedMenuBar();
-        robot.delay(2000);
         menuTestCase();
-        robot.delay(2000);
         cleanUp();
     }
 
@@ -188,7 +186,6 @@
         robot.keyRelease(VK_COMMA);
         robot.keyRelease(VK_SHIFT);
         robot.keyRelease(VK_META);
-        robot.delay(2000);
         checkText(textArea.getText());
     }
 
@@ -198,13 +195,10 @@
         robot.mouseMove(mousePoint.x, mousePoint.y);
         robot.mousePress(InputEvent.BUTTON1_MASK);
         robot.mouseRelease(InputEvent.BUTTON1_MASK);
-        robot.delay(2000);
         mousePoint = Util.getCenterPoint(menuItem);
         robot.mouseMove(mousePoint.x, mousePoint.y);
-        robot.delay(2000);
         robot.mousePress(InputEvent.BUTTON1_MASK);
         robot.mouseRelease(InputEvent.BUTTON1_MASK);
-        robot.delay(2000);
         checkText(textArea.getText());
     }
 
--- a/jdk/test/javax/swing/JTextArea/ScrollbarFlicker/ScrollFlickerTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/swing/JTextArea/ScrollbarFlicker/ScrollFlickerTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,8 +29,6 @@
 
 import javax.swing.*;
 import java.awt.*;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
 
 public class ScrollFlickerTest {
 
@@ -56,18 +54,19 @@
         robot.delay(200);
 
         SwingUtilities.invokeAndWait(() -> {
-            scroll.getViewport().addChangeListener((e) -> cnt++);
             Insets insets = scroll.getInsets();
             scroll.setSize(insets.left + insets.right +
                     scroll.getVerticalScrollBar().getPreferredSize().width, 50);
             scroll.revalidate();
         });
-
+        robot.delay(200);
+        SwingUtilities.invokeAndWait(() ->
+                          scroll.getViewport().addChangeListener((e) -> cnt++));
         robot.delay(1000);
 
         SwingUtilities.invokeLater(frame::dispose);
 
-        if (cnt > 2) {
+        if (cnt > 0) {
             throw new RuntimeException("Scroll bar flickers");
         }
     }
--- a/jdk/test/javax/swing/ToolTipManager/7123767/bug7123767.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/swing/ToolTipManager/7123767/bug7123767.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -23,12 +23,25 @@
 
 /*
  * @test
- * @key headful
- * @bug 7123767
- * @summary Wrong tooltip location in Multi-Monitor configurations
- * @author Vladislav Karnaukhov
- * @modules java.desktop/sun.awt
- * @run main bug7123767
+ * @bug      7123767
+ *
+ * @summary  Check if a tooltip location in Multi-Monitor
+ *           configurations is correct.
+ *           If the configurations number per device exceeds 5,
+ *           then some 5 random configurations will be checked.
+ *           Please Use -Dseed=X to set the random generator seed
+ *           (if necessary).
+ *
+ * @author   Vladislav Karnaukhov
+ *
+ * @key      headful
+ * @key      randomness
+ *
+ * @modules  java.desktop/sun.awt
+ * @library  /lib/testlibrary/
+ * @build    jdk.testlibrary.*
+ *
+ * @run      main/timeout=300 bug7123767
  */
 
 import javax.swing.*;
@@ -37,8 +50,50 @@
 import java.awt.event.MouseEvent;
 import java.lang.reflect.InvocationTargetException;
 
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Random;
+
+import jdk.testlibrary.RandomFactory;
+
+
 public class bug7123767 extends JFrame {
 
+    // maximum number of GraphicsConfigurations checked per GraphicsDevice
+    private static final int MAX_N_CONFIGS = 5;
+    private static final List<GraphicsConfiguration> CONFIGS = getConfigs();
+
+    private static List<GraphicsConfiguration> getConfigs() {
+
+        Random rnd = RandomFactory.getRandom();
+
+        List<GraphicsConfiguration> configs = new ArrayList<>();
+
+        GraphicsEnvironment ge =
+                GraphicsEnvironment.getLocalGraphicsEnvironment();
+        GraphicsDevice[] devices = ge.getScreenDevices();
+
+        for (GraphicsDevice device : devices) {
+            GraphicsConfiguration[] allConfigs = device.getConfigurations();
+            int nConfigs = allConfigs.length;
+            if (nConfigs <= MAX_N_CONFIGS) {
+                Collections.addAll(configs, allConfigs);
+            } else { // see JDK-8159454
+                System.out.println("check only " + MAX_N_CONFIGS +
+                    " configurations for device " + device);
+                configs.add(device.getDefaultConfiguration()); // check default
+                for (int j = 0; j < MAX_N_CONFIGS - 1; j++) {
+                    int k = rnd.nextInt(nConfigs);
+                    configs.add(allConfigs[k]);
+                }
+            }
+        }
+
+        return configs;
+    }
+
+
     private static class TestFactory extends PopupFactory {
 
         private static TestFactory newFactory = new TestFactory();
@@ -62,15 +117,21 @@
         }
 
         // Actual test happens here
+        @Override
         public Popup getPopup(Component owner, Component contents, int x, int y) {
-            GraphicsConfiguration mouseGC = testGC(MouseInfo.getPointerInfo().getLocation());
+
+            GraphicsConfiguration mouseGC =
+                testGC(MouseInfo.getPointerInfo().getLocation());
+
             if (mouseGC == null) {
-                throw new RuntimeException("Can't find GraphicsConfiguration that mouse pointer belongs to");
+                throw new RuntimeException("Can't find GraphicsConfiguration "
+                        + "that mouse pointer belongs to");
             }
 
             GraphicsConfiguration tipGC = testGC(new Point(x, y));
             if (tipGC == null) {
-                throw new RuntimeException("Can't find GraphicsConfiguration that tip belongs to");
+                throw new RuntimeException(
+                        "Can't find GraphicsConfiguration that tip belongs to");
             }
 
             if (!mouseGC.equals(tipGC)) {
@@ -81,17 +142,14 @@
         }
 
         private static GraphicsConfiguration testGC(Point pt) {
-            GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
-            GraphicsDevice[] devices = environment.getScreenDevices();
-            for (GraphicsDevice device : devices) {
-                GraphicsConfiguration[] configs = device.getConfigurations();
-                for (GraphicsConfiguration config : configs) {
-                    Rectangle rect = config.getBounds();
-                    Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config);
-                    adjustInsets(rect, insets);
-                    if (rect.contains(pt))
-                        return config;
-                }
+
+            for (GraphicsConfiguration config: CONFIGS) {
+
+                Rectangle rect = config.getBounds();
+                Insets insets =
+                    Toolkit.getDefaultToolkit().getScreenInsets(config);
+                adjustInsets(rect, insets);
+                if (rect.contains(pt)) { return config; }
             }
 
             return null;
@@ -103,15 +161,18 @@
     private static Robot robot;
 
     public static void main(String[] args) throws Exception {
+
         UIManager.setLookAndFeel(new MetalLookAndFeel());
         setUp();
         testToolTip();
         TestFactory.uninstall();
+        if (frame != null) { frame.dispose(); }
     }
 
     // Creates a window that is stretched across all available monitors
     // and adds itself as ContainerListener to track tooltips drawing
     private bug7123767() {
+
         super();
 
         ToolTipManager.sharedInstance().setInitialDelay(0);
@@ -135,17 +196,16 @@
         pack();
 
         Rectangle rect = new Rectangle();
-        GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        GraphicsDevice[] devices = environment.getScreenDevices();
-        for (GraphicsDevice device : devices) {
-            GraphicsConfiguration[] configs = device.getConfigurations();
-            for (GraphicsConfiguration config : configs) {
-                Insets localInsets = Toolkit.getDefaultToolkit().getScreenInsets(config);
-                Rectangle localRect = config.getBounds();
-                adjustInsets(localRect, localInsets);
-                rect.add(localRect);
-            }
+
+        for (GraphicsConfiguration config: CONFIGS) {
+
+            Insets localInsets =
+                Toolkit.getDefaultToolkit().getScreenInsets(config);
+            Rectangle localRect = config.getBounds();
+            adjustInsets(localRect, localInsets);
+            rect.add(localRect);
         }
+
         setBounds(rect);
     }
 
@@ -166,35 +226,32 @@
         robot.setAutoDelay(20);
         robot.waitForIdle();
 
-        GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        GraphicsDevice[] devices = environment.getScreenDevices();
-        for (GraphicsDevice device : devices) {
-            GraphicsConfiguration[] configs = device.getConfigurations();
-            for (GraphicsConfiguration config : configs) {
-                Rectangle rect = config.getBounds();
-                Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config);
-                adjustInsets(rect, insets);
+        for (GraphicsConfiguration config: CONFIGS) {
 
-                // Upper left
-                glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
-                        rect.x + MARGIN, rect.y + MARGIN);
-                robot.waitForIdle();
+            Rectangle rect = config.getBounds();
+            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(config);
+            adjustInsets(rect, insets);
+
+            // Upper left
+            glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
+                    rect.x + MARGIN, rect.y + MARGIN);
+            robot.waitForIdle();
 
-                // Lower left
-                glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
-                        rect.x + MARGIN, rect.y + rect.height - MARGIN);
-                robot.waitForIdle();
+            // Lower left
+            glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
+                    rect.x + MARGIN, rect.y + rect.height - MARGIN);
+            robot.waitForIdle();
 
-                // Upper right
-                glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
-                        rect.x + rect.width - MARGIN, rect.y + MARGIN);
-                robot.waitForIdle();
+            // Upper right
+            glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
+                    rect.x + rect.width - MARGIN, rect.y + MARGIN);
+            robot.waitForIdle();
 
-                // Lower right
-                glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
-                        rect.x + rect.width - MARGIN, rect.y + rect.height - MARGIN);
-                robot.waitForIdle();
-            }
+            // Lower right
+            glide(rect.x + rect.width / 2, rect.y + rect.height / 2,
+                    rect.x + rect.width - MARGIN, rect.y + rect.height - MARGIN);
+
+            robot.waitForIdle();
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/basic/BasicScrollPaneUI/8166591/TooMuchWheelRotationEventsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8166591
+ * @key headful
+ * @summary [macos 10.12] Trackpad scrolling of text on OS X 10.12 Sierra
+ *    is very fast (Trackpad, Retina only)
+ * @run main/manual/othervm TooMuchWheelRotationEventsTest
+ */
+public class TooMuchWheelRotationEventsTest {
+
+    private static volatile boolean testResult = false;
+    private static volatile CountDownLatch countDownLatch;
+    private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
+            + "Try to check the issue on Mac OS X 10.12 Sierra with trackpad"
+            + " on Retina display.\n"
+            + "\n"
+            + "If the trackpad is not supported, press PASS\n"
+            + "\n"
+            + "Use the trackpad to slightly scroll the JTextArea horizontally and vertically.\n"
+            + "If the text area is scrolled too fast press FAIL, else press PASS.";
+
+    public static void main(String args[]) throws Exception {
+        countDownLatch = new CountDownLatch(1);
+
+        SwingUtilities.invokeLater(TooMuchWheelRotationEventsTest::createUI);
+        countDownLatch.await(15, TimeUnit.MINUTES);
+
+        if (!testResult) {
+            throw new RuntimeException("Test fails!");
+        }
+    }
+
+    private static void createUI() {
+
+        final JFrame mainFrame = new JFrame("Trackpad scrolling test");
+        GridBagLayout layout = new GridBagLayout();
+        JPanel mainControlPanel = new JPanel(layout);
+        JPanel resultButtonPanel = new JPanel(layout);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JPanel testPanel = createTestPanel();
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(testPanel, gbc);
+
+        JTextArea instructionTextArea = new JTextArea();
+        instructionTextArea.setText(INSTRUCTIONS);
+        instructionTextArea.setEditable(false);
+        instructionTextArea.setBackground(Color.white);
+
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(instructionTextArea, gbc);
+
+        JButton passButton = new JButton("Pass");
+        passButton.setActionCommand("Pass");
+        passButton.addActionListener((ActionEvent e) -> {
+            testResult = true;
+            mainFrame.dispose();
+            countDownLatch.countDown();
+
+        });
+
+        JButton failButton = new JButton("Fail");
+        failButton.setActionCommand("Fail");
+        failButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        resultButtonPanel.add(passButton, gbc);
+
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        resultButtonPanel.add(failButton, gbc);
+
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        mainControlPanel.add(resultButtonPanel, gbc);
+
+        mainFrame.add(mainControlPanel);
+        mainFrame.pack();
+
+        mainFrame.addWindowListener(new WindowAdapter() {
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+        mainFrame.setVisible(true);
+    }
+
+    private static JPanel createTestPanel() {
+        JPanel panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+        JTextArea textArea = new JTextArea(20, 20);
+        textArea.setText(getLongString());
+        JScrollPane scrollPane = new JScrollPane(textArea);
+        panel.add(scrollPane);
+        return panel;
+    }
+
+    private static String getLongString() {
+
+        String lowCaseString = getLongString('a', 'z');
+        String upperCaseString = getLongString('A', 'Z');
+        String digitsString = getLongString('0', '9');
+
+        int repeat = 30;
+        StringBuilder lowCaseBuilder = new StringBuilder();
+        StringBuilder upperCaseBuilder = new StringBuilder();
+        StringBuilder digitsBuilder = new StringBuilder();
+
+        for (int i = 0; i < repeat; i++) {
+            lowCaseBuilder.append(lowCaseString).append(' ');
+            upperCaseBuilder.append(upperCaseString).append(' ');
+            digitsBuilder.append(digitsString).append(' ');
+        }
+
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < 200; i++) {
+            builder.append(upperCaseBuilder).append('\n')
+                    .append(lowCaseBuilder).append('\n')
+                    .append(digitsBuilder).append("\n\n\n");
+        }
+
+        return builder.toString();
+    }
+
+    private static String getLongString(char c1, char c2) {
+
+        char[] chars = new char[c2 - c1 + 1];
+        for (char i = c1; i <= c2; i++) {
+            chars[i - c1] = i;
+        }
+        return new String(chars);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/motif/8165485/MotifHiDPIIconsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ScrollPaneConstants;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug 8165485
+ * @summary Bad rendering of Swing UI controls with Motif L&F on HiDPI display
+ * @run main/manual/othervm -Dsun.java2d.uiScale=2
+ * -Dswing.defaultlaf=com.sun.java.swing.plaf.motif.MotifLookAndFeel MotifHiDPIIconsTest
+ */
+public class MotifHiDPIIconsTest {
+
+    private static volatile boolean testResult = false;
+    private static volatile CountDownLatch countDownLatch;
+    private static final String INSTRUCTIONS = "INSTRUCTIONS:\n"
+            + "Check that the icons are painted smoothly on Swing UI controls:\n"
+            + "  - JRadioButton\n"
+            + "  - JCheckBox\n"
+            + "  - JComboBox\n"
+            + "  - JScrollPane (vertical and horizontal scroll bars)\n"
+            + "\n"
+            + "If so, press PASS, else press FAIL.\n";
+
+    public static void main(String args[]) throws Exception {
+        countDownLatch = new CountDownLatch(1);
+
+        SwingUtilities.invokeLater(MotifHiDPIIconsTest::createUI);
+        countDownLatch.await(15, TimeUnit.MINUTES);
+
+        if (!testResult) {
+            throw new RuntimeException("Test fails!");
+        }
+    }
+
+    private static void createUI() {
+
+        final JFrame mainFrame = new JFrame("Motif L&F icons test");
+        GridBagLayout layout = new GridBagLayout();
+        JPanel mainControlPanel = new JPanel(layout);
+        JPanel resultButtonPanel = new JPanel(layout);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+
+        JPanel testPanel = createJPanel();
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(testPanel, gbc);
+
+        JTextArea instructionTextArea = new JTextArea();
+        instructionTextArea.setText(INSTRUCTIONS);
+        instructionTextArea.setEditable(false);
+        instructionTextArea.setBackground(Color.white);
+
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(instructionTextArea, gbc);
+
+        JButton passButton = new JButton("Pass");
+        passButton.setActionCommand("Pass");
+        passButton.addActionListener((ActionEvent e) -> {
+            testResult = true;
+            mainFrame.dispose();
+            countDownLatch.countDown();
+
+        });
+
+        JButton failButton = new JButton("Fail");
+        failButton.setActionCommand("Fail");
+        failButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        resultButtonPanel.add(passButton, gbc);
+
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        resultButtonPanel.add(failButton, gbc);
+
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        mainControlPanel.add(resultButtonPanel, gbc);
+
+        mainFrame.add(mainControlPanel);
+        mainFrame.pack();
+
+        mainFrame.addWindowListener(new WindowAdapter() {
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+        mainFrame.setVisible(true);
+    }
+
+    private static JPanel createJPanel() {
+        JPanel panel = new JPanel();
+        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+
+        JPanel iconPanel = new JPanel(new FlowLayout());
+        JRadioButton radioButton = new JRadioButton();
+        radioButton.setSelected(false);
+        iconPanel.add(radioButton);
+        radioButton = new JRadioButton();
+        radioButton.setSelected(true);
+        iconPanel.add(radioButton);
+        panel.add(iconPanel);
+
+        iconPanel = new JPanel(new FlowLayout());
+        JCheckBox checkBox = new JCheckBox();
+        checkBox.setSelected(false);
+        iconPanel.add(checkBox);
+        checkBox = new JCheckBox();
+        checkBox.setSelected(true);
+        iconPanel.add(checkBox);
+        panel.add(iconPanel);
+
+        iconPanel = new JPanel(new FlowLayout());
+        JComboBox<String> comboBox = new JComboBox(new String[]{"111", "222"});
+        iconPanel.add(comboBox);
+        panel.add(iconPanel);
+
+        iconPanel = new JPanel(new FlowLayout());
+        JTextArea textArea = new JTextArea(3, 7);
+        textArea.setText("AAA");
+        JScrollPane scrollPane = new JScrollPane(textArea);
+        scrollPane.setHorizontalScrollBarPolicy(
+                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
+        scrollPane.setVerticalScrollBarPolicy(
+                ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
+        iconPanel.add(scrollPane);
+        panel.add(iconPanel);
+
+        return panel;
+    }
+}
--- a/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/javax/swing/text/CSSBorder/6796710/bug6796710.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,11 +24,10 @@
 /*
  * @test
  * @key headful
- * @bug 6796710 7124242
+ * @bug 6796710 7124242 8168540
  * @summary Html content in JEditorPane is overlapping on swing components while resizing the application.
  * @library ../../../regtesthelpers
  * @build Util
- * @author Pavel Porvatov
    @run main bug6796710
  */
 
@@ -109,7 +108,7 @@
             }
         });
 
-        robot.waitForIdle();
+        robot.delay(1000);
 
         // On Linux platforms realSync doesn't guaranties setSize completion
         Thread.sleep(1000);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/Caret/8163124/CaretFloatingPointAPITest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.Dimension;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.awt.geom.Line2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.TextUI;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Caret;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Document;
+import javax.swing.text.Highlighter;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Position;
+
+/*
+ * @test
+ * @bug 8163175
+ * @summary PlainView.modelToView() method should return Rectangle2D
+ * @run main/manual CaretFloatingPointAPITest
+ */
+public class CaretFloatingPointAPITest {
+
+    private static volatile boolean testResult = false;
+    private static volatile CountDownLatch countDownLatch;
+    private static final String INSTRUCTIONS = "INSTRUCTIONS:\n\n"
+            + "Verify that cursor position is not rounded on HiDPI display.\n\n"
+            + "If the display does not support HiDPI mode press PASS.\n\n"
+            + "1. Press the Right-Arrow key several times to move the red caret"
+            + " in the text field.\n"
+            + "2. Check that the caret has the same position between chars"
+            + " in diffrent locations.\n\n"
+            + "If so, press PASS, else press FAIL.\n";
+
+    public static void main(String args[]) throws Exception {
+        countDownLatch = new CountDownLatch(1);
+
+        SwingUtilities.invokeLater(CaretFloatingPointAPITest::createUI);
+        countDownLatch.await(15, TimeUnit.MINUTES);
+
+        if (!testResult) {
+            throw new RuntimeException("Test fails!");
+        }
+    }
+
+    private static void createUI() {
+
+        final JFrame mainFrame = new JFrame("Metal L&F icons test");
+        GridBagLayout layout = new GridBagLayout();
+        JPanel mainControlPanel = new JPanel(layout);
+        JPanel resultButtonPanel = new JPanel(layout);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaa");
+        Dimension size = new Dimension(400, 100);
+        textField.setPreferredSize(size);
+        textField.setFont(textField.getFont().deriveFont(28.0f));
+        textField.setCaretColor(Color.RED);
+        textField.setCaret(new CustomCaret());
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.insets = new Insets(5, 15, 5, 15);
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(textField, gbc);
+
+        JTextArea instructionTextArea = new JTextArea();
+        instructionTextArea.setText(INSTRUCTIONS);
+        instructionTextArea.setEditable(false);
+        instructionTextArea.setBackground(Color.white);
+
+        gbc.gridx = 0;
+        gbc.gridy = 1;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(instructionTextArea, gbc);
+
+        JButton passButton = new JButton("Pass");
+        passButton.setActionCommand("Pass");
+        passButton.addActionListener((ActionEvent e) -> {
+            testResult = true;
+            mainFrame.dispose();
+            countDownLatch.countDown();
+
+        });
+
+        JButton failButton = new JButton("Fail");
+        failButton.setActionCommand("Fail");
+        failButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+
+        resultButtonPanel.add(passButton, gbc);
+
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        resultButtonPanel.add(failButton, gbc);
+
+        gbc.gridx = 0;
+        gbc.gridy = 2;
+        mainControlPanel.add(resultButtonPanel, gbc);
+
+        mainFrame.add(mainControlPanel);
+        mainFrame.pack();
+
+        mainFrame.addWindowListener(new WindowAdapter() {
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                mainFrame.dispose();
+                countDownLatch.countDown();
+            }
+        });
+        mainFrame.setVisible(true);
+    }
+
+    static class CustomCaret implements Caret {
+
+        private JTextComponent component;
+        private boolean visible;
+        private boolean selectionVisible = true;
+        int blinkRate;
+        int dot;
+        int mark;
+        Position.Bias dotBias;
+        Position.Bias markBias;
+        Object selectionTag;
+        Point2D magicCaretPosition;
+
+        private MouseListener mouseListener = new CaretMouseListener();
+
+        @Override
+        public void install(JTextComponent c) {
+            this.component = c;
+            c.addMouseListener(mouseListener);
+        }
+
+        @Override
+        public void deinstall(JTextComponent c) {
+            c.removeMouseListener(mouseListener);
+            this.component = null;
+        }
+
+        @Override
+        public void paint(Graphics g) {
+
+            if (component == null) {
+                return;
+            }
+
+            int dot = getDot();
+            Rectangle2D r = null;
+            try {
+                r = component.modelToView2D(dot);
+            } catch (BadLocationException e) {
+                return;
+            }
+
+            if (r == null) {
+                return;
+            }
+
+            Rectangle2D cr = getCaretRectangle(r);
+            repaint(cr.getBounds());
+
+            g.setColor(component.getCaretColor());
+            float cx = (float) cr.getX();
+            float cy = (float) cr.getY();
+            float cw = (float) cr.getWidth();
+            float ch = (float) cr.getHeight();
+            float c = cx + cw / 2;
+
+            Graphics2D g2d = (Graphics2D) g;
+            g2d.draw(new Line2D.Float(c, cy, c, cy + ch));
+            g2d.draw(new Line2D.Float(cx, cy, cx + cw, cy));
+            g2d.draw(new Line2D.Float(cx, cy + ch, cx + cw, cy + ch));
+        }
+
+        void repaint(Rectangle r) {
+            component.repaint(r);
+        }
+
+        Rectangle2D getCaretRectangle(Rectangle2D r) {
+            int d = 3;
+            double cx = r.getX() - d;
+            double cy = r.getY();
+            double cw = 2 * d;
+            double ch = r.getHeight();
+            return new Rectangle2D.Double(cx, cy, cw, ch);
+        }
+
+        @Override
+        public void addChangeListener(ChangeListener l) {
+        }
+
+        @Override
+        public void removeChangeListener(ChangeListener l) {
+        }
+
+        @Override
+        public boolean isVisible() {
+            return visible;
+        }
+
+        @Override
+        public void setVisible(boolean v) {
+            this.visible = true;
+        }
+
+        @Override
+        public boolean isSelectionVisible() {
+            return selectionVisible;
+        }
+
+        @Override
+        public void setSelectionVisible(boolean v) {
+            this.selectionVisible = v;
+            updateSelection();
+        }
+
+        @Override
+        public void setMagicCaretPosition(Point p) {
+            magicCaretPosition = p;
+        }
+
+        @Override
+        public Point getMagicCaretPosition() {
+            if (magicCaretPosition != null) {
+                return new Point((int) magicCaretPosition.getX(),
+                                 (int) magicCaretPosition.getY());
+            }
+            return null;
+        }
+
+        @Override
+        public void setBlinkRate(int rate) {
+            this.blinkRate = rate;
+        }
+
+        @Override
+        public int getBlinkRate() {
+            return blinkRate;
+        }
+
+        @Override
+        public int getDot() {
+            return dot;
+        }
+
+        @Override
+        public int getMark() {
+            return mark;
+        }
+
+        @Override
+        public void setDot(int dot) {
+            setDot(dot, Position.Bias.Forward);
+        }
+
+        private void setDot(int dot, Position.Bias bias) {
+            handleSetDot(dot, bias);
+            updateSelection();
+        }
+
+        @Override
+        public void moveDot(int dot) {
+            moveDot(dot, Position.Bias.Forward);
+        }
+
+        private void moveDot(int dot, Position.Bias bias) {
+            changeCaretPosition(dot, bias);
+            updateSelection();
+        }
+
+        void handleSetDot(int dot, Position.Bias dotBias) {
+
+            if (component == null) {
+                return;
+            }
+
+            Document doc = component.getDocument();
+            if (doc != null) {
+                dot = Math.min(dot, doc.getLength());
+            }
+
+            dot = Math.max(dot, 0);
+
+            if (dot == 0) {
+                dotBias = Position.Bias.Forward;
+            }
+
+            mark = dot;
+
+            if (this.dot != dot || this.dotBias != dotBias) {
+                changeCaretPosition(dot, dotBias);
+                updateSelection();
+            }
+
+            this.markBias = this.dotBias;
+        }
+
+        void changeCaretPosition(int dot, Position.Bias dotBias) {
+            this.dot = dot;
+            this.dotBias = dotBias;
+            setMagicCaretPosition(null);
+            SwingUtilities.invokeLater(this::repaintNewCaret);
+        }
+
+        private void updateSelection() {
+            Highlighter h = component.getHighlighter();
+            if (h != null) {
+                int p0 = Math.min(dot, mark);
+                int p1 = Math.max(dot, mark);
+
+                if (p0 == p1 || !selectionVisible) {
+                    if (selectionTag != null) {
+                        h.removeHighlight(selectionTag);
+                        selectionTag = null;
+                    }
+                } else {
+                    try {
+                        if (selectionTag != null) {
+                            h.changeHighlight(selectionTag, p0, p1);
+                        } else {
+                            Highlighter.HighlightPainter p = getSelectionPainter();
+                            selectionTag = h.addHighlight(p0, p1, p);
+                        }
+                    } catch (BadLocationException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+            }
+        }
+
+        void repaintNewCaret() {
+            if (component != null) {
+                TextUI mapper = component.getUI();
+                Document doc = component.getDocument();
+                if ((mapper != null) && (doc != null)) {
+                    Rectangle2D newLoc;
+                    try {
+                        newLoc = mapper.modelToView2D(component, this.dot, this.dotBias);
+                    } catch (BadLocationException e) {
+                        newLoc = null;
+                    }
+                    if (newLoc != null) {
+                        adjustVisibility(newLoc.getBounds());
+                        if (getMagicCaretPosition() == null) {
+                            setMagicCaretPosition(new Point((int) newLoc.getX(),
+                                                            (int) newLoc.getY()));
+                        }
+                    }
+                    damage(newLoc.getBounds());
+                }
+            }
+        }
+
+        protected Highlighter.HighlightPainter getSelectionPainter() {
+            return DefaultHighlighter.DefaultPainter;
+        }
+
+        protected void adjustVisibility(Rectangle nloc) {
+            if (component == null) {
+                return;
+            }
+            if (SwingUtilities.isEventDispatchThread()) {
+                component.scrollRectToVisible(nloc);
+            } else {
+                SwingUtilities.invokeLater(() -> {
+                    component.scrollRectToVisible(nloc);
+                });
+            }
+        }
+
+        protected synchronized void damage(Rectangle r) {
+            if (r != null && component != null) {
+                component.repaint(r);
+            }
+        }
+
+        private class CaretMouseListener extends MouseAdapter {
+
+            @Override
+            public void mousePressed(MouseEvent e) {
+                Point pt = new Point(e.getX(), e.getY());
+                Position.Bias[] biasRet = new Position.Bias[1];
+                int pos = component.getUI().viewToModel(component, pt, biasRet);
+                if (biasRet[0] == null) {
+                    biasRet[0] = Position.Bias.Forward;
+                }
+                if (pos >= 0) {
+                    setDot(pos);
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/JTextComponent/8156217/TextSelectionTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.SwingUtilities;
+import javax.swing.text.JTextComponent;
+
+/**
+ * @test
+ * @bug 8156217
+ * @summary Selected text is shifted on HiDPI display
+ * @run main/manual/othervm -Dsun.java2d.uiScale=2 TextSelectionTest
+ */
+public class TextSelectionTest {
+
+    private static final String INSTRUCTIONS = "This is a manual test.\n"
+            + "\n"
+            + "Select the current text from the end to the beginning.\n"
+            + "\n"
+            + "If the text is slightly shiftted from one side to another\n"
+            + "and back during selection press Fail.\n"
+            + "Otherwise, press Pass.";
+
+    private static final CountDownLatch latch = new CountDownLatch(1);
+    private static volatile boolean passed = false;
+
+    public static void main(String[] args) throws Exception {
+        SwingUtilities.invokeAndWait(TextSelectionTest::createAndShowGUI);
+        latch.await(3, TimeUnit.MINUTES);
+        System.out.println("passed: " + passed);
+        if (!passed) {
+            throw new RuntimeException("Test fails!");
+        }
+    }
+
+    private static void createAndShowGUI() {
+
+        JFrame frame = new JFrame("Follow the instructions below:");
+        frame.setSize(700, 500);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        JPanel panel = new JPanel(new BorderLayout());
+        JTextComponent textComponent = new JTextArea(INSTRUCTIONS);
+        textComponent.setEditable(false);
+        Font font = textComponent.getFont();
+        font = font.deriveFont(24.0f);
+        textComponent.setFont(font);
+        panel.add(textComponent, BorderLayout.CENTER);
+
+        JPanel buttonsPanel = new JPanel(new FlowLayout());
+        JButton passButton = new JButton("Pass");
+        passButton.addActionListener((e) -> {
+            passed = true;
+            latch.countDown();
+            frame.dispose();
+        });
+        JButton failsButton = new JButton("Fail");
+        failsButton.addActionListener((e) -> {
+            passed = false;
+            latch.countDown();
+            frame.dispose();
+        });
+
+        buttonsPanel.add(passButton);
+        buttonsPanel.add(failsButton);
+        panel.add(buttonsPanel, BorderLayout.SOUTH);
+
+        frame.getContentPane().add(panel);
+
+        frame.addWindowListener(new WindowAdapter() {
+
+            @Override
+            public void windowClosing(WindowEvent e) {
+                latch.countDown();
+            }
+        });
+        frame.setVisible(true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/text/View/8156217/FPMethodCalledTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.FlowLayout;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Robot;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.plaf.metal.MetalLookAndFeel;
+import javax.swing.plaf.metal.MetalTextFieldUI;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Element;
+import javax.swing.text.PasswordView;
+import javax.swing.text.PlainView;
+import javax.swing.text.View;
+import javax.swing.text.WrappedPlainView;
+
+/**
+ * @test
+ * @bug 8156217
+ * @key headful
+ * @summary Selected text is shifted on HiDPI display
+ * @run main FPMethodCalledTest
+ */
+public class FPMethodCalledTest {
+
+    private static JFrame frame;
+    private static JTextField textField;
+
+    public static void main(String[] args) throws Exception {
+
+        for (Test test : TESTS) {
+            test(test);
+        }
+    }
+
+    static void test(final Test test) throws Exception {
+        try {
+            Robot robot = new Robot();
+            robot.setAutoDelay(50);
+            SwingUtilities.invokeAndWait(() -> {
+                createAndShowGUI(test);
+            });
+
+            robot.waitForIdle();
+
+            SwingUtilities.invokeAndWait(() -> {
+                textField.select(1, 3);
+            });
+
+            robot.waitForIdle();
+
+            SwingUtilities.invokeAndWait(() -> {
+                Resultable resultable = test.resultable;
+                if (!resultable.getResult()) {
+                    throw new RuntimeException("Test fails for: " + resultable);
+                }
+            });
+        } finally {
+            SwingUtilities.invokeAndWait(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            });
+        }
+    }
+
+    static void createAndShowGUI(Test test) {
+
+        try {
+            UIManager.setLookAndFeel(new MetalLookAndFeel());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        frame = new JFrame();
+        frame.setSize(300, 300);
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+        JPanel panel = new JPanel(new FlowLayout());
+
+        String text = "AAAAAAA";
+        textField = test.isPasswordField()
+                ? new JPasswordField(text)
+                : new JTextField(text);
+
+        textField.setUI(new MetalTextFieldUI() {
+
+            @Override
+            public View create(Element elem) {
+                return test.createView(elem);
+            }
+        });
+
+        panel.add(textField);
+        frame.getContentPane().add(panel);
+        frame.setVisible(true);
+    }
+
+    private static final Test[] TESTS = {
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                PlainViewINTAPI view = new PlainViewINTAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                PlainViewFPAPI view = new PlainViewFPAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                PlainViewMixedAPI view = new PlainViewMixedAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                WrappedPlainViewINTAPI view = new WrappedPlainViewINTAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                WrappedPlainViewFPAPI view = new WrappedPlainViewFPAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test() {
+            @Override
+            View createView(Element elem) {
+                WrappedPlainViewMixedAPI view = new WrappedPlainViewMixedAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test(true) {
+
+            @Override
+            View createView(Element elem) {
+                PasswordViewINTAPI view = new PasswordViewINTAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test(true) {
+
+            @Override
+            View createView(Element elem) {
+                PasswordViewFPAPI view = new PasswordViewFPAPI(elem);
+                resultable = view;
+                return view;
+            }
+        },
+        new Test(true) {
+
+            @Override
+            View createView(Element elem) {
+                PasswordViewMixedAPI view = new PasswordViewMixedAPI(elem);
+                resultable = view;
+                return view;
+            }
+        }
+    };
+
+    static interface Resultable {
+
+        boolean getResult();
+    }
+
+    static abstract class Test {
+
+        Resultable resultable;
+        final boolean isPasswordField;
+
+        public Test() {
+            this(false);
+        }
+
+        public Test(boolean isPasswordField) {
+            this.isPasswordField = isPasswordField;
+        }
+
+        boolean isPasswordField() {
+            return isPasswordField;
+        }
+
+        abstract View createView(Element elem);
+    }
+
+    static class PlainViewINTAPI extends PlainView implements Resultable {
+
+        boolean drawLine = false;
+        boolean drawSelected = false;
+        boolean drawUnselected = false;
+
+        public PlainViewINTAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected void drawLine(int lineIndex, Graphics g, int x, int y) {
+            drawLine = true;
+            super.drawLine(lineIndex, g, x, y);
+        }
+
+        @Override
+        protected int drawSelectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            drawSelected = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected int drawUnselectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            drawUnselected = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return drawLine && drawSelected && drawUnselected;
+        }
+    }
+
+    static class PlainViewFPAPI extends PlainView implements Resultable {
+
+        boolean drawLine = false;
+        boolean drawSelected = false;
+        boolean drawUnselected = false;
+
+        public PlainViewFPAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected void drawLine(int lineIndex, Graphics2D g, float x, float y) {
+            drawLine = true;
+            super.drawLine(lineIndex, g, x, y);
+        }
+
+        @Override
+        protected float drawSelectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            drawSelected = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected float drawUnselectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            drawUnselected = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return drawSelected;
+        }
+    }
+
+    static class PlainViewMixedAPI extends PlainView implements Resultable {
+
+        boolean isIntMethodCalled = false;
+        boolean isFPMethodCalled = false;
+
+        public PlainViewMixedAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected int drawSelectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            isIntMethodCalled = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected float drawSelectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            isFPMethodCalled = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return !isIntMethodCalled && isFPMethodCalled;
+        }
+    }
+
+    static class WrappedPlainViewINTAPI extends WrappedPlainView implements Resultable {
+
+        boolean drawLine = false;
+        boolean drawSelected = false;
+        boolean drawUnselected = false;
+
+        public WrappedPlainViewINTAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected void drawLine(int p0, int p1, Graphics g, int x, int y) {
+            drawLine = true;
+            super.drawLine(p0, p1, g, x, y);
+        }
+
+        @Override
+        protected int drawSelectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            drawSelected = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected int drawUnselectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            drawUnselected = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return drawLine && drawSelected && drawUnselected;
+        }
+    }
+
+    static class WrappedPlainViewFPAPI extends WrappedPlainView implements Resultable {
+
+        boolean drawLine = false;
+        boolean drawSelected = false;
+        boolean drawUnselected = false;
+
+        public WrappedPlainViewFPAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected void drawLine(int p0, int p1, Graphics2D g, float x, float y) {
+            drawLine = true;
+            super.drawLine(p0, p1, g, x, y);
+        }
+
+        @Override
+        protected float drawSelectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            drawSelected = true;
+            return super.drawSelectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected float drawUnselectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            drawUnselected = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return drawLine && drawSelected && drawUnselected;
+        }
+    }
+
+    static class WrappedPlainViewMixedAPI extends WrappedPlainView implements Resultable {
+
+        boolean isIntMethodCalled = false;
+        boolean isFPMethodCalled = false;
+
+        public WrappedPlainViewMixedAPI(Element elem) {
+            super(elem);
+        }
+
+        @Override
+        protected int drawUnselectedText(Graphics g, int x, int y,
+                int p0, int p1) throws BadLocationException {
+            isIntMethodCalled = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        protected float drawUnselectedText(Graphics2D g, float x, float y,
+                int p0, int p1) throws BadLocationException {
+            isFPMethodCalled = true;
+            return super.drawUnselectedText(g, x, y, p0, p1);
+        }
+
+        @Override
+        public boolean getResult() {
+            return !isIntMethodCalled && isFPMethodCalled;
+        }
+    }
+
+    static class PasswordViewINTAPI extends PasswordView implements Resultable {
+
+        boolean isIntMethodCalled = false;
+
+        public PasswordViewINTAPI(Element elem) {
+            super(elem);
+
+        }
+
+        @Override
+        protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
+            isIntMethodCalled = true;
+            return super.drawEchoCharacter(g, x, y, c);
+        }
+
+        @Override
+        public boolean getResult() {
+            return isIntMethodCalled;
+        }
+    }
+
+    static class PasswordViewFPAPI extends PasswordView implements Resultable {
+
+        boolean isFPMethodCalled = false;
+
+        public PasswordViewFPAPI(Element elem) {
+            super(elem);
+
+        }
+
+        @Override
+        protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
+            isFPMethodCalled = true;
+            return super.drawEchoCharacter(g, x, y, c);
+        }
+
+        @Override
+        public boolean getResult() {
+            return isFPMethodCalled;
+        }
+    }
+
+    static class PasswordViewMixedAPI extends PasswordView implements Resultable {
+
+        boolean isIntMethodCalled = false;
+        boolean isFPMethodCalled = false;
+
+        public PasswordViewMixedAPI(Element elem) {
+            super(elem);
+
+        }
+
+        @Override
+        protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
+            isIntMethodCalled = true;
+            return super.drawEchoCharacter(g, x, y, c);
+        }
+
+        @Override
+        protected float drawEchoCharacter(Graphics2D g, float x, float y, char c) {
+            isFPMethodCalled = true;
+            return super.drawEchoCharacter(g, x, y, c);
+        }
+
+        @Override
+        public boolean getResult() {
+            return !isIntMethodCalled && isFPMethodCalled;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/editpad/EditPadTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8167636 8167639 8168972
+ * @summary Testing built-in editor.
+ * @modules java.desktop/java.awt
+ *          jdk.internal.ed/jdk.internal.editor.spi
+ *          jdk.editpad/jdk.editpad
+ * @run testng EditPadTest
+ */
+
+import java.awt.AWTException;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GraphicsEnvironment;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.WindowEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ServiceLoader;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.function.Consumer;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JViewport;
+import javax.swing.SwingUtilities;
+
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import jdk.internal.editor.spi.BuildInEditorProvider;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test
+public class EditPadTest {
+
+    private static final int DELAY = 500;
+    private static final String WINDOW_LABEL = "Test Edit Pad";
+
+    private static ExecutorService executor;
+    private static Robot robot;
+    private static JFrame frame = null;
+    private static JTextArea area = null;
+    private static JButton cancel = null;
+    private static JButton accept = null;
+    private static JButton exit = null;
+
+    @BeforeClass
+    public static void setUpEditorPadTest() {
+        if (!GraphicsEnvironment.isHeadless()) {
+            try {
+                robot = new Robot();
+                robot.setAutoWaitForIdle(true);
+                robot.setAutoDelay(DELAY);
+            } catch (AWTException e) {
+                throw new ExceptionInInitializerError(e);
+            }
+        }
+    }
+
+    @AfterClass
+    public static void shutdown() {
+        executorShutdown();
+    }
+
+    public void testSimple() {
+        testEdit("abcdef", 1, "xyz",
+                () -> assertSource("abcdef"),
+                () -> writeSource("xyz"),
+                () -> accept(),
+                () -> assertSource("xyz"),
+                () -> shutdownEditor());
+    }
+
+    public void testCancel() {
+        testEdit("abcdef", 0, "abcdef",
+                () -> assertSource("abcdef"),
+                () -> writeSource("xyz"),
+                () -> cancel());
+    }
+
+    public void testAbort() {
+        testEdit("abcdef", 0, "abcdef",
+                () -> assertSource("abcdef"),
+                () -> writeSource("xyz"),
+                () -> shutdownEditor());
+    }
+
+    public void testAcceptCancel() {
+        testEdit("abcdef", 1, "xyz",
+                () -> assertSource("abcdef"),
+                () -> writeSource("xyz"),
+                () -> accept(),
+                () -> assertSource("xyz"),
+                () -> writeSource("!!!!!!!!!"),
+                () -> cancel());
+    }
+
+    public void testAcceptEdit() {
+        testEdit("abcdef", 2, "xyz",
+                () -> assertSource("abcdef"),
+                () -> writeSource("NoNo"),
+                () -> accept(),
+                () -> assertSource("NoNo"),
+                () -> writeSource("xyz"),
+                () -> exit());
+    }
+
+    private void testEdit(String initialText,
+            int savedCount, String savedText, Runnable... actions) {
+        class Handler {
+
+            String text = null;
+            int count = 0;
+
+            void handle(String s) {
+                ++count;
+                text = s;
+            }
+        }
+        Handler save = new Handler();
+        Handler error = new Handler();
+
+        if (GraphicsEnvironment.isHeadless()) {
+            // Do not actually run if we are headless
+            return;
+        }
+        Future<?> task = doActions(actions);
+        builtInEdit(initialText, save::handle, error::handle);
+        complete(task);
+        assertEquals(error.count, 0, "Error: " + error.text);
+        assertTrue(save.count != savedCount
+                || save.text == null
+                    ? savedText != null
+                    : savedText.equals(save.text),
+                "Expected " + savedCount + " saves, got " + save.count
+                + ", expected \"" + savedText + "\" got \"" + save.text + "\"");
+    }
+
+    private static ExecutorService getExecutor() {
+        if (executor == null) {
+            executor = Executors.newSingleThreadExecutor();
+        }
+        return executor;
+    }
+
+    private static void executorShutdown() {
+        if (executor != null) {
+            executor.shutdown();
+            executor = null;
+        }
+    }
+
+    private void builtInEdit(String initialText,
+            Consumer<String> saveHandler, Consumer<String> errorHandler) {
+        ServiceLoader<BuildInEditorProvider> sl
+                = ServiceLoader.load(BuildInEditorProvider.class);
+        // Find the highest ranking provider
+        BuildInEditorProvider provider = null;
+        for (BuildInEditorProvider p : sl) {
+            if (provider == null || p.rank() > provider.rank()) {
+                provider = p;
+            }
+        }
+        if (provider != null) {
+            provider.edit(WINDOW_LABEL,
+                    initialText, saveHandler, errorHandler);
+        } else {
+            throw new InternalError("Cannot find provider");
+        }
+    }
+
+    private Future<?> doActions(Runnable... actions) {
+        return getExecutor().submit(() -> {
+            try {
+                waitForIdle();
+                SwingUtilities.invokeLater(this::seekElements);
+                waitForIdle();
+                for (Runnable act : actions) {
+                    act.run();
+                }
+            } catch (Throwable e) {
+                shutdownEditor();
+                if (e instanceof AssertionError) {
+                    throw (AssertionError) e;
+                }
+                throw new RuntimeException(e);
+            }
+        });
+    }
+
+    private void complete(Future<?> task) {
+        try {
+            task.get();
+            waitForIdle();
+        } catch (ExecutionException e) {
+            if (e.getCause() instanceof AssertionError) {
+                throw (AssertionError) e.getCause();
+            }
+            throw new RuntimeException(e);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        } finally {
+            shutdownEditor();
+        }
+    }
+
+    private void writeSource(String s) {
+        SwingUtilities.invokeLater(() -> area.setText(s));
+    }
+
+    private void assertSource(String expected) {
+        String[] s = new String[1];
+        try {
+            SwingUtilities.invokeAndWait(() -> s[0] = area.getText());
+        } catch (InvocationTargetException | InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+        assertEquals(s[0], expected);
+    }
+
+    private void accept() {
+        clickOn(accept);
+    }
+
+    private void exit() {
+        clickOn(exit);
+    }
+
+    private void cancel() {
+        clickOn(cancel);
+    }
+
+    private void shutdownEditor() {
+        SwingUtilities.invokeLater(this::clearElements);
+        waitForIdle();
+    }
+
+    private void waitForIdle() {
+        robot.waitForIdle();
+        robot.delay(DELAY);
+    }
+
+    private void seekElements() {
+        for (Frame f : Frame.getFrames()) {
+            if (f.getTitle().equals(WINDOW_LABEL)) {
+                frame = (JFrame) f;
+                // workaround
+                frame.setLocation(0, 0);
+                Container root = frame.getContentPane();
+                for (Component c : root.getComponents()) {
+                    if (c instanceof JScrollPane) {
+                        JScrollPane scrollPane = (JScrollPane) c;
+                        for (Component comp : scrollPane.getComponents()) {
+                            if (comp instanceof JViewport) {
+                                JViewport view = (JViewport) comp;
+                                area = (JTextArea) view.getComponent(0);
+                            }
+                        }
+                    }
+                    if (c instanceof JPanel) {
+                        JPanel p = (JPanel) c;
+                        for (Component comp : p.getComponents()) {
+                            if (comp instanceof JButton) {
+                                JButton b = (JButton) comp;
+                                switch (b.getText()) {
+                                    case "Cancel":
+                                        cancel = b;
+                                        break;
+                                    case "Exit":
+                                        exit = b;
+                                        break;
+                                    case "Accept":
+                                        accept = b;
+                                        break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private void clearElements() {
+        if (frame != null) {
+            frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
+            frame = null;
+        }
+        area = null;
+        accept = null;
+        cancel = null;
+        exit = null;
+    }
+
+    private void clickOn(JButton button) {
+        waitForIdle();
+        waitForIdle();
+        waitForIdle();
+        waitForIdle();
+        waitForIdle();
+        waitForIdle();
+        Point p = button.getLocationOnScreen();
+        Dimension d = button.getSize();
+        robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
+        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+    }
+}
--- a/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/reflect/ReflectionFactory/ReflectionFactoryTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -45,7 +45,7 @@
 
 /*
  * @test
- * @bug 8137058 8164908
+ * @bug 8137058 8164908 8168980
  * @run testng ReflectionFactoryTest
  * @run testng/othervm/policy=security.policy ReflectionFactoryTest
  * @summary Basic test for the unsupported ReflectionFactory
@@ -95,6 +95,47 @@
         }
     }
 
+    @DataProvider(name = "NonSerialConstructors")
+    static Object[][] constructors() throws NoSuchMethodException {
+        return new Object[][] {
+                {Foo.class, Object.class.getDeclaredConstructor()},
+                {Foo.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Object.class.getDeclaredConstructor()},
+                {Baz.class, Foo.class.getDeclaredConstructor()},
+                {Baz.class, Baz.class.getDeclaredConstructor()}
+        };
+    }
+
+    /**
+     * Tests that the given Constructor, in the hierarchy, is run.
+     */
+    @Test(dataProvider="NonSerialConstructors")
+    static void testNonSerializableConstructor(Class<?> cl,
+                                               Constructor<?> constructorToCall)
+        throws ReflectiveOperationException
+    {
+        @SuppressWarnings("unchecked")
+        Constructor<?> c = factory.newConstructorForSerialization(cl,
+                                                                  constructorToCall);
+
+        Object o = c.newInstance();
+        Assert.assertEquals(o.getClass(), cl, "Instance is wrong type");
+
+        int expectedFoo = 0;
+        int expectedBaz = 0;
+        if (constructorToCall.getName().equals("ReflectionFactoryTest$Foo")) {
+            expectedFoo = 1;
+        } else if (constructorToCall.getName().equals("ReflectionFactoryTest$Baz")) {
+            expectedFoo = 1;
+            expectedBaz = 4;
+        }
+
+        Assert.assertEquals(((Foo)o).foo(), expectedFoo);
+        if (o instanceof Baz) {
+            Assert.assertEquals(((Baz)o).baz(), expectedBaz);
+        }
+    }
+
     static class Foo {
         private int foo;
         public Foo() {
@@ -109,6 +150,8 @@
             int expectedFoo = 1;
             Assert.assertEquals(foo, expectedFoo, "foo() constructor not run");
         }
+
+        public int foo() { return foo; }
     }
 
     static class Bar extends Foo implements Serializable {
@@ -128,6 +171,12 @@
         }
     }
 
+    static class Baz extends Foo {
+        private final int baz;
+        public Baz() { this.baz = 4; }
+        public int baz() { return baz; }
+    }
+
     /**
      * Test newConstructorForExternalization returns the constructor and it can be called.
      * @throws NoSuchMethodException - error
--- a/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/rmi/runtime/Log/6409194/NoConsoleOutput.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -35,7 +35,7 @@
  *          java.rmi/sun.rmi.server
  *          java.rmi/sun.rmi.transport
  *          java.rmi/sun.rmi.transport.tcp
- * @build TestLibrary JavaVM
+ * @build JavaVM
  * @run main/othervm NoConsoleOutput
  */
 
@@ -43,8 +43,6 @@
 import java.io.File;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
-import java.rmi.registry.LocateRegistry;
-import java.rmi.registry.Registry;
 import java.rmi.server.UnicastRemoteObject;
 
 public class NoConsoleOutput {
@@ -53,7 +51,7 @@
         System.err.println("\nRegression test for bug 6409194\n");
 
         /*
-         * Exdecute a subprocess VM that does a bunch of RMI activity
+         * Execute a subprocess VM that does a bunch of RMI activity
          * with a logging configuration file that does not specify a
          * ConsoleHandler and with no legacy sun.rmi.*.logLevel system
          * properties set.
@@ -65,7 +63,7 @@
         ByteArrayOutputStream err = new ByteArrayOutputStream();
 
         // We instantiate a JavaVM that should not produce any console output
-        // (neither on standard output, nor on standard err streams).
+        // on standard err streams, where RMI logging messages are sent to.
         JavaVM vm = new JavaVM(
                 DoRMIStuff.class.getName(),
                 "--add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED"
@@ -77,8 +75,7 @@
         vm.execute();
 
         /*
-         * Verify that the subprocess had no System.out or System.err
-         * output.
+         * Verify that the subprocess had no System.err output.
          */
         String outString = out.toString();
         String errString = err.toString();
@@ -89,7 +86,7 @@
         System.err.print(err);
         System.err.println("---------------------------------------------");
 
-        if (outString.length() > 0 || errString.length() > 0) {
+        if (errString.length() > 0) {
             throw new Error("TEST FAILED: unexpected subprocess output");
         }
 
@@ -105,13 +102,8 @@
             public Object echo(Object obj) { return obj; }
         }
         public static void main(String[] args) throws Exception {
-            Registry registry = TestLibrary.createRegistryOnUnusedPort();
-            int registryPort = TestLibrary.getRegistryPort(registry);
-            Registry reg = LocateRegistry.getRegistry("", registryPort);
             FooImpl fooimpl = new FooImpl();
-            UnicastRemoteObject.exportObject(fooimpl, 0);
-            reg.rebind("foo", fooimpl);
-            Foo foostub = (Foo) reg.lookup("foo");
+            Foo foostub = (Foo) UnicastRemoteObject.exportObject(fooimpl, 0);
             FooImpl fooimpl2 = new FooImpl();
             UnicastRemoteObject.exportObject(fooimpl2, 0);
             foostub.echo(fooimpl2);
--- a/jdk/test/sun/security/ec/TestEC.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/ec/TestEC.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,7 +35,7 @@
  * @library ../pkcs11/sslecc
  * @library ../../../java/security/testlibrary
  * @modules jdk.crypto.pkcs11/sun.security.pkcs11.wrapper
- * @compile -XDignore.symbol.file TestEC.java
+ * @compile --add-modules jdk.crypto.pkcs11 TestEC.java
  * @run main/othervm -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC
  * @run main/othervm/java.security.policy=TestEC.policy -Djdk.tls.namedGroups="secp256r1,sect193r1" TestEC
  */
--- a/jdk/test/sun/security/krb5/auto/ReplayCacheExpunge.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/krb5/auto/ReplayCacheExpunge.java	Fri Nov 11 16:44:36 2016 +0100
@@ -47,15 +47,15 @@
         int count = Integer.parseInt(args[0]);
         ReplayCache cache = ReplayCache.getInstance("dfl:./");
         AuthTimeWithHash a1 =
-                new AuthTimeWithHash(client, server, time(-400), 0, hash("1"));
+                new AuthTimeWithHash(client, server, time(-400), 0, "HASH", hash("1"));
         AuthTimeWithHash a2 =
-                new AuthTimeWithHash(client, server, time(0), 0, hash("4"));
+                new AuthTimeWithHash(client, server, time(0), 0, "HASH", hash("4"));
         KerberosTime now = new KerberosTime(time(0)*1000L);
         KerberosTime then = new KerberosTime(time(-300)*1000L);
 
         // Once upon a time, we added a lot of events
         for (int i=0; i<count; i++) {
-            a1 = new AuthTimeWithHash(client, server, time(-400), 0, hash(""));
+            a1 = new AuthTimeWithHash(client, server, time(-400), 0, "HASH", hash(""));
             cache.checkAndStore(then, a1);
         }
 
--- a/jdk/test/sun/security/krb5/auto/ReplayCachePrecise.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/krb5/auto/ReplayCachePrecise.java	Fri Nov 11 16:44:36 2016 +0100
@@ -48,9 +48,9 @@
     public static void main(String[] args) throws Exception {
 
         AuthTimeWithHash a1 = new AuthTimeWithHash(client, server, time(0), 0,
-                "1111111111111111");
+                "HASH", "1111111111111111");
         AuthTimeWithHash a2 = new AuthTimeWithHash(client, server, time(0), 0,
-                "2222222222222222");
+                "HASH", "2222222222222222");
         KerberosTime now = new KerberosTime(time(0)*1000L);
 
         // When all new styles, must exact match
--- a/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/krb5/auto/ReplayCacheTestProc.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,11 +23,10 @@
 
 /*
  * @test
- * @bug 7152176
+ * @bug 7152176 8168518
  * @summary More krb5 tests
- * @library ../../../../java/security/testlibrary/
- * @compile -XDignore.symbol.file ReplayCacheTestProc.java
- * @run main/othervm/timeout=100 ReplayCacheTestProc
+ * @library ../../../../java/security/testlibrary/ /test/lib
+ * @run main/othervm/timeout=300 ReplayCacheTestProc
  */
 
 import java.io.*;
@@ -38,17 +37,40 @@
 import java.nio.file.StandardCopyOption;
 import java.nio.file.StandardOpenOption;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
+import jdk.test.lib.Platform;
 import sun.security.jgss.GSSUtil;
-import sun.security.krb5.internal.APReq;
 import sun.security.krb5.internal.rcache.AuthTime;
 
-// This test runs multiple acceptor Procs to mimin AP-REQ replays.
+/**
+ * This test runs multiple acceptor Procs to mimic AP-REQ replays.
+ * These system properties are supported:
+ *
+ * - test.libs on what types of acceptors to use
+ *   Format: CSV of (J|N|N<suffix>=<libname>|J<suffix>=<launcher>)
+ *   Default: J,N on Solaris and Linux where N is available, or J
+ *   Example: J,N,N14=/krb5-1.14/lib/libgssapi_krb5.so,J8=/java8/bin/java
+ *
+ * - test.runs on manual runs. If empty, a iterate through all pattern
+ *   Format: (req# | client# service#) acceptor# expected, ...
+ *   Default: null
+ *   Example: c0s0Jav,c1s1N14av,r0Jbx means 0th req is new c0->s0 sent to Ja,
+ *            1st req is new c1 to s1 sent to N14a,
+ *            2nd req is old (0th replayed) sent to Jb.
+ *            a/b at the end of acceptor is different acceptors of the same lib
+ *
+ * - test.autoruns on number of automatic runs
+ *   Format: number
+ *   Default: 100
+ */
 public class ReplayCacheTestProc {
 
-    private static Proc[] ps;
-    private static Proc pc;
+    private static Proc[] pa;   // all acceptors
+    private static Proc pi;     // the single initiator
     private static List<Req> reqs = new ArrayList<>();
     private static String HOST = "localhost";
 
@@ -59,119 +81,193 @@
                 "/var/krb5/rcache/" :
                 System.getProperty("user.dir");
 
+    private static MessageDigest md5, sha256;
+
+    static {
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            sha256 = MessageDigest.getInstance("SHA-256");
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new AssertionError("Impossible", nsae);
+        }
+    }
 
     private static long uid;
 
     public static void main0(String[] args) throws Exception {
         System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
         if (args.length == 0) { // The controller
-            int ns = 5;     // number of servers
-            int nu = 5;     // number of users
-            int nx = 50;    // number of experiments
-            int np = 5;     // number of peers (services)
-            int mode = 0;   // native(1), random(0), java(-1)
-            boolean random = true;      // random experiments choreograph
-
-            // Do not test interop with native GSS on some platforms
-            String os = System.getProperty("os.name", "???");
-            if (!os.startsWith("SunOS") && !os.startsWith("Linux")) {
-                mode = -1;
-            }
+            int nc = 5;     // number of clients
+            int ns = 5;     // number of services
+            String[] libs;  // available acceptor types:
+                            // J: java
+                            // J<suffix>=<java launcher>: another java
+                            // N: default native lib
+                            // N<suffix>=<libname>: another native lib
+            Ex[] result;
+            int numPerType = 2; // number of acceptors per type
 
             uid = jdk.internal.misc.VM.geteuid();
 
             KDC kdc = KDC.create(OneKDC.REALM, HOST, 0, true);
-            for (int i=0; i<nu; i++) {
-                kdc.addPrincipal(user(i), OneKDC.PASS);
+            for (int i=0; i<nc; i++) {
+                kdc.addPrincipal(client(i), OneKDC.PASS);
             }
             kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
-            for (int i=0; i<np; i++) {
-                kdc.addPrincipalRandKey(peer(i));
+            for (int i=0; i<ns; i++) {
+                kdc.addPrincipalRandKey(service(i));
             }
 
             kdc.writeKtab(OneKDC.KTAB);
             KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
 
-            if (mode != -1) {
-                // A special native server to check basic sanity
-                if (ns(-1).waitFor() != 0) {
-                    Proc.d("Native mode sanity check failed, revert to java");
-                    mode = -1;
+            // User-provided libs
+            String userLibs = System.getProperty("test.libs");
+
+            if (userLibs != null) {
+                libs = userLibs.split(",");
+            } else {
+                if (Platform.isOSX() || Platform.isWindows()) {
+                    // macOS uses Heimdal and Windows has no native lib
+                    libs = new String[]{"J"};
+                } else {
+                    if (acceptor("N", "sanity").waitFor() != 0) {
+                        Proc.d("Native mode sanity check failed, only java");
+                        libs = new String[]{"J"};
+                    } else {
+                        libs = new String[]{"J", "N"};
+                    }
                 }
             }
 
-            pc = Proc.create("ReplayCacheTestProc").debug("C")
-                    .args("client")
+            pi = Proc.create("ReplayCacheTestProc").debug("C")
+                    .args("initiator")
                     .start();
-            ps = new Proc[ns];
-            Ex[] result = new Ex[nx];
 
-            if (!random) {
-                // 2 experiments, 2 server, 1 peer, 1 user
-                nx = 2; ns = 2; np = 1; nu = 1;
+            int na = libs.length * numPerType;  // total number of acceptors
+            pa = new Proc[na];
 
-                // Creates reqs from user# to peer#
-                req(0, 0);
+            // Acceptors, numPerType for 1st, numForType for 2nd, ...
+            for (int i=0; i<na; i++) {
+                pa[i] = acceptor(libs[i/numPerType],
+                        "" + (char)('a' + i%numPerType));
+            }
 
-                // Creates server#
-                ps[0] = ns(0);
-                ps[1] = js(1);
+            // Manual runs
+            String userRuns = System.getProperty("test.runs");
 
-                // Runs ex# using req# to server# with expected result
-                result[0] = round(0, 0, 0, true);
-                result[1] = round(1, 0, 1, false);
-            } else {
+            if (userRuns == null) {
+                result = new Ex[Integer.parseInt(
+                        System.getProperty("test.autoruns", "100"))];
                 Random r = new Random();
-                for (int i=0; i<ns; i++) {
-                    boolean useNative = (mode == 1) ? true
-                            : (mode == -1 ? false : r.nextBoolean());
-                    ps[i] = useNative?ns(i):js(i);
+                for (int i = 0; i < result.length; i++) {
+                    boolean expected = reqs.isEmpty() || r.nextBoolean();
+                    result[i] = new Ex(
+                            i,
+                            expected ?
+                                    req(r.nextInt(nc), r.nextInt(ns)) :
+                                    r.nextInt(reqs.size()),
+                            pa[r.nextInt(na)],
+                            expected);
                 }
-                for (int i=0; i<nx; i++) {
-                    result[i] = new Ex();
-                    int old;    // which req to send
-                    boolean expected;
-                    if (reqs.isEmpty() || r.nextBoolean()) {
-                        Proc.d("Console get new AP-REQ");
-                        old = req(r.nextInt(nu), r.nextInt(np));
-                        expected = true;
-                    } else {
-                        Proc.d("Console resue old");
-                        old = r.nextInt(reqs.size());
-                        expected = false;
+            } else if (userRuns.isEmpty()) {
+                int count = 0;
+                result = new Ex[libs.length * libs.length];
+                for (int i = 0; i < libs.length; i++) {
+                    result[count] = new Ex(
+                            count,
+                            req(0, 0),
+                            pa[i * numPerType],
+                            true);
+                    count++;
+                    for (int j = 0; j < libs.length; j++) {
+                        if (i == j) {
+                            continue;
+                        }
+                        result[count] = new Ex(
+                                count,
+                                i,
+                                pa[j * numPerType],
+                                false);
+                        count++;
                     }
-                    int s = r.nextInt(ns);
-                    Proc.d("Console send to " + s);
-                    result[i] = round(i, old, s, expected);
-                    Proc.d("Console sees " + result[i].actual);
+                }
+            } else {
+                String[] runs = userRuns.split(",");
+                result = new Ex[runs.length];
+                for (int i = 0; i < runs.length; i++) {
+                    UserRun run = new UserRun(runs[i]);
+                    result[i] = new Ex(
+                            i,
+                            run.req() == -1 ?
+                                    req(run.client(), run.service()) :
+                                    result[run.req()].req,
+                            Arrays.stream(pa)
+                                    .filter(p -> p.debug().equals(run.acceptor()))
+                                    .findFirst()
+                                    .orElseThrow(() -> new Exception(
+                                            "no acceptor named " + run.acceptor())),
+                            run.success());
                 }
             }
 
-            pc.println("END");
-            for (int i=0; i<ns; i++) {
-                ps[i].println("END");
+            for (Ex x : result) {
+                x.run();
             }
-            System.out.println("Result\n======");
+
+            pi.println("END");
+            for (int i=0; i<na; i++) {
+                pa[i].println("END");
+            }
+            System.out.println("\nAll Test Results\n================");
             boolean finalOut = true;
-            for (int i=0; i<nx; i++) {
+            System.out.println("        req**  client    service  acceptor   Result");
+            System.out.println("----  -------  ------  ---------  --------  -------");
+            for (int i=0; i<result.length; i++) {
                 boolean out = result[i].expected==result[i].actual;
                 finalOut &= out;
-                System.out.printf("%3d: %s (%2d): u%d h%d %s %s   %s %2d\n",
+                System.out.printf("%3d:    %3d%s      c%d    s%d %4s  %8s   %s  %s\n",
                         i,
-                        result[i].expected?"----":"    ",
-                        result[i].old,
-                        result[i].user, result[i].peer, result[i].server,
-                        result[i].actual?"Good":"Bad ",
-                        out?"   ":"xxx",
-                        result[i].csize);
+                        result[i].req,
+                        result[i].expected ? "**" : "  ",
+                        reqs.get(result[i].req).client,
+                        reqs.get(result[i].req).service,
+                        "(" + result[i].csize + ")",
+                        result[i].acceptor.debug(),
+                        result[i].actual ? "++" : "--",
+                        out ? "   " : "xxx");
+            }
+
+            System.out.println("\nPath of Reqs\n============");
+            for (int j=0; ; j++) {
+                boolean found = false;
+                for (int i=0; i<result.length; i++) {
+                    if (result[i].req == j) {
+                        if (!found) {
+                            System.out.printf("%3d (c%s -> s%s): ", j,
+                                    reqs.get(j).client, reqs.get(j).service);
+                        }
+                        System.out.printf("%s%s(%d)%s",
+                                found ? " -> " : "",
+                                result[i].acceptor.debug(),
+                                i,
+                                result[i].actual != result[i].expected ?
+                                        "xxx" : "");
+                        found = true;
+                    }
+                }
+                System.out.println();
+                if (!found) {
+                    break;
+                }
             }
             if (!finalOut) throw new Exception();
-        } else if (args[0].equals("N-1")) {
+        } else if (args[0].equals("Nsanity")) {
             // Native mode sanity check
             Proc.d("Detect start");
             Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
             s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
-        } else if (args[0].equals("client")) {
+        } else if (args[0].equals("initiator")) {
             while (true) {
                 String title = Proc.textIn();
                 Proc.d("Client see " + title);
@@ -185,22 +281,26 @@
                 Proc.binOut(token);
             }
         } else {
+            Proc.d(System.getProperty("java.vm.version"));
+            Proc.d(System.getProperty("sun.security.jgss.native"));
+            Proc.d(System.getProperty("sun.security.jgss.lib"));
+            Proc.d("---------------------------------\n");
             Proc.d("Server start");
             Context s = Context.fromUserKtab("*", OneKDC.KTAB, true);
             Proc.d("Server login");
             while (true) {
                 String title = Proc.textIn();
-                Proc.d("Server " + args[0] + " sees " + title);
+                Proc.d("Server sees " + title);
                 if (title.equals("END")) break;
                 s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
                 byte[] token = Proc.binIn();
                 try {
                     s.take(token);
                     Proc.textOut("true");
-                    Proc.d(args[0] + " Good");
+                    Proc.d("Good");
                 } catch (Exception e) {
                     Proc.textOut("false");
-                    Proc.d(args[0] + " Bad");
+                    Proc.d("Bad");
                 }
             }
         }
@@ -215,79 +315,90 @@
         }
     }
 
-    // returns the user name
-    private static String user(int p) {
-        return "USER" + p;
+    // returns the client name
+    private static String client(int p) {
+        return "client" + p;
     }
-    // returns the peer name
-    private static String peer(int p) {
-        return "host" + p + "/" + HOST;
+
+    // returns the service name
+    private static String service(int p) {
+        return "service" + p + "/" + HOST;
     }
-    // returns the dfl name for a host
+
+    // returns the dfl name for a service
     private static String dfl(int p) {
-        return cwd + "host" + p + (uid == -1 ? "" : ("_"+uid));
+        return "service" + p + (uid == -1 ? "" : ("_"+uid));
     }
+
     // generates an ap-req and save into reqs, returns the index
-    private static int req(int user, int peer) throws Exception {
-        pc.println(user(user) + " " + peer(peer));
-        Req req = new Req(user, peer, pc.readData());
+    private static int req(int client, int service) throws Exception {
+        pi.println(client(client) + " " + service(service));
+        Req req = new Req(client, service, pi.readData());
         reqs.add(req);
         return reqs.size() - 1;
     }
-    // carries out a round of experiment
-    // i: ex#, old: which req, server: which server, expected: result?
-    private static Ex round(int i, int old, int server, boolean expected)
-            throws Exception {
-        ps[server].println("TEST");
-        ps[server].println(reqs.get(old).msg);
-        String reply = ps[server].readData();
-        Ex result = new Ex();
-        result.i = i;
-        result.expected = expected;
-        result.server = ps[server].debug();
-        result.actual = Boolean.valueOf(reply);
-        result.user = reqs.get(old).user;
-        result.peer = reqs.get(old).peer;
-        result.old = old;
-        result.csize = csize(result.peer);
-        result.hash = hash(reqs.get(old).msg);
-        if (new File(dfl(result.peer)).exists()) {
-            Files.copy(Paths.get(dfl(result.peer)), Paths.get(
-                String.format("%03d-USER%d-host%d-%s-%s",
-                    i, result.user, result.peer, result.server,
-                    result.actual)
-                + "-" + result.hash),
-                StandardCopyOption.COPY_ATTRIBUTES);
+
+    // create a acceptor
+    private static Proc acceptor(String type, String suffix) throws Exception {
+        Proc p;
+        String label;
+        String lib;
+        int pos = type.indexOf('=');
+        if (pos < 0) {
+            label = type;
+            lib = null;
+        } else {
+            label = type.substring(0, pos);
+            lib = type.substring(pos + 1);
         }
-        return result;
+        if (type.startsWith("J")) {
+            if (lib == null) {
+                p = Proc.create("ReplayCacheTestProc");
+            } else {
+                p = Proc.create("ReplayCacheTestProc", lib);
+            }
+            p.prop("sun.security.krb5.rcache", "dfl")
+                    .prop("java.io.tmpdir", cwd);
+            String useMD5 = System.getProperty("jdk.krb5.rcache.useMD5");
+            if (useMD5 != null) {
+                p.prop("jdk.krb5.rcache.useMD5", useMD5);
+            }
+        } else {
+            p = Proc.create("ReplayCacheTestProc")
+                    .env("KRB5_CONFIG", OneKDC.KRB5_CONF)
+                    .env("KRB5_KTNAME", OneKDC.KTAB)
+                    .env("KRB5RCACHEDIR", cwd)
+                    .prop("sun.security.jgss.native", "true")
+                    .prop("javax.security.auth.useSubjectCredsOnly", "false")
+                    .prop("sun.security.nativegss.debug", "true");
+            if (lib != null) {
+                String libDir = lib.substring(0, lib.lastIndexOf('/'));
+                p.prop("sun.security.jgss.lib", lib)
+                        .env("DYLD_LIBRARY_PATH", libDir)
+                        .env("LD_LIBRARY_PATH", libDir);
+            }
+        }
+        Proc.d(label+suffix+" started");
+        return p.args(label+suffix).debug(label+suffix).start();
     }
-    // create a native server
-    private static Proc ns(int i) throws Exception {
-        return Proc.create("ReplayCacheTestProc")
-                .args("N"+i)
-                .env("KRB5_CONFIG", OneKDC.KRB5_CONF)
-                .env("KRB5_KTNAME", OneKDC.KTAB)
-                .env("KRB5RCACHEDIR", cwd)
-                .prop("sun.security.jgss.native", "true")
-                .prop("javax.security.auth.useSubjectCredsOnly", "false")
-                .prop("sun.security.nativegss.debug", "true")
-                .debug("N"+i)
-                .start();
+
+    // generates hash of authenticator inside ap-req inside initsectoken
+    private static void record(String label, Req req) throws Exception {
+        byte[] data = Base64.getDecoder().decode(req.msg);
+        data = Arrays.copyOfRange(data, 17, data.length);
+
+        try (PrintStream ps = new PrintStream(
+                new FileOutputStream("log.txt", true))) {
+            ps.printf("%s:\nmsg: %s\nMD5: %s\nSHA-256: %s\n\n",
+                    label,
+                    req.msg,
+                    hex(md5.digest(data)),
+                    hex(sha256.digest(data)));
+        }
     }
-    // creates a java server
-    private static Proc js(int i) throws Exception {
-        return Proc.create("ReplayCacheTestProc")
-                .debug("S"+i)
-                .args("S"+i)
-                .prop("sun.security.krb5.rcache", "dfl")
-                .prop("java.io.tmpdir", cwd)
-                .start();
-    }
-    // generates hash of authenticator inside ap-req inside initsectoken
-    private static String hash(String req) throws Exception {
-        byte[] data = Base64.getDecoder().decode(req);
-        data = Arrays.copyOfRange(data, 17, data.length);
-        byte[] hash = MessageDigest.getInstance("MD5").digest(new APReq(data).authenticator.getBytes());
+
+    // Returns a compact hexdump for a byte array
+    private static String hex(byte[] hash) {
         char[] h = new char[hash.length * 2];
         char[] hexConst = "0123456789ABCDEF".toCharArray();
         for (int i=0; i<hash.length; i++) {
@@ -296,10 +407,11 @@
         }
         return new String(h);
     }
+
     // return size of dfl file, excluding the null hash ones
     private static int csize(int p) throws Exception {
         try (SeekableByteChannel chan = Files.newByteChannel(
-                Paths.get(dfl(p)), StandardOpenOption.READ)) {
+                Paths.get(cwd, dfl(p)), StandardOpenOption.READ)) {
             chan.position(6);
             int cc = 0;
             while (true) {
@@ -314,27 +426,73 @@
             return 0;
         }
     }
+
     // models an experiement
     private static class Ex {
         int i;              // #
+        int req;            // which ap-req to send
+        Proc acceptor;      // which acceptor to send to
         boolean expected;   // expected result
+
         boolean actual;     // actual output
-        int old;            // which ap-req to send
-        String server;      // which server to send to
+        int csize;          // size of rcache after test
         String hash;        // the hash of req
-        int user;           // which initiator
-        int peer;           // which acceptor
-        int csize;          // size of rcache after test
+
+        Ex(int i, int req, Proc acceptor, boolean expected) {
+            this.i = i;
+            this.req = req;
+            this.acceptor = acceptor;
+            this.expected = expected;
+        }
+
+        void run() throws Exception {
+            Req r = reqs.get(req);
+            acceptor.println("TEST");
+            acceptor.println(r.msg);
+            String reply = acceptor.readData();
+
+            actual = Boolean.valueOf(reply);
+            csize = csize(r.service);
+
+            String label = String.format("%03d-CLIENT%d-SERVICE%d-%s-%s",
+                    i, r.client, r.service, acceptor.debug(), actual);
+
+            record(label, r);
+            if (new File(cwd, dfl(r.service)).exists()) {
+                Files.copy(Paths.get(cwd, dfl(r.service)), Paths.get(label),
+                        StandardCopyOption.COPY_ATTRIBUTES);
+            }
+        }
     }
+
     // models a saved ap-req msg
     private static class Req {
         String msg;         // based64-ed req
-        int user;           // which initiator
-        int peer;           // which accceptor
-        Req(int user, int peer, String msg) {
+        int client;         // which client
+        int service;        // which service
+        Req(int client, int service, String msg) {
             this.msg = msg;
-            this.user= user;
-            this.peer = peer;
+            this.client= client;
+            this.service = service;
+        }
+    }
+
+    private static class UserRun {
+        static final Pattern p
+                = Pattern.compile("(c(\\d)+s(\\d+)|r(\\d+))(.*)(.)");
+        final Matcher m;
+
+        UserRun(String run) { m = p.matcher(run); m.find(); }
+
+        int req() { return group(4); }
+        int client() { return group(2); }
+        int service() { return group(3); }
+        String acceptor() { return m.group(5); }
+        boolean success() { return m.group(6).equals("v"); }
+
+        int group(int i) {
+            String g = m.group(i);
+            return g == null ? -1 : Integer.parseInt(g);
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/auto/rcache_usemd5.sh	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+#
+
+# @test
+# @bug 8168518
+# @library ../../../../java/security/testlibrary/ /test/lib
+# @run main/othervm/timeout=300 -Djdk.krb5.rcache.useMD5=true ReplayCacheTestProc
+# @summary  testing jdk.krb5.rcache.useMD5. This action is put in a separate
+#           test so that ReplayCacheTestProc.java can be launched with special
+#           test.* system properties easily.
--- a/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/mscapi/IsSunMSCAPIAvailable.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,6 +26,7 @@
  * @bug 6318171 6931562
  * @requires os.family == "windows"
  * @modules jdk.crypto.mscapi/sun.security.mscapi
+ * @compile --add-modules jdk.crypto.mscapi IsSunMSCAPIAvailable.java
  * @run main/othervm IsSunMSCAPIAvailable
  */
 
--- a/jdk/test/sun/security/pkcs11/ec/TestCurves.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/pkcs11/ec/TestCurves.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,7 +28,7 @@
  * @author Andreas Sterbenz
  * @library ..
  * @modules jdk.crypto.pkcs11/sun.security.pkcs11.wrapper
- * @compile -XDignore.symbol.file TestCurves.java
+ * @compile --add-modules jdk.crypto.pkcs11 TestCurves.java
  * @run main/othervm TestCurves
  * @run main/othervm TestCurves sm
  * @key randomness
--- a/jdk/test/sun/security/smartcardio/TestChannel.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/smartcardio/TestChannel.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug 6239117
+ * @bug 6239117 8168851
  * @summary test logical channels work
  * @author Andreas Sterbenz
  * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestChannel
+ * @run main/othervm/manual/java.security.policy==test.policy TestChannel
  */
 
 // This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestControl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/smartcardio/TestControl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug 6239117 6470320
+ * @bug 6239117 6470320 8168851
  * @summary test if transmitControlCommand() works
  * @author Andreas Sterbenz
  * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestControl
+ * @run main/othervm/manual/java.security.policy==test.policy TestControl
  */
 
 // This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestDefault.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/smartcardio/TestDefault.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,11 +23,12 @@
 
 /*
  * @test
- * @bug 6327047
+ * @bug 6327047 8168851
  * @summary verify that TerminalFactory.getDefault() works
  * @author Andreas Sterbenz
  * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestDefault
+ * @run main/othervm/manual/java.security.policy==test.policy TestDefault
  */
 
 // This test requires special hardware.
--- a/jdk/test/sun/security/smartcardio/TestDirect.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/smartcardio/TestDirect.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,10 +23,11 @@
 
 /*
  * @test
- * @bug 8046343
+ * @bug 8046343 8168851
  * @summary Make sure that direct protocol is available
  * @modules java.smartcardio/javax.smartcardio
  * @run main/manual TestDirect
+ * @run main/othervm/manual/java.security.policy==test.policy TestDirect
  */
 
 // This test requires special hardware.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/smartcardio/test.policy	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,3 @@
+grant codebase "file:${test.classes}/*" {
+    permission javax.smartcardio.CardPermission "*", "connect,getBasicChannel,reset,transmitControl";
+};
--- a/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,31 +29,22 @@
 /*
  * @test
  * @bug 4392475
+ * @library /javax/net/ssl/templates
  * @summary Calling setWantClientAuth(true) disables anonymous suites
  * @run main/othervm/timeout=180 AnonCipherWithWantClientAuth
  */
 
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.*;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.security.Security;
 
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
 public class AnonCipherWithWantClientAuth {
 
     /*
-     * =============================================================
-     * Set the various variables needed for the tests, then
-     * specify what tests to run on each side.
-     */
-
-    /*
-     * Should we run the client or server in a separate thread?
-     * Both sides can throw exceptions, but do you have a preference
-     * as to which side should be the main thread.
-     */
-    static boolean separateServerThread = false;
-
-    /*
      * Where do we find the keystores?
      */
     static String pathToStores = "../../../../javax/net/ssl/etc";
@@ -61,106 +52,7 @@
     static String trustStoreFile = "truststore";
     static String passwd = "passphrase";
 
-    /*
-     * Is the server ready to serve?
-     */
-    volatile static boolean serverReady = false;
-
-    /*
-     * Turn on SSL debugging?
-     */
-    static boolean debug = false;
-
-    /*
-     * If the client or server is doing some kind of object creation
-     * that the other side depends on, and that thread prematurely
-     * exits, you may experience a hang.  The test harness will
-     * terminate all hung threads after its timeout has expired,
-     * currently 3 minutes by default, but you might try to be
-     * smart about it....
-     */
-
-    /*
-     * Define the server side of the test.
-     *
-     * If the server prematurely exits, serverReady will be set to true
-     * to avoid infinite hangs.
-     */
-    void doServerSide() throws Exception {
-        SSLServerSocketFactory sslssf =
-            (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
-        SSLServerSocket sslServerSocket =
-            (SSLServerSocket) sslssf.createServerSocket(serverPort);
-        serverPort = sslServerSocket.getLocalPort();
-        String ciphers[]={"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-                          "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
-                          "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"};
-        sslServerSocket.setEnabledCipherSuites(ciphers);
-        sslServerSocket.setWantClientAuth(true);
-        /*
-         * Signal Client, we're ready for his connect.
-         */
-        serverReady = true;
-
-        SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
-        InputStream sslIS = sslSocket.getInputStream();
-        OutputStream sslOS = sslSocket.getOutputStream();
-
-        sslIS.read();
-        sslOS.write(85);
-        sslOS.flush();
-
-        sslSocket.close();
-    }
-
-    /*
-     * Define the client side of the test.
-     *
-     * If the server prematurely exits, serverReady will be set to true
-     * to avoid infinite hangs.
-     */
-    void doClientSide() throws Exception {
-
-        /*
-         * Wait for server to get started.
-         */
-        while (!serverReady) {
-            Thread.sleep(50);
-        }
-
-        SSLSocketFactory sslsf =
-            (SSLSocketFactory) SSLSocketFactory.getDefault();
-        SSLSocket sslSocket = (SSLSocket)
-            sslsf.createSocket("localhost", serverPort);
-        String ciphers[] = {"SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
-                            "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5"};
-        sslSocket.setEnabledCipherSuites(ciphers);
-        sslSocket.setUseClientMode(true);
-
-        InputStream sslIS = sslSocket.getInputStream();
-        OutputStream sslOS = sslSocket.getOutputStream();
-
-        sslOS.write(280);
-        sslOS.flush();
-        sslIS.read();
-
-        sslSocket.close();
-    }
-
-    /*
-     * =============================================================
-     * The remainder is just support stuff
-     */
-
-    // use any free port by default
-    volatile int serverPort = 0;
-
-    volatile Exception serverException = null;
-    volatile Exception clientException = null;
-
     public static void main(String[] args) throws Exception {
-        // reset security properties to make sure that the algorithms
-        // and keys used in this test are not disabled.
         Security.setProperty("jdk.tls.disabledAlgorithms", "");
         Security.setProperty("jdk.certpath.disabledAlgorithms", "");
 
@@ -170,100 +62,84 @@
         String trustFilename =
             System.getProperty("test.src", "./") + "/" + pathToStores +
                 "/" + trustStoreFile;
-
-        System.setProperty("javax.net.ssl.keyStore", keyFilename);
-        System.setProperty("javax.net.ssl.keyStorePassword", passwd);
-        System.setProperty("javax.net.ssl.trustStore", trustFilename);
-        System.setProperty("javax.net.ssl.trustStorePassword", passwd);
-
-        if (debug)
-            System.setProperty("javax.net.debug", "all");
+        SSLTest.setup(keyFilename, trustFilename, passwd);
 
-        /*
-         * Start the tests.
-         */
-        new AnonCipherWithWantClientAuth();
-    }
-
-    Thread clientThread = null;
-    Thread serverThread = null;
+        new SSLTest()
+            .setServerPeer(test -> {
+                SSLServerSocketFactory sslssf =
+                        (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+                SSLServerSocket sslServerSocket =
+                        (SSLServerSocket) sslssf.createServerSocket(SSLTest.FREE_PORT);
+                test.setServerPort(sslServerSocket.getLocalPort());
+                SSLTest.print("Server is listening on port "
+                        + test.getServerPort());
 
-    /*
-     * Primary constructor, used to drive remainder of the test.
-     *
-     * Fork off the other side, then do your work.
-     */
-    AnonCipherWithWantClientAuth () throws Exception {
-        if (separateServerThread) {
-            startServer(true);
-            startClient(false);
-        } else {
-            startClient(true);
-            startServer(false);
-        }
+                String ciphers[] = {
+                        "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+                        "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
+                        "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" };
+                sslServerSocket.setEnabledCipherSuites(ciphers);
+                sslServerSocket.setWantClientAuth(true);
+
+                // Signal the client, the server is ready to accept connection.
+                test.signalServerReady();
 
-        /*
-         * Wait for other side to close down.
-         */
-        if (separateServerThread) {
-            serverThread.join();
-        } else {
-            clientThread.join();
-        }
+                // Try to accept a connection in 30 seconds.
+                SSLSocket sslSocket = SSLTest.accept(sslServerSocket);
+                if (sslSocket == null) {
+                    // Ignore the test case if no connection within 30 seconds.
+                    SSLTest.print("No incoming client connection in 30 seconds."
+                            + " Ignore in server side.");
+                    return;
+                }
+                SSLTest.print("Server accepted connection");
 
-        /*
-         * When we get here, the test is pretty much over.
-         *
-         * If the main thread excepted, that propagates back
-         * immediately.  If the other thread threw an exception, we
-         * should report back.
-         */
-        if (serverException != null)
-            throw serverException;
-        if (clientException != null)
-            throw clientException;
-    }
+                // handle the connection
+                try {
+                    // Is it the expected client connection?
+                    //
+                    // Naughty test cases or third party routines may try to
+                    // connection to this server port unintentionally.  In
+                    // order to mitigate the impact of unexpected client
+                    // connections and avoid intermittent failure, it should
+                    // be checked that the accepted connection is really linked
+                    // to the expected client.
+                    boolean clientIsReady = test.waitForClientSignal();
 
-    void startServer(boolean newThread) throws Exception {
-        if (newThread) {
-            serverThread = new Thread() {
-                public void run() {
-                    try {
-                        doServerSide();
-                    } catch (Exception e) {
-                        /*
-                         * Our server thread just died.
-                         */
-                        System.err.println("Server died...");
-                        serverReady = true;
-                        serverException = e;
+                    if (clientIsReady) {
+                        // Run the application in server side.
+                        SSLTest.print("Run server application");
+
+                        InputStream sslIS = sslSocket.getInputStream();
+                        OutputStream sslOS = sslSocket.getOutputStream();
+
+                        sslIS.read();
+                        sslOS.write(85);
+                        sslOS.flush();
+                    } else {
+                        System.out.println(
+                                "The client is not the expected one or timeout. "
+                                        + "Ignore in server side.");
                     }
+                } finally {
+                    sslSocket.close();
+                    sslServerSocket.close();
                 }
-            };
-            serverThread.start();
-        } else {
-            doServerSide();
-        }
-    }
+            })
+            .setClientApplication((socket, test) -> {
+                String ciphers[] = {
+                        "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
+                        "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5" };
+                socket.setEnabledCipherSuites(ciphers);
+                socket.setUseClientMode(true);
 
-    void startClient(boolean newThread) throws Exception {
-        if (newThread) {
-            clientThread = new Thread() {
-                public void run() {
-                    try {
-                        doClientSide();
-                    } catch (Exception e) {
-                        /*
-                         * Our client thread just died.
-                         */
-                        System.err.println("Client died...");
-                        clientException = e;
-                    }
-                }
-            };
-            clientThread.start();
-        } else {
-            doClientSide();
-        }
+                InputStream sslIS = socket.getInputStream();
+                OutputStream sslOS = socket.getOutputStream();
+
+                sslOS.write(280);
+                sslOS.flush();
+                sslIS.read();
+            })
+            .runTest();
     }
 }
--- a/jdk/test/sun/util/calendar/zi/tzdata/VERSION	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/util/calendar/zi/tzdata/VERSION	Fri Nov 11 16:44:36 2016 +0100
@@ -21,4 +21,4 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-tzdata2016g
+tzdata2016h
--- a/jdk/test/sun/util/calendar/zi/tzdata/asia	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/util/calendar/zi/tzdata/asia	Fri Nov 11 16:44:36 2016 +0100
@@ -2567,11 +2567,6 @@
 # From Paul Eggert (2015-03-03):
 # http://www.timeanddate.com/time/change/west-bank/ramallah?year=2014
 # says that the fall 2014 transition was Oct 23 at 24:00.
-# For future dates, guess the last Friday in March at 24:00 through
-# the first Friday on or after October 21 at 00:00.  This is consistent with
-# the predictions in today's editions of the following URLs:
-# http://www.timeanddate.com/time/change/gaza-strip/gaza
-# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # From Hannah Kreitem (2016-03-09):
 # http://www.palestinecabinet.gov.ps/WebSite/ar/ViewDetails?ID=31728
@@ -2581,7 +2576,21 @@
 #
 # From Paul Eggert (2016-03-12):
 # Predict spring transitions on March's last Saturday at 01:00 from now on.
-# Leave fall predictions alone for now.
+
+# From Sharef Mustafa (2016-10-19):
+# [T]he Palestinian cabinet decision (Mar 8th 2016) published on
+# http://www.palestinecabinet.gov.ps/WebSite/Upload/Decree/GOV_17/16032016134830.pdf
+# states that summer time will end on Oct 29th at 01:00.
+#
+# From Tim Parenti (2016-10-19):
+# Predict fall transitions on October's last Saturday at 01:00 from now on.
+# This is consistent with the 2016 transition as well as our spring
+# predictions.
+#
+# From Paul Eggert (2016-10-19):
+# It's also consistent with predictions in the following URLs today:
+# http://www.timeanddate.com/time/change/gaza-strip/gaza
+# http://www.timeanddate.com/time/change/west-bank/hebron
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule EgyptAsia	1957	only	-	May	10	0:00	1:00	S
@@ -2610,9 +2619,10 @@
 Rule Palestine	2012	2014	-	Mar	lastThu	24:00	1:00	S
 Rule Palestine	2012	only	-	Sep	21	1:00	0	-
 Rule Palestine	2013	only	-	Sep	Fri>=21	0:00	0	-
-Rule Palestine	2014	max	-	Oct	Fri>=21	0:00	0	-
+Rule Palestine	2014	2015	-	Oct	Fri>=21	0:00	0	-
 Rule Palestine	2015	only	-	Mar	lastFri	24:00	1:00	S
 Rule Palestine	2016	max	-	Mar	lastSat	1:00	1:00	S
+Rule Palestine	2016	max	-	Oct	lastSat	1:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
@@ -2762,45 +2772,31 @@
 # People who live in regions under Tamil control can use [TZ='Asia/Kolkata'],
 # as that zone has agreed with the Tamil areas since our cutoff date of 1970.
 
-# From K Sethu (2006-04-25):
-# I think the abbreviation LKT originated from the world of computers at
-# the time of or subsequent to the time zone changes by SL Government
-# twice in 1996 and probably SL Government or its standardization
-# agencies never declared an abbreviation as a national standard.
-#
-# I recollect before the recent change the government announcements
-# mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
-# Time and no mention was made about the abbreviation.
+# From Sadika Sumanapala (2016-10-19):
+# According to http://www.sltime.org (maintained by Measurement Units,
+# Standards & Services Department, Sri Lanka) abbreviation for Sri Lanka
+# standard time is SLST.
 #
-# If we look at Sri Lanka Department of Government's "Official News
-# Website of Sri Lanka" ... http://www.news.lk/ we can see that they
-# use SLT as abbreviation in time stamp at the beginning of each news
-# item....
-#
-# Within Sri Lanka I think LKT is well known among computer users and
-# administrators.  In my opinion SLT may not be a good choice because the
-# nation's largest telcom / internet operator Sri Lanka Telcom is well
-# known by that abbreviation - simply as SLT (there IP domains are
-# slt.lk and sltnet.lk).
-#
-# But if indeed our government has adopted SLT as standard abbreviation
-# (that we have not known so far) then  it is better that it be used for
-# all computers.
-
-# From Paul Eggert (2006-04-25):
-# One possibility is that we wait for a bit for the dust to settle down
-# and then see what people actually say in practice.
+# From Paul Eggert (2016-10-18):
+# "SLST" seems to be reasonably recent and rarely-used outside time
+# zone nerd sources.  I searched Google News and found three uses of
+# it in the International Business Times of India in February and
+# March of this year when discussing cricket match times, but nothing
+# since then (though there has been a lot of cricket) and nothing in
+# other English-language news sources.  Our old abbreviation "LKT" is
+# even worse.  For now, let's use a numeric abbreviation; we can
+# switch to "SLST" if it catches on.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
 			5:19:32	-	MMT	1906        # Moratuwa Mean Time
-			5:30	-	IST	1942 Jan  5
-			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16  2:00
-			5:30	-	IST	1996 May 25  0:00
-			6:30	-	LKT	1996 Oct 26  0:30
-			6:00	-	LKT	2006 Apr 15  0:30
-			5:30	-	IST
+			5:30	-	+0530	1942 Jan  5
+			5:30	0:30	+0530/+06 1942 Sep
+			5:30	1:00	+0530/+0630 1945 Oct 16  2:00
+			5:30	-	+0530	1996 May 25  0:00
+			6:30	-	+0630	1996 Oct 26  0:30
+			6:00	-	+06	2006 Apr 15  0:30
+			5:30	-	+0530
 
 # Syria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
--- a/jdk/test/sun/util/calendar/zi/tzdata/australasia	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/util/calendar/zi/tzdata/australasia	Fri Nov 11 16:44:36 2016 +0100
@@ -373,7 +373,13 @@
 # commencing at 2.00 am on Sunday 1st November, 2015 and ending at
 # 3.00 am on Sunday 17th January, 2016.
 
-# From Paul Eggert (2015-09-01):
+# From Raymond Kumar (2016-10-04):
+# http://www.fiji.gov.fj/Media-Center/Press-Releases/DAYLIGHT-SAVING-STARTS-ON-6th-NOVEMBER,-2016.aspx
+# "Fiji's daylight savings will begin on Sunday, 6 November 2016, when
+# clocks go forward an hour at 2am to 3am....  Daylight Saving will
+# end at 3.00am on Sunday 15th January 2017."
+
+# From Paul Eggert (2016-10-03):
 # For now, guess DST from 02:00 the first Sunday in November to
 # 03:00 the third Sunday in January.  Although ad hoc, it matches
 # transitions since late 2014 and seems more likely to match future
--- a/jdk/test/sun/util/calendar/zi/tzdata/europe	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/util/calendar/zi/tzdata/europe	Fri Nov 11 16:44:36 2016 +0100
@@ -1931,7 +1931,7 @@
 # Amsterdam mean time.
 
 # The data entries before 1945 are taken from
-# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
+# http://www.staff.science.uu.nl/~gent0113/idl/idl.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -3450,22 +3450,24 @@
 
 # Turkey
 
-# From Amar Devegowda (2007-01-03):
-# The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at:
-# http://www.timeanddate.com/worldclock/timezone.html?n=107
-# From Steffen Thorsen (2007-01-03):
-# I have been able to find press records back to 1996 which all say that
-# DST started 01:00 local time and end at 02:00 local time.  I am not sure
-# what happened before that.  One example for each year from 1996 to 2001:
-# http://newspot.byegm.gov.tr/arsiv/1996/21/N4.htm
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING97/03/97X03X25.TXT
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING98/03/98X03X02.HTM
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING99/10/99X10X26.HTM#%2016
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2000/03/00X03X06.HTM#%2021
-# http://www.byegm.gov.tr/YAYINLARIMIZ/CHR/ING2001/03/23x03x01.HTM#%2027
-# From Paul Eggert (2007-01-03):
-# Prefer the above source to Shanks & Pottenger for time stamps after 1990.
+# From Kıvanç Yazan (2016-09-25):
+# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
+#    no exceptions.
+# 2) 1994's lastSun was overridden with Mar 20 ...
+# Here are official papers:
+# http://www.resmigazete.gov.tr/arsiv/19032.pdf  - page 2 for 1986
+# http://www.resmigazete.gov.tr/arsiv/19400.pdf  - page 4 for 1987
+# http://www.resmigazete.gov.tr/arsiv/19752.pdf  - page 15 for 1988
+# http://www.resmigazete.gov.tr/arsiv/20102.pdf  - page 6 for 1989
+# http://www.resmigazete.gov.tr/arsiv/20464.pdf  - page 1 for 1990 - 1992
+# http://www.resmigazete.gov.tr/arsiv/21531.pdf  - page 15 for 1993 - 1995
+# http://www.resmigazete.gov.tr/arsiv/21879.pdf  - page 1 for overriding 1994
+# http://www.resmigazete.gov.tr/arsiv/22588.pdf  - page 1 for 1996, 1997
+# http://www.resmigazete.gov.tr/arsiv/23286.pdf  - page 10 for 1998 - 2000
+# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2  - for 2001
+# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2  - for 2002-2006
+# From Paul Eggert (2016-09-25):
+# Prefer the above sources to Shanks & Pottenger for time stamps after 1985.
 
 # From Steffen Thorsen (2007-03-09):
 # Starting 2007 though, it seems that they are adopting EU's 1:00 UTC
@@ -3574,10 +3576,10 @@
 Rule	Turkey	1983	only	-	Oct	 2	0:00	0	-
 Rule	Turkey	1985	only	-	Apr	20	0:00	1:00	S
 Rule	Turkey	1985	only	-	Sep	28	0:00	0	-
-Rule	Turkey	1986	1990	-	Mar	lastSun	2:00s	1:00	S
-Rule	Turkey	1986	1990	-	Sep	lastSun	2:00s	0	-
-Rule	Turkey	1991	2006	-	Mar	lastSun	1:00s	1:00	S
-Rule	Turkey	1991	1995	-	Sep	lastSun	1:00s	0	-
+Rule	Turkey	1986	1993	-	Mar	lastSun	1:00s	1:00	S
+Rule	Turkey	1986	1995	-	Sep	lastSun	1:00s	0	-
+Rule	Turkey	1994	only	-	Mar	20	1:00s	1:00	S
+Rule	Turkey	1995	2006	-	Mar	lastSun	1:00s	1:00	S
 Rule	Turkey	1996	2006	-	Oct	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Istanbul	1:55:52 -	LMT	1880
--- a/jdk/test/sun/util/calendar/zi/tzdata/northamerica	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/sun/util/calendar/zi/tzdata/northamerica	Fri Nov 11 16:44:36 2016 +0100
@@ -47,8 +47,32 @@
 # was the result of his proposals at the Convention of Railroad Trunk Lines
 # in New York City (1869-10).  His 1870 proposal was based on Washington, DC,
 # but in 1872-05 he moved the proposed origin to Greenwich.
-# His proposal was adopted by the railroads on 1883-11-18 at 12:00,
-# and the most of the country soon followed suit.
+
+# From Paul Eggert (2016-09-21):
+# Dowd's proposal left many details unresolved, such as where to draw
+# lines between time zones.  The key individual who made time zones
+# work in the US was William Frederick Allen - railway engineer,
+# managing editor of the Travelers' Guide, and secretary of the
+# General Time Convention, a railway standardization group.  Allen
+# spent months in dialogs with scientific and railway leaders,
+# developed a workable plan to institute time zones, and presented it
+# to the General Time Convention on 1883-04-11, saying that his plan
+# meant "local time would be practically abolished" - a plus for
+# railway scheduling.  By the next convention on 1883-10-11 nearly all
+# railroads had agreed and it took effect on 1883-11-18 at 12:00.
+# That Sunday was called the "day of two noons", as the eastern parts
+# of the new zones observed noon twice.  Allen witnessed the
+# transition in New York City, writing:
+#
+#   I heard the bells of St. Paul's strike on the old time.  Four
+#   minutes later, obedient to the electrical signal from the Naval
+#   Observatory ... the time-ball made its rapid descent, the chimes
+#   of old Trinity rang twelve measured strokes, and local time was
+#   abandoned, probably forever.
+#
+# Most of the US soon followed suit.  See:
+# Bartky IR. The adoption of standard time. Technol Cult 1989 Jan;30(1):25-56.
+# http://dx.doi.org/10.2307/3105430
 
 # From Paul Eggert (2005-04-16):
 # That 1883 transition occurred at 12:00 new time, not at 12:00 old time.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/ConcealedPackage.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8146486
+ * @summary Fail to create a MR modular JAR with a versioned entry in
+ *          base-versioned empty package
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.FileUtils
+ * @run testng ConcealedPackage
+ */
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.testlibrary.FileUtils;
+
+public class ConcealedPackage {
+    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+           .orElseThrow(() -> new RuntimeException("jar tool not found"));
+    private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+            .orElseThrow(() -> new RuntimeException("javac tool not found"));
+    private final String linesep = System.lineSeparator();
+    private final Path userdir;
+    private final ByteArrayOutputStream outbytes = new ByteArrayOutputStream();
+    private final PrintStream out = new PrintStream(outbytes, true);
+    private final ByteArrayOutputStream errbytes = new ByteArrayOutputStream();
+    private final PrintStream err = new PrintStream(errbytes, true);
+
+    public ConcealedPackage() throws IOException {
+        Path testsrc = Paths.get(System.getProperty("test.src"));
+        userdir = Paths.get(System.getProperty("user.dir", "."));
+
+        // compile the classes directory
+        Path source = testsrc.resolve("src").resolve("classes");
+        Path destination = Paths.get("classes");
+        javac(source, destination);
+
+        // compile the mr9 directory including module-info.java
+        source = testsrc.resolve("src").resolve("mr9");
+        destination = Paths.get("mr9");
+        javac(source, destination);
+
+        // move module-info.class for later use
+        Files.move(destination.resolve("module-info.class"),
+                Paths.get("module-info.class"));
+    }
+
+    private void javac(Path source, Path destination) throws IOException {
+        String[] args = Stream.concat(
+                Stream.of("-d", destination.toString()),
+                Files.walk(source)
+                        .map(Path::toString)
+                        .filter(s -> s.endsWith(".java"))
+        ).toArray(String[]::new);
+        JAVAC_TOOL.run(System.out, System.err, args);
+    }
+
+    private int jar(String cmd) {
+        outbytes.reset();
+        errbytes.reset();
+        return JAR_TOOL.run(out, err, cmd.split(" +"));
+    }
+
+    @AfterClass
+    public void cleanup() throws IOException {
+        Files.walk(userdir, 1)
+                .filter(p -> !p.equals(userdir))
+                .forEach(p -> {
+                    try {
+                        if (Files.isDirectory(p)) {
+                            FileUtils.deleteFileTreeWithRetry(p);
+                        } else {
+                            FileUtils.deleteFileIfExistsWithRetry(p);
+                        }
+                    } catch (IOException x) {
+                        throw new UncheckedIOException(x);
+                    }
+                });
+    }
+
+    // updates a valid multi-release jar with a new public class in
+    // versioned section and fails
+    @Test
+    public void test1() {
+        // successful build of multi-release jar
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+        Assert.assertEquals(rc, 0);
+
+        jar("-tf mmr.jar");
+
+        String s = new String(outbytes.toByteArray());
+        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/p/Hi.class"
+        );
+        Assert.assertEquals(actual, expected);
+
+        // failed build because of new public class
+        rc = jar("-uf mmr.jar --release 9 -C mr9 p/internal/Bar.class");
+        Assert.assertEquals(rc, 1);
+
+        s = new String(errbytes.toByteArray());
+        Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+                + "class not found in base entries")
+        );
+    }
+
+    // updates a valid multi-release jar with a module-info class and new
+    // concealed public class in versioned section and succeeds
+    @Test
+    public void test2() {
+        // successful build of multi-release jar
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 p/Hi.class");
+        Assert.assertEquals(rc, 0);
+
+        // successful build because of module-info and new public class
+        rc = jar("-uf mmr.jar module-info.class --release 9 -C mr9 p/internal/Bar.class");
+        Assert.assertEquals(rc, 0);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+                        + "concealed package, \nplacing this jar on the class path "
+                        + "will result in incompatible public interfaces")
+        );
+
+        jar("-tf mmr.jar");
+
+        s = new String(outbytes.toByteArray());
+        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/Bar.class",
+                "module-info.class"
+        );
+        Assert.assertEquals(actual, expected);
+    }
+
+    // jar tool fails building mmr.jar because of new public class
+    @Test
+    public void test3() {
+        int rc = jar("-cf mmr.jar -C classes . --release 9 -C mr9 .");
+        Assert.assertEquals(rc, 1);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(s.contains("p/internal/Bar.class, contains a new public "
+                + "class not found in base entries")
+        );
+    }
+
+    // jar tool succeeds building mmr.jar because of concealed package
+    @Test
+    public void test4() {
+        int rc = jar("-cf mmr.jar module-info.class -C classes . " +
+                "--release 9 module-info.class -C mr9 .");
+        Assert.assertEquals(rc, 0);
+
+        String s = new String(errbytes.toByteArray());
+        Assert.assertTrue(s.contains("p/internal/Bar.class is a public class in a "
+                + "concealed package, \nplacing this jar on the class path "
+                + "will result in incompatible public interfaces")
+        );
+
+        jar("-tf mmr.jar");
+
+        s = new String(outbytes.toByteArray());
+        Set<String> actual = Arrays.stream(s.split(linesep)).collect(Collectors.toSet());
+        Set<String> expected = Set.of(
+                "META-INF/",
+                "META-INF/MANIFEST.MF",
+                "module-info.class",
+                "META-INF/versions/9/module-info.class",
+                "p/",
+                "p/Hi.class",
+                "META-INF/versions/9/p/",
+                "META-INF/versions/9/p/Hi.class",
+                "META-INF/versions/9/p/internal/",
+                "META-INF/versions/9/p/internal/Bar.class"
+        );
+        Assert.assertEquals(actual, expected);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/classes/p/Hi.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p;
+
+public class Hi {
+    public void sayHi() {
+        System.out.println("Hi");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 {
+    exports p;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/Hi.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p;
+
+public class Hi {
+    public void sayHi() {
+        System.out.println("Hello");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jar/mmrjar/src/mr9/p/internal/Bar.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p.internal;
+
+public class Bar {
+    @Override
+    public String toString() {
+        return "p.internal.Bar";
+    }
+}
--- a/jdk/test/tools/jlink/JLinkPluginsTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/jlink/JLinkPluginsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -83,5 +83,21 @@
             Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
             helper.checkImage(imageDir, moduleName, null, null);
         }
+        {
+            // disable generate jli classes - JDK-8160063
+            String[] userOptions = {"--disable-plugin", "generate-jli-classes"};
+            String moduleName = "jlidisabled";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
+            helper.checkImage(imageDir, moduleName, null, null);
+        }
+        {
+            // disable invalid plugin - JDK-8160063
+            String[] userOptions = {"--disable-plugin", "non-existent-plugin"};
+            String moduleName = "invaliddisabled";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            helper.generateDefaultImage(userOptions, moduleName).
+                assertFailure("Error: No such plugin: non-existent-plugin");
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/JLinkSigningTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8159393
+ * @summary Test signed jars involved in image creation
+ * @modules java.base/jdk.internal.jimage
+ *          jdk.jlink/jdk.tools.jlink.internal
+ *          jdk.compiler/com.sun.tools.javac
+ *          java.base/sun.security.tools.keytool
+ *          jdk.jartool/sun.security.tools.jarsigner
+ *          jdk.jartool/sun.tools.jar
+ * @run main/othervm JLinkSigningTest
+ */
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+public class JLinkSigningTest {
+    static final String[] MODULE_INFO = {
+        "module test {",
+        "}",
+    };
+
+    static final String[] TEST_CLASS = {
+        "package test;",
+        "public class test {",
+        "    public static void main(String[] args) {",
+        "    }",
+        "}",
+    };
+
+    static void report(String command, String[] args) {
+        System.out.println(command + " " + String.join(" ", Arrays.asList(args)));
+    }
+
+    static void javac(String[] args) {
+        report("javac", args);
+        com.sun.tools.javac.Main javac = new com.sun.tools.javac.Main();
+
+        if (javac.compile(args) != 0) {
+            throw new RuntimeException("javac failed");
+        }
+    }
+
+    static void jar(String[] args) {
+        report("jar", args);
+        sun.tools.jar.Main jar = new sun.tools.jar.Main(System.out, System.err, "jar");
+
+        if (!jar.run(args)) {
+            throw new RuntimeException("jar failed");
+        }
+    }
+
+    static void keytool(String[] args) {
+        report("keytool", args);
+
+        try {
+            sun.security.tools.keytool.Main.main(args);
+        } catch (Exception ex) {
+            throw new RuntimeException("keytool failed");
+        }
+    }
+
+    static void jarsigner(String[] args) {
+        report("jarsigner", args);
+
+        try {
+            sun.security.tools.jarsigner.Main.main(args);
+        } catch (Exception ex) {
+            throw new RuntimeException("jarsigner failed");
+        }
+    }
+
+    static void jlink(String[] args) {
+        report("jlink", args);
+
+        try {
+            jdk.tools.jlink.internal.Main.run(new PrintWriter(System.out, true),
+                                              new PrintWriter(System.err, true),
+                                              args);
+        } catch (Exception ex) {
+            throw new RuntimeException("jlink failed");
+        }
+    }
+
+    public static void main(String[] args) {
+        final String JAVA_HOME = System.getProperty("java.home");
+        Path moduleInfoJavaPath = Paths.get("module-info.java");
+        Path moduleInfoClassPath = Paths.get("module-info.class");
+        Path testDirectoryPath = Paths.get("test");
+        Path testJavaPath = testDirectoryPath.resolve("test.java");
+        Path testClassPath = testDirectoryPath.resolve("test.class");
+        Path testModsDirectoryPath = Paths.get("testmods");
+        Path jmodsPath = Paths.get(JAVA_HOME, "jmods");
+        Path testjarPath = testModsDirectoryPath.resolve("test.jar");
+        String modulesPath = testjarPath.toString() +
+                             File.pathSeparator +
+                             jmodsPath.toString();
+
+        try {
+            Files.write(moduleInfoJavaPath, Arrays.asList(MODULE_INFO));
+            Files.createDirectories(testDirectoryPath);
+            Files.write(testJavaPath, Arrays.asList(TEST_CLASS));
+            Files.createDirectories(testModsDirectoryPath);
+        } catch (IOException ex) {
+            throw new RuntimeException("file construction failed");
+        }
+
+        javac(new String[] {
+            testJavaPath.toString(),
+            moduleInfoJavaPath.toString(),
+        });
+
+        jar(new String[] {
+            "-c",
+            "-f", testjarPath.toString(),
+            "--module-path", jmodsPath.toString(),
+            testClassPath.toString(),
+            moduleInfoClassPath.toString(),
+        });
+
+        keytool(new String[] {
+            "-genkey",
+            "-keyalg", "RSA",
+            "-dname", "CN=John Doe, OU=JPG, O=Oracle, L=Santa Clara, ST=California, C=US",
+            "-alias", "examplekey",
+            "-storepass", "password",
+            "-keypass", "password",
+            "-keystore", "examplekeystore",
+            "-validity", "365",
+        });
+
+        jarsigner(new String[] {
+            "-keystore", "examplekeystore",
+            "-verbose", testjarPath.toString(),
+            "-storepass", "password",
+            "-keypass", "password",
+            "examplekey",
+        });
+
+        try {
+            jlink(new String[] {
+                "--module-path", modulesPath,
+                "--add-modules", "test",
+                "--output", "foo",
+            });
+        } catch (Throwable ex) {
+            System.out.println("Failed as should");
+        }
+
+        try {
+            jlink(new String[] {
+                "--module-path", modulesPath,
+                "--add-modules", "test",
+                "--ignore-signing-information",
+                "--output", "foo",
+            });
+            System.out.println("Suceeded as should");
+        } catch (Throwable ex) {
+            System.err.println("Should not have failed");
+            throw new RuntimeException(ex);
+        }
+
+        System.out.println("Done");
+    }
+}
+
--- a/jdk/test/tools/jlink/JLinkTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/jlink/JLinkTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -109,19 +109,16 @@
                     .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 --module-path");
         }
 
@@ -132,7 +129,6 @@
                     .modulePath(helper.defaultModulePath())
                     .output(helper.createNewImageDir(moduleName))
                     .addMods("m")
-                    .option("")
                     .call().assertSuccess();
             moduleName = "mod";
             jmod = helper.generateDefaultJModule(moduleName).assertSuccess();
@@ -140,7 +136,6 @@
                     .modulePath(helper.defaultModulePath())
                     .output(helper.createNewImageDir(moduleName))
                     .addMods("m")
-                    .option("")
                     .call().assertSuccess();
         }
 
@@ -282,18 +277,21 @@
             helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: Invalid compression level invalid");
         }
 
-        // @file
+        // orphan argument - JDK-8166810
         {
-            Path path = Paths.get("embedded.properties");
-            Files.write(path, Collections.singletonList("--strip-debug --add-modules " +
-                    "toto.unknown --compress UNKNOWN\n"));
-            String[] userOptions = {"@", path.toAbsolutePath().toString()};
-            String moduleName = "configembeddednocompresscomposite2";
+            String[] userOptions = {"--compress", "2", "foo" };
+            String moduleName = "orphanarg1";
             helper.generateDefaultJModule(moduleName, "composite2");
-            Path imageDir = helper.generateDefaultImage(userOptions, moduleName).assertSuccess();
-            helper.checkImage(imageDir, moduleName, null, null);
+            helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: foo");
         }
 
+        // orphan argument - JDK-8166810
+        {
+            String[] userOptions = {"--output", "foo", "bar" };
+            String moduleName = "orphanarg2";
+            helper.generateDefaultJModule(moduleName, "composite2");
+            helper.generateDefaultImage(userOptions, moduleName).assertFailure("Error: orphan argument: bar");
+        }
     }
 
     private static void testCompress(Helper helper, String moduleName, String... userOptions) throws IOException {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/JLinkMultiReleaseJarTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8156499
+ * @summary Test image creation from Multi-Release JAR
+ * @author Steve Drach
+ * @library /lib/testlibrary /test/lib
+ * @modules java.base/jdk.internal.jimage
+ *          java.base/jdk.internal.module
+ * @build jdk.testlibrary.FileUtils jdk.test.lib.process.*
+ * @run testng JLinkMultiReleaseJarTest
+*/
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.module.ModuleDescriptor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.jar.JarFile;
+import java.util.spi.ToolProvider;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import jdk.internal.jimage.BasicImageReader;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.FileUtils;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class JLinkMultiReleaseJarTest {
+    private static final ToolProvider JAR_TOOL = ToolProvider.findFirst("jar")
+            .orElseThrow(() -> new RuntimeException("jar tool not found"));
+    private static final ToolProvider JAVAC_TOOL = ToolProvider.findFirst("javac")
+            .orElseThrow(() -> new RuntimeException("javac tool not found"));
+    private static final ToolProvider JLINK_TOOL = ToolProvider.findFirst("jlink")
+            .orElseThrow(() -> new RuntimeException("jlink tool not found"));
+
+    private final Path userdir = Paths.get(System.getProperty("user.dir", "."));
+    private final Path javahome = Paths.get(System.getProperty("java.home"));
+    private final Path jmodsdir = javahome.resolve("jmods");
+
+    private final String pathsep = System.getProperty("path.separator");
+
+    private byte[] resource = (Runtime.version().major() + " resource file").getBytes();
+
+    @BeforeClass
+    public void initialize() throws IOException {
+        Path srcdir = Paths.get(System.getProperty("test.src"));
+
+        // create class files from source
+        Path base = srcdir.resolve("base");
+        Path basemods = userdir.resolve("basemods");
+        javac(base, basemods, base.toString());
+
+        Path rt = srcdir.resolve("rt");
+        Path rtmods = userdir.resolve("rtmods");
+        javac(rt, rtmods, rt.toString());
+
+        // create resources in basemods and rtmods
+        Path dest = basemods.resolve("m1").resolve("resource.txt");
+        byte[] text = "base resource file".getBytes();
+        ByteArrayInputStream is = new ByteArrayInputStream(text);
+        Files.copy(is, dest);
+
+        dest = rtmods.resolve("m1").resolve("resource.txt");
+        is = new ByteArrayInputStream(resource);
+        Files.copy(is, dest);
+
+        // build multi-release jar file with different module-infos
+        String[] args = {
+                "-cf", "m1.jar",
+                "-C", basemods.resolve("m1").toString(), ".",
+                "--release ", String.valueOf(JarFile.runtimeVersion().major()),
+                "-C", rtmods.resolve("m1").toString(), "."
+        };
+        JAR_TOOL.run(System.out, System.err, args);
+
+        // now move the module-info that requires logging to temporary place
+        Files.move(rtmods.resolve("m1").resolve("module-info.class"),
+                userdir.resolve("module-info.class"));
+
+        // and build another jar
+        args[1] = "m1-no-logging.jar";
+        JAR_TOOL.run(System.out, System.err, args);
+
+        // replace the no logging module-info with the logging module-info
+        Files.move(userdir.resolve("module-info.class"),
+                basemods.resolve("m1").resolve("module-info.class"),
+                StandardCopyOption.REPLACE_EXISTING);
+
+        // and build another jar
+        args[1] = "m1-logging.jar";
+        JAR_TOOL.run(System.out, System.err, args);
+    }
+
+    private void javac(Path source, Path destination, String srcpath) throws IOException {
+        String[] args = Stream.concat(
+                Stream.of("-d", destination.toString(), "--module-source-path", srcpath),
+                Files.walk(source)
+                        .map(Path::toString)
+                        .filter(s -> s.endsWith(".java"))
+        ).toArray(String[]::new);
+        int rc = JAVAC_TOOL.run(System.out, System.err, args);
+        Assert.assertEquals(rc, 0);
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.walk(userdir, 1)
+                .filter(p -> !p.equals(userdir))
+                .forEach(p -> {
+                    try {
+                        if (Files.isDirectory(p)) {
+                            FileUtils.deleteFileTreeWithRetry(p);
+                        } else {
+                            FileUtils.deleteFileIfExistsWithRetry(p);
+                        }
+                    } catch (IOException x) {
+                        throw new UncheckedIOException(x);
+                    }
+                });
+    }
+
+    @Test
+    public void basicTest() throws Throwable {
+        if (ignoreTest()) return;
+
+        // use jlink to build image from multi-release jar
+       jlink("m1.jar", "myimage");
+
+        // validate image
+        Path jimage = userdir.resolve("myimage").resolve("lib").resolve("modules");
+        try (BasicImageReader reader = BasicImageReader.open(jimage)) {
+
+            // do we have the right entry names?
+            Set<String> names = Arrays.stream(reader.getEntryNames())
+                    .filter(n -> n.startsWith("/m1"))
+                    .collect(Collectors.toSet());
+            Assert.assertEquals(names, Set.of(
+                    "/m1/module-info.class",
+                    "/m1/p/Main.class",
+                    "/m1/p/Type.class",
+                    "/m1/q/PublicClass.class",
+                    "/m1/META-INF/MANIFEST.MF",
+                    "/m1/resource.txt"));
+
+            // do we have the right module-info.class?
+            byte[] b = reader.getResource("/m1/module-info.class");
+            Set<String> requires = ModuleDescriptor
+                    .read(new ByteArrayInputStream(b))
+                    .requires()
+                    .stream()
+                    .map(mdr -> mdr.name())
+                    .filter(nm -> !nm.equals("java.base"))
+                    .collect(Collectors.toSet());
+            Assert.assertEquals(requires, Set.of("java.logging"));
+
+            // do we have the right resource?
+            b = reader.getResource("/m1/resource.txt");
+            Assert.assertEquals(b, resource);
+
+            // do we have the right class?
+            b = reader.getResource("/m1/p/Main.class");
+            Class<?> clazz = (new ByteArrayClassLoader()).loadClass("p.Main", b);
+            MethodHandle getVersion = MethodHandles.lookup()
+                    .findVirtual(clazz, "getVersion", MethodType.methodType(int.class));
+            int version = (int) getVersion.invoke(clazz.getConstructor().newInstance());
+            Assert.assertEquals(version, JarFile.runtimeVersion().major());
+        }
+    }
+
+    @Test
+    public void noLoggingTest() throws Throwable {
+        if (ignoreTest()) return;
+
+        jlink("m1-no-logging.jar", "no-logging-image");
+        runImage("no-logging-image", false);
+    }
+
+    @Test
+    public void loggingTest() throws Throwable {
+        if (ignoreTest()) return;
+
+        jlink("m1-logging.jar", "logging-image");
+        runImage("logging-image", true);
+
+    }
+
+    // java.base.jmod must exist for this test to make sense
+    private boolean ignoreTest() {
+        if (Files.isRegularFile(jmodsdir.resolve("java.base.jmod"))) {
+            return false;
+        }
+        System.err.println("Test skipped. NO jmods/java.base.jmod");
+        return true;
+    }
+
+
+    private void jlink(String jar, String image) {
+        String args = "--output " + image + " --add-modules m1 --module-path " +
+                jar + pathsep + jmodsdir.toString();
+        int exitCode = JLINK_TOOL.run(System.out, System.err, args.split(" +"));
+        Assert.assertEquals(exitCode, 0);
+    }
+
+    public void runImage(String image, boolean expected) throws Throwable {
+        Path java = Paths.get(image, "bin", "java");
+        OutputAnalyzer oa = ProcessTools.executeProcess(java.toString(), "-m", "m1/p.Main");
+        String sout = oa.getStdout();
+        boolean actual = sout.contains("logging found");
+        Assert.assertEquals(actual, expected);
+        System.out.println(sout);
+        System.err.println(oa.getStderr());
+        Assert.assertEquals(oa.getExitValue(), 0);
+    }
+
+    private static class ByteArrayClassLoader extends ClassLoader {
+        public Class<?> loadClass(String name, byte[] bytes) {
+            return defineClass(name, bytes, 0, bytes.length);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/base/m1/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/base/m1/p/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 p;
+
+import java.lang.module.ModuleFinder;
+
+public class Main {
+    private String msg = "something to give this a different size";
+
+    public int getVersion() {
+        return 8;
+    }
+
+    private void testForLogging() {
+        ModuleFinder.ofSystem().find("java.logging").ifPresentOrElse(
+                mr -> System.out.println("java.logging found in image"),
+                () -> System.out.println("java.logging not found in image")
+        );
+    }
+
+    public static void main(String[] args) {
+        Main main = new Main();
+        main.testForLogging();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/rt/m1/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 java.logging;
+    exports p;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/rt/m1/p/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.module.ModuleFinder;
+import java.util.jar.JarFile;
+
+public class Main {
+    public int getVersion() {
+        return JarFile.runtimeVersion().major();
+    }
+
+    private void testForLogging() {
+        ModuleFinder.ofSystem().find("java.logging").ifPresentOrElse(
+                mr -> System.out.println("java.logging found in image"),
+                () -> System.out.println("java.logging not found in image")
+        );
+    }
+
+    public static void main(String[] args) {
+        Main main = new Main();
+        main.testForLogging();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/rt/m1/p/Type.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+package p;
+
+class Type{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jlink/multireleasejar/rt/m1/q/PublicClass.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 q;
+
+public class PublicClass {
+    public void doNothing() {
+        int i = 3 + 2;
+    }
+}
--- a/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/jlink/plugins/IncludeLocalesPluginTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -40,7 +40,7 @@
 
 /*
  * @test
- * @bug 8152143 8152704 8155649
+ * @bug 8152143 8152704 8155649 8165804
  * @summary IncludeLocalesPlugin tests
  * @author Naoto Sato
  * @library ../../lib
@@ -236,6 +236,7 @@
                 "/jdk.localedata/sun/text/resources/ext/thai_dict",
                 "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
                 "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_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",
@@ -261,6 +262,7 @@
                 "/jdk.localedata/sun/text/resources/ext/thai_dict",
                 "/jdk.localedata/sun/text/resources/ext/WordBreakIteratorData_th",
                 "/jdk.localedata/sun/text/resources/ext/BreakIteratorInfo_th.class",
+                "/jdk.localedata/sun/text/resources/ext/BreakIteratorResources_th.class",
                 "/jdk.localedata/sun/text/resources/ext/FormatData_th.class"),
             List.of(
                 "/jdk.localedata/sun/text/resources/ext/FormatData_en_GB.class",
@@ -431,13 +433,23 @@
 
         for (Object[] data : testData) {
             // create image for each test data
-            System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
-            Result result = JImageGenerator.getJLinkTask()
+            Result result;
+            if (data[INCLUDE_LOCALES_OPTION].toString().isEmpty()) {
+                System.out.println("Invoking jlink with no --include-locales option");
+                result = JImageGenerator.getJLinkTask()
+                    .modulePath(helper.defaultModulePath())
+                    .output(helper.createNewImageDir(moduleName))
+                    .addMods((String) data[ADDMODS_OPTION])
+                    .call();
+            } else {
+                System.out.println("Invoking jlink with \"" + data[INCLUDE_LOCALES_OPTION] + "\"");
+                result = JImageGenerator.getJLinkTask()
                     .modulePath(helper.defaultModulePath())
                     .output(helper.createNewImageDir(moduleName))
                     .addMods((String) data[ADDMODS_OPTION])
                     .option((String) data[INCLUDE_LOCALES_OPTION])
                     .call();
+            }
 
             String errorMsg = (String) data[ERROR_MESSAGE];
             if (errorMsg.isEmpty()) {
--- a/jdk/test/tools/jmod/JmodTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/jmod/JmodTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,7 @@
  *          jdk.jlink
  * @build jdk.testlibrary.FileUtils CompilerUtils
  * @run testng JmodTest
+ * @bug 8142968
  * @summary Basic test for jmod
  */
 
@@ -85,6 +86,31 @@
         Files.createDirectories(MODS_DIR);
     }
 
+    // JDK-8166286 - jmod fails on symlink to directory
+    @Test
+    public void testSymlinks() throws IOException {
+        Path apaDir = EXPLODED_DIR.resolve("apa");
+        Path classesDir = EXPLODED_DIR.resolve("apa").resolve("classes");
+        assertTrue(compileModule("apa", classesDir));
+        Path libDir = apaDir.resolve("lib");
+        createFiles(libDir, List.of("foo/bar/libfoo.so"));
+        try {
+            Path link = Files.createSymbolicLink(
+                libDir.resolve("baz"), libDir.resolve("foo").toAbsolutePath());
+            assertTrue(Files.exists(link));
+        } catch (UnsupportedOperationException uoe) {
+            // OS does not support symlinks. Nothing to test!
+            return;
+        }
+
+        Path jmod = MODS_DIR.resolve("apa.jmod");
+        jmod("create",
+             "--libs=", libDir.toString(),
+             "--class-path", classesDir.toString(),
+             jmod.toString())
+            .assertSuccess();
+    }
+
     @Test
     public void testList() throws IOException {
         String cp = EXPLODED_DIR.resolve("foo").resolve("classes").toString();
--- a/jdk/test/tools/jmod/hashes/HashesTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/jmod/hashes/HashesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -26,7 +26,8 @@
  * @summary Test the recording and checking of module hashes
  * @author Andrei Eremeev
  * @library /lib/testlibrary
- * @modules java.base/jdk.internal.module
+ * @modules java.base/jdk.internal.misc
+ *          java.base/jdk.internal.module
  *          jdk.jlink
  *          jdk.compiler
  * @build CompilerUtils
@@ -39,7 +40,6 @@
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReader;
 import java.lang.module.ModuleReference;
-import java.lang.reflect.Method;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -55,8 +55,10 @@
 import java.util.spi.ToolProvider;
 import java.util.stream.Collectors;
 
-import jdk.internal.module.ConfigurableModuleFinder;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaLangModuleAccess;
 import jdk.internal.module.ModuleHashes;
+
 import org.testng.annotations.BeforeTest;
 import org.testng.annotations.Test;
 
@@ -74,7 +76,6 @@
     private final Path jmods = Paths.get("jmods");
     private final String[] modules = new String[] { "m1", "m2", "m3"};
 
-    private static Method hashesMethod;
     @BeforeTest
     private void setup() throws Exception {
         if (Files.exists(jmods)) {
@@ -97,13 +98,6 @@
         // compile org.bar and org.foo
         compileModule("org.bar", modSrc);
         compileModule("org.foo", modSrc);
-
-        try {
-            hashesMethod = ModuleDescriptor.class.getDeclaredMethod("hashes");
-            hashesMethod.setAccessible(true);
-        } catch (ReflectiveOperationException x) {
-            throw new InternalError(x);
-        }
     }
 
     @Test
@@ -143,17 +137,14 @@
     }
 
     private Optional<ModuleHashes> hashes(String name) throws Exception {
-        ModuleFinder finder = ModuleFinder.of(jmods.resolve(name + ".jmod"));
-        if (finder instanceof ConfigurableModuleFinder) {
-            ((ConfigurableModuleFinder) finder)
-                .configurePhase(ConfigurableModuleFinder.Phase.LINK_TIME);
-        }
+        ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess()
+            .newModulePath(Runtime.version(), true, jmods.resolve(name + ".jmod"));
         ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new);
         ModuleReader reader = mref.open();
         try (InputStream in = reader.open("module-info.class").get()) {
             ModuleDescriptor md = ModuleDescriptor.read(in);
-            Optional<ModuleHashes> hashes =
-                (Optional<ModuleHashes>) hashesMethod.invoke(md);
+            JavaLangModuleAccess jmla = SharedSecrets.getJavaLangModuleAccess();
+            Optional<ModuleHashes> hashes = jmla.hashes(md);
             System.out.format("hashes in module %s %s%n", name,
                               hashes.isPresent() ? "present" : "absent");
             if (hashes.isPresent()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/src/apa/jdk/test/apa/Apa.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.test.apa;
+
+public class Apa { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/jmod/src/apa/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module apa {
+    exports jdk.test.apa;
+}
--- a/jdk/test/tools/launcher/MiscTests.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/launcher/MiscTests.java	Fri Nov 11 16:44:36 2016 +0100
@@ -69,8 +69,6 @@
     static void test6856415() throws IOException {
 
         final String mainClass = "Foo6856415";
-        final String exportOpts
-            = "--add-exports=jdk.crypto.pkcs11/sun.security.pkcs11=ALL-UNNAMED";
 
         List<String> scratch = new ArrayList<>();
         scratch.add("public class Foo6856415 {");
@@ -81,7 +79,9 @@
         scratch.add("}");
         createFile(new File(mainClass + ".java"), scratch);
 
-        compile(mainClass + ".java", exportOpts);
+        compile(mainClass + ".java",
+                "--add-modules=jdk.crypto.pkcs11",
+                "--add-exports=jdk.crypto.pkcs11/sun.security.pkcs11=ALL-UNNAMED");
 
         File testJar = new File("Foo.jar");
         testJar.delete();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/JavaClassPathTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.List;
+import java.util.Map;
+
+import jdk.testlibrary.OutputAnalyzer;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+import static jdk.testlibrary.ProcessTools.*;
+
+/**
+ * @test
+ * @bug 8168205
+ * @summary Test the default class path if -Djava.class.path is set
+ * @library /lib/testlibrary
+ * @modules jdk.compiler
+ * @build CompilerUtils jdk.testlibrary.*
+ * @run testng JavaClassPathTest
+ */
+
+public class JavaClassPathTest {
+    private static final Path SRC_DIR = Paths.get(System.getProperty("test.src"),
+                                                  "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+    private static final String TEST_MODULE = "m";
+    private static final String TEST_MAIN = "jdk.test.Main";
+
+    @BeforeTest
+    public void setup() throws Exception {
+        boolean compiled = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
+                                                 MODS_DIR.resolve(TEST_MODULE));
+        assertTrue(compiled, "module " + TEST_MODULE + " did not compile");
+
+        // add the class and a resource to the current working directory
+        Path file = Paths.get("jdk/test/Main.class");
+        Files.createDirectories(file.getParent());
+        Files.copy(MODS_DIR.resolve(TEST_MODULE).resolve(file), file);
+
+        Path res = Paths.get("jdk/test/res.properties");
+        Files.createFile(res);
+    }
+
+    @DataProvider(name = "classpath")
+    public Object[][] classpath() {
+        return new Object[][]{
+            // true indicates that class path default to current working directory
+            { "",                              true  },
+            { "-Djava.class.path",             true  },
+            { "-Djava.class.path=",            true  },
+            { "-Djava.class.path=.",           true  },
+        };
+    }
+
+    @Test(dataProvider = "classpath")
+    public void testUnnamedModule(String option, boolean expected) throws Throwable {
+        List<String> args = new ArrayList<>();
+        if (!option.isEmpty()) {
+            args.add(option);
+        }
+        args.add(TEST_MAIN);
+        args.add(Boolean.toString(expected));
+
+        assertTrue(execute(args).getExitValue() == 0);
+    }
+
+    @DataProvider(name = "moduleAndClassPath")
+    public Object[][] moduleAndClassPath() {
+        return new Object[][]{
+            // true indicates that class path default to current working directory
+            { "",                              false  },
+            { "-Djava.class.path",             false  },
+            { "-Djava.class.path=",            false  },
+            { "-Djava.class.path=.",           true   },
+        };
+    }
+
+    @Test(dataProvider = "moduleAndClassPath")
+    public void testNamedModule(String option, boolean expected) throws Throwable {
+        List<String> args = new ArrayList<>();
+        if (!option.isEmpty()) {
+            args.add(option);
+        }
+        args.add("--module-path");
+        args.add(MODS_DIR.toString());
+        args.add("-m");
+        args.add(TEST_MODULE + "/" + TEST_MAIN);
+        args.add(Boolean.toString(expected));
+
+        assertTrue(execute(args).getExitValue() == 0);
+    }
+
+    private OutputAnalyzer execute(List<String> options) throws Throwable {
+        ProcessBuilder pb =
+            createJavaProcessBuilder(options.toArray(new String[0]));
+        Map<String,String> env = pb.environment();
+        // remove CLASSPATH environment variable
+        String value = env.remove("CLASSPATH");
+        return executeCommand(pb)
+                    .outputTo(System.out)
+                    .errorTo(System.out);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/src/m/jdk/test/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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;
+
+public class Main {
+    static final String JAVA_CLASS_PATH = "java.class.path";
+
+    public static void main(String[] args) throws Exception {
+        String value = System.getProperty(JAVA_CLASS_PATH);
+        if (value == null) {
+            throw new RuntimeException(JAVA_CLASS_PATH + " is expected non-null" +
+                " for compatibility");
+        }
+
+        boolean expected = args[0].equals("true");
+        ClassLoader loader = ClassLoader.getSystemClassLoader();
+        URL url = loader.getResource("jdk/test/res.properties");
+        if ((expected && url == null) || (!expected && url != null)) {
+            throw new RuntimeException("URL: " + url + " expected non-null: " + expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/modules/classpath/src/m/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 m {
+}
+
--- a/jdk/test/tools/pack200/MultiRelease.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/pack200/MultiRelease.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -60,6 +60,7 @@
         } else {
             System.out.println("All tests(" + pass + ") passes");
         }
+        Utils.cleanup();
     }
 
     /*
--- a/jdk/test/tools/pack200/Utils.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/jdk/test/tools/pack200/Utils.java	Fri Nov 11 16:44:36 2016 +0100
@@ -94,7 +94,7 @@
         }
         File srcDir = new File(getVerifierDir(), "src");
         List<File> javaFileList = findFiles(srcDir, createFilter(JAVA_FILE_EXT));
-        File tmpFile = File.createTempFile("javac", ".tmp");
+        File tmpFile = File.createTempFile("javac", ".tmp", new File("."));
         XCLASSES.mkdirs();
         FileOutputStream fos = null;
         PrintStream ps = null;
@@ -208,6 +208,10 @@
                 Utils.createFilter(".idx")));
         toDelete.addAll(Utils.findFiles(new File("."),
                 Utils.createFilter(".gidx")));
+        toDelete.addAll(Utils.findFiles(new File("."),
+                Utils.createFilter(".tmp")));
+        toDelete.addAll(Utils.findFiles(new File("."),
+                Utils.createFilter(".class")));
         for (File f : toDelete) {
             f.delete();
         }
--- a/langtools/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -384,3 +384,5 @@
 17a82cb0e4b480e97021691d39917f15e3f7b653 jdk-9+139
 6842e63d6c3971172214b411f29965852ca175d1 jdk-9+140
 296c875051187918f8f3f87e9432036d13013d39 jdk-9+141
+d245e56f4a79a8a8d18bd143c08f079ee98ab638 jdk-9+142
+6ef8a1453577832626b0efb7f70a3102b721ebbf jdk-9+143
--- a/langtools/make/build.xml	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/make/build.xml	Fri Nov 11 16:44:36 2016 +0100
@@ -84,17 +84,21 @@
     <property name="build.prevsrc" location="${build.dir}/prevsrc"/>
 
     <pathconvert property="modules.names" pathsep=",">
-        <globmapper from="${src.dir}/*" to="*" />
+        <globmapper from="${src.dir}/*" to="*" handledirsep="yes"/>
         <dirset dir="${src.dir}" includes="*.*"/>
     </pathconvert>
 
     <pathconvert property="xpatch.rest" pathsep=" --patch-module=">
-        <regexpmapper from="${file.separator}([^${file.separator}]+)$" to='\1="${build.modules}${file.separator}\1"' />
+        <regexpmapper from="/([^$/]+)$"
+                      to='\1="${build.modules}/\1"'
+                      handledirsep="yes"/>
         <dirset dir="${src.dir}" includes="*.*"/>
     </pathconvert>
 
     <pathconvert property="xpatch.noquotes.rest" pathsep=" --patch-module=">
-        <regexpmapper from="${file.separator}([^${file.separator}]+)$" to="\1=${build.modules}${file.separator}\1" />
+        <regexpmapper from="/([^$/]+)$"
+                      to="\1=${build.modules}/\1"
+                      handledirsep="yes"/>
         <dirset dir="${src.dir}" includes="*.*"/>
     </pathconvert>
 
@@ -207,7 +211,9 @@
             <arg line="-source ${javac.source} -target ${javac.target}" />
             <arg value="-d" />
             <arg value="${build.modules}" />
-            <arg line="${javac.opts} --module-source-path ${src.dir}${file.separator}*${file.separator}share${file.separator}classes:${build.gensrc} -m ${modules.names}" />
+            <arg line="${javac.opts}" />
+            <arg line="--module-source-path ${src.dir}${file.separator}*${file.separator}share${file.separator}classes${path.separator}${build.gensrc}" />
+            <arg line="-m ${modules.names}" />
         </exec>
         <delete>
             <fileset dir="${build.modules}" includes="**/module-info.class"/>
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/doclint/Entity.java	Fri Nov 11 16:44:36 2016 +0100
@@ -297,17 +297,21 @@
     rsaquo(8250),
     euro(8364);
 
-    int code;
+    public final int code;
 
     private Entity(int code) {
         this.code = code;
     }
 
-    static boolean isValid(String name) {
+    public static boolean isValid(String name) {
         return names.containsKey(name);
     }
 
-    static boolean isValid(int code) {
+    public static Entity get(String name) {
+        return names.get(name);
+    }
+
+    public static boolean isValid(int code) {
         // allow numeric codes for standard ANSI characters
         return codes.containsKey(code) || ( 32 <= code && code < 2127);
     }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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
@@ -101,6 +101,8 @@
                 @Override
                 public Main.Result call() throws Exception {
                     prepareCompiler(false);
+                    if (compiler.errorCount() > 0)
+                        return Main.Result.ERROR;
                     compiler.compile(args.getFileObjects(), args.getClassNames(), processors);
                     return (compiler.errorCount() > 0) ? Main.Result.ERROR : Main.Result.OK; // FIXME?
                 }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1004,7 +1004,7 @@
        List<Type> argtypes = msym.type.getParameterTypes();
        return (msym.flags_field & NATIVE) != 0 &&
               (msym.owner == syms.methodHandleType.tsym || msym.owner == syms.varHandleType.tsym) &&
-               argtypes.tail.tail == null &&
+               argtypes.length() == 1 &&
                argtypes.head.hasTag(TypeTag.ARRAY) &&
                ((ArrayType)argtypes.head).elemtype.tsym == syms.objectType.tsym;
    }
@@ -2850,20 +2850,64 @@
             return undef;
         }
 
+    public class CandidatesCache {
+        public Map<Entry, List<MethodSymbol>> cache = new WeakHashMap<>();
+
+        class Entry {
+            Type site;
+            MethodSymbol msym;
+
+            Entry(Type site, MethodSymbol msym) {
+                this.site = site;
+                this.msym = msym;
+            }
+
+            @Override
+            public boolean equals(Object obj) {
+                if (obj instanceof Entry) {
+                    Entry e = (Entry)obj;
+                    return e.msym == msym && isSameType(site, e.site);
+                } else {
+                    return false;
+                }
+            }
+
+            @Override
+            public int hashCode() {
+                return Types.this.hashCode(site) & ~msym.hashCode();
+            }
+        }
+
+        public List<MethodSymbol> get(Entry e) {
+            return cache.get(e);
+        }
+
+        public void put(Entry e, List<MethodSymbol> msymbols) {
+            cache.put(e, msymbols);
+        }
+    }
+
+    public CandidatesCache candidatesCache = new CandidatesCache();
 
     //where
     public List<MethodSymbol> interfaceCandidates(Type site, MethodSymbol ms) {
-        Filter<Symbol> filter = new MethodFilter(ms, site);
-        List<MethodSymbol> candidates = List.nil();
+        CandidatesCache.Entry e = candidatesCache.new Entry(site, ms);
+        List<MethodSymbol> candidates = candidatesCache.get(e);
+        if (candidates == null) {
+            Filter<Symbol> filter = new MethodFilter(ms, site);
+            List<MethodSymbol> candidates2 = List.nil();
             for (Symbol s : membersClosure(site, false).getSymbols(filter)) {
                 if (!site.tsym.isInterface() && !s.owner.isInterface()) {
                     return List.of((MethodSymbol)s);
-                } else if (!candidates.contains(s)) {
-                    candidates = candidates.prepend((MethodSymbol)s);
+                } else if (!candidates2.contains(s)) {
+                    candidates2 = candidates2.prepend((MethodSymbol)s);
                 }
             }
-            return prune(candidates);
+            candidates = prune(candidates2);
+            candidatesCache.put(e, candidates);
         }
+        return candidates;
+    }
 
     public List<MethodSymbol> prune(List<MethodSymbol> methods) {
         ListBuffer<MethodSymbol> methodsMin = new ListBuffer<>();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java	Fri Nov 11 16:44:36 2016 +0100
@@ -853,9 +853,9 @@
             List<Type> caughtPrev = caught;
             ListBuffer<FlowPendingExit> pendingExitsPrev = pendingExits;
             Lint lintPrev = lint;
-
+            boolean anonymousClass = tree.name == names.empty;
             pendingExits = new ListBuffer<>();
-            if (tree.name != names.empty) {
+            if (!anonymousClass) {
                 caught = List.nil();
             }
             classDef = tree;
@@ -874,7 +874,7 @@
 
                 // add intersection of all thrown clauses of initial constructors
                 // to set of caught exceptions, unless class is anonymous.
-                if (tree.name != names.empty) {
+                if (!anonymousClass) {
                     boolean firstConstructor = true;
                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
                         if (TreeInfo.isInitialConstructor(l.head)) {
@@ -905,10 +905,11 @@
                 // Changing the throws clause on the fly is okay here because
                 // the anonymous constructor can't be invoked anywhere else,
                 // and its type hasn't been cached.
-                if (tree.name == names.empty) {
+                if (anonymousClass) {
                     for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
-                        if (TreeInfo.isInitialConstructor(l.head)) {
+                        if (TreeInfo.isConstructor(l.head)) {
                             JCMethodDecl mdef = (JCMethodDecl)l.head;
+                            scan(mdef);
                             mdef.thrown = make.Types(thrown);
                             mdef.sym.type = types.createMethodTypeWithThrown(mdef.sym.type, thrown);
                         }
@@ -918,6 +919,8 @@
 
                 // process all the methods
                 for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+                    if (anonymousClass && TreeInfo.isConstructor(l.head))
+                        continue; // there can never be an uncaught exception.
                     if (l.head.hasTag(METHODDEF)) {
                         scan(l.head);
                         errorUncaught();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -404,15 +404,11 @@
         } else if (to.hasTag(NONE)) {
             to = from.isPrimitive() ? from : syms.objectType;
         } else if (qtype.hasTag(UNDETVAR)) {
-            if (resultInfo.pt.isReference()) {
-                if (needsEagerInstantiation((UndetVar)qtype, to, inferenceContext)) {
-                    to = generateReferenceToTargetConstraint(tree, (UndetVar)qtype, to, resultInfo, inferenceContext);
-                }
-            } else {
-                if (to.isPrimitive()) {
-                    to = generateReturnConstraintsPrimitive(tree, (UndetVar)qtype, to,
-                        resultInfo, inferenceContext);
-                }
+            if (needsEagerInstantiation((UndetVar)qtype, to, inferenceContext) &&
+                    (allowGraphInference || !to.isPrimitive())) {
+                to = generateReferenceToTargetConstraint(tree, (UndetVar)qtype, to, resultInfo, inferenceContext);
+            } else if (to.isPrimitive()) {
+                to = types.boxedClass(to).type;
             }
         } else if (rsInfoInfContext.free(resultInfo.pt)) {
             //propagation - cache captured vars
@@ -432,26 +428,21 @@
         return from;
     }
 
-    private Type generateReturnConstraintsPrimitive(JCTree tree, UndetVar from,
-            Type to, Attr.ResultInfo resultInfo, InferenceContext inferenceContext) {
-        if (!allowGraphInference) {
-            //if legacy, just return boxed type
-            return types.boxedClass(to).type;
+    private boolean needsEagerInstantiation(UndetVar from, Type to, InferenceContext inferenceContext) {
+        if (to.isPrimitive()) {
+            /* T is a primitive type, and one of the primitive wrapper classes is an instantiation,
+             * upper bound, or lower bound for alpha in B2.
+             */
+            for (Type t : from.getBounds(InferenceBound.values())) {
+                Type boundAsPrimitive = types.unboxedType(t);
+                if (boundAsPrimitive == null || boundAsPrimitive.hasTag(NONE)) {
+                    continue;
+                }
+                return true;
+            }
+            return false;
         }
-        //if graph inference we need to skip conflicting boxed bounds...
-        for (Type t : from.getBounds(InferenceBound.EQ, InferenceBound.UPPER,
-                InferenceBound.LOWER)) {
-            Type boundAsPrimitive = types.unboxedType(t);
-            if (boundAsPrimitive == null || boundAsPrimitive.hasTag(NONE)) {
-                continue;
-            }
-            return generateReferenceToTargetConstraint(tree, from, to,
-                    resultInfo, inferenceContext);
-        }
-        return types.boxedClass(to).type;
-    }
 
-    private boolean needsEagerInstantiation(UndetVar from, Type to, InferenceContext inferenceContext) {
         Type captureOfTo = types.capture(to);
         /* T is a reference type, but is not a wildcard-parameterized type, and either
          */
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Fri Nov 11 16:44:36 2016 +0100
@@ -36,7 +36,6 @@
 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.Consumer;
 import java.util.function.Predicate;
@@ -59,6 +58,7 @@
 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.Lint.LintCategory;
 import com.sun.tools.javac.code.ModuleFinder;
 import com.sun.tools.javac.code.Source;
 import com.sun.tools.javac.code.Symbol;
@@ -131,6 +131,7 @@
     private final Types types;
     private final JavaFileManager fileManager;
     private final ModuleFinder moduleFinder;
+    private final Source source;
     private final boolean allowModules;
 
     public final boolean multiModuleMode;
@@ -151,6 +152,8 @@
     private final String limitModsOpt;
     private final Set<String> extraLimitMods = new HashSet<>();
 
+    private final boolean lintOptions;
+
     private Set<ModuleSymbol> rootModules = null;
 
     public static Modules instance(Context context) {
@@ -170,9 +173,12 @@
         moduleFinder = ModuleFinder.instance(context);
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
-        allowModules = Source.instance(context).allowModules();
+        source = Source.instance(context);
+        allowModules = source.allowModules();
         Options options = Options.instance(context);
 
+        lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
+
         moduleOverride = options.get(Option.XMODULE);
 
         multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
@@ -487,7 +493,7 @@
             ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
 
             if (msym.kind == Kinds.Kind.ERR) {
-                log.error(Errors.CantFindModule(msym));
+                log.error(Errors.ModuleNotFound(msym));
                 //make sure the module is initialized:
                 msym.directives = List.nil();
                 msym.exports = List.nil();
@@ -684,15 +690,10 @@
         }
 
         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;
-            }
         }
     }
 
@@ -776,8 +777,6 @@
                 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) {
@@ -884,6 +883,8 @@
             Set<ModuleSymbol> limitMods = new HashSet<>();
             if (limitModsOpt != null) {
                 for (String limit : limitModsOpt.split(",")) {
+                    if (!isValidName(limit))
+                        continue;
                     limitMods.add(syms.enterModule(names.fromString(limit)));
                 }
             }
@@ -892,6 +893,14 @@
             }
             observable = computeTransitiveClosure(limitMods, null);
             observable.addAll(rootModules);
+            if (lintOptions) {
+                for (ModuleSymbol msym : limitMods) {
+                    if (!observable.contains(msym)) {
+                        log.warning(LintCategory.OPTIONS,
+                                Warnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym));
+                    }
+                }
+            }
         }
 
         Predicate<ModuleSymbol> observablePred = sym -> observable == null || observable.contains(sym);
@@ -944,6 +953,8 @@
                                       .filter(systemModulePred.negate().and(observablePred));
                         break;
                     default:
+                        if (!isValidName(added))
+                            continue;
                         modules = Stream.of(syms.enterModule(names.fromString(added)));
                         break;
                 }
@@ -1141,8 +1152,9 @@
             addVisiblePackages(msym, seen, rm, rm.exports);
         }
 
-        for (Entry<ModuleSymbol, Set<ExportsDirective>> addExportsEntry : addExports.entrySet())
-            addVisiblePackages(msym, seen, addExportsEntry.getKey(), addExportsEntry.getValue());
+        addExports.forEach((exportsFrom, exports) -> {
+            addVisiblePackages(msym, seen, exportsFrom, exports);
+        });
     }
 
     private void addVisiblePackages(ModuleSymbol msym,
@@ -1180,12 +1192,11 @@
             return;
 
         addExports = new LinkedHashMap<>();
+        Set<ModuleSymbol> unknownModules = new HashSet<>();
 
         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())
@@ -1203,7 +1214,15 @@
             String packageName = em.group(2);
             String targetNames = em.group(3);
 
+            if (!isValidName(moduleName))
+                continue;
+
             ModuleSymbol msym = syms.enterModule(names.fromString(moduleName));
+            if (!isKnownModule(msym, unknownModules))
+                continue;
+
+            if (!isValidName(packageName))
+                continue;
             PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
             p.modle = msym;  // TODO: do we need this?
 
@@ -1213,11 +1232,11 @@
                 if (toModule.equals("ALL-UNNAMED")) {
                     m = syms.unnamedModule;
                 } else {
-                    if (!SourceVersion.isName(toModule)) {
-                        // TODO: error: invalid module name
+                    if (!isValidName(toModule))
                         continue;
-                    }
                     m = syms.enterModule(names.fromString(toModule));
+                    if (!isKnownModule(m, unknownModules))
+                        continue;
                 }
                 targetModules = targetModules.prepend(m);
             }
@@ -1228,6 +1247,21 @@
         }
     }
 
+    private boolean isKnownModule(ModuleSymbol msym, Set<ModuleSymbol> unknownModules) {
+        if (allModules.contains(msym)) {
+            return true;
+        }
+
+        if (!unknownModules.contains(msym)) {
+            if (lintOptions) {
+                log.warning(LintCategory.OPTIONS,
+                        Warnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym));
+            }
+            unknownModules.add(msym);
+        }
+        return false;
+    }
+
     private void initAddReads() {
         if (addReads != null)
             return;
@@ -1237,8 +1271,6 @@
         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())
@@ -1249,26 +1281,40 @@
             }
 
             // Terminology comes from
-            //  --add-reads target-module=source-module,...
+            //  --add-reads source-module=target-module,...
             // Compare to
-            //  module target-module { requires source-module; ... }
-            String targetName = rm.group(1);
-            String sources = rm.group(2);
+            //  module source-module { requires target-module; ... }
+            String sourceName = rm.group(1);
+            String targetNames = rm.group(2);
+
+            if (!isValidName(sourceName))
+                continue;
 
-            ModuleSymbol msym = syms.enterModule(names.fromString(targetName));
-            for (String source : sources.split("[ ,]+")) {
-                ModuleSymbol sourceModule;
-                if (source.equals("ALL-UNNAMED")) {
-                    sourceModule = syms.unnamedModule;
+            ModuleSymbol msym = syms.enterModule(names.fromString(sourceName));
+            if (!allModules.contains(msym)) {
+                if (lintOptions) {
+                    log.warning(Warnings.ModuleForOptionNotFound(Option.ADD_READS, msym));
+                }
+                continue;
+            }
+
+            for (String targetName : targetNames.split("[ ,]+", -1)) {
+                ModuleSymbol targetModule;
+                if (targetName.equals("ALL-UNNAMED")) {
+                    targetModule = syms.unnamedModule;
                 } else {
-                    if (!SourceVersion.isName(source)) {
-                        // TODO: error: invalid module name
+                    if (!isValidName(targetName))
+                        continue;
+                    targetModule = syms.enterModule(names.fromString(targetName));
+                    if (!allModules.contains(targetModule)) {
+                        if (lintOptions) {
+                            log.warning(LintCategory.OPTIONS, Warnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule));
+                        }
                         continue;
                     }
-                    sourceModule = syms.enterModule(names.fromString(source));
                 }
                 addReads.computeIfAbsent(msym, m -> new HashSet<>())
-                        .add(new RequiresDirective(sourceModule, EnumSet.of(RequiresFlag.EXTRA)));
+                        .add(new RequiresDirective(targetModule, EnumSet.of(RequiresFlag.EXTRA)));
             }
         }
     }
@@ -1301,6 +1347,10 @@
         }
     }
 
+    private boolean isValidName(CharSequence name) {
+        return SourceVersion.isName(name, Source.toSourceVersion(source));
+    }
+
     // DEBUG
     private String toString(ModuleSymbol msym) {
         return msym.name + "["
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Fri Nov 11 16:44:36 2016 +0100
@@ -554,7 +554,8 @@
         } else if (mt.hasTag(FORALL) && typeargtypes.nonEmpty()) {
             ForAll pmt = (ForAll) mt;
             if (typeargtypes.length() != pmt.tvars.length())
-                throw inapplicableMethodException.setMessage("arg.length.mismatch"); // not enough args
+                 // not enough args
+                throw inapplicableMethodException.setMessage("wrong.number.type.args", Integer.toString(pmt.tvars.length()));
             // Check type arguments are within bounds
             List<Type> formals = pmt.tvars;
             List<Type> actuals = typeargtypes;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java	Fri Nov 11 16:44:36 2016 +0100
@@ -39,6 +39,7 @@
 import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
+import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.ProviderNotFoundException;
@@ -66,6 +67,7 @@
 import javax.lang.model.SourceVersion;
 import javax.tools.JavaFileManager;
 import javax.tools.JavaFileManager.Location;
+import javax.tools.JavaFileObject;
 import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardJavaFileManager.PathFactory;
 import javax.tools.StandardLocation;
@@ -137,7 +139,11 @@
     }
 
     Path getPath(String first, String... more) {
-        return pathFactory.getPath(first, more);
+        try {
+            return pathFactory.getPath(first, more);
+        } catch (InvalidPathException ipe) {
+            throw new IllegalArgumentException(ipe);
+        }
     }
 
     public void close() throws IOException {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1328,7 +1328,7 @@
         } else {
             ((ClassType)sym.type).setEnclosingType(Type.noType);
         }
-        enterTypevars(self);
+        enterTypevars(self, self.type);
         if (!missingTypeVariables.isEmpty()) {
             ListBuffer<Type> typeVars =  new ListBuffer<>();
             for (Type typevar : missingTypeVariables) {
@@ -2353,19 +2353,17 @@
     /** Enter type variables of this classtype and all enclosing ones in
      *  `typevars'.
      */
-    protected void enterTypevars(Type t) {
-        if (t.getEnclosingType() != null && t.getEnclosingType().hasTag(CLASS))
-            enterTypevars(t.getEnclosingType());
-        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail)
+    protected void enterTypevars(Symbol sym, Type t) {
+        if (t.getEnclosingType() != null) {
+            if (!t.getEnclosingType().hasTag(TypeTag.NONE)) {
+                enterTypevars(sym.owner, t.getEnclosingType());
+            }
+        } else if (sym.kind == MTH && !sym.isStatic()) {
+            enterTypevars(sym.owner, sym.owner.type);
+        }
+        for (List<Type> xs = t.getTypeArguments(); xs.nonEmpty(); xs = xs.tail) {
             typevars.enter(xs.head.tsym);
-    }
-
-    protected void enterTypevars(Symbol sym) {
-        if (sym.owner.kind == MTH) {
-            enterTypevars(sym.owner);
-            enterTypevars(sym.owner.owner);
         }
-        enterTypevars(sym.type);
     }
 
     protected ClassSymbol enterClass(Name name) {
@@ -2388,7 +2386,7 @@
         // prepare type variable table
         typevars = typevars.dup(currentOwner);
         if (ct.getEnclosingType().hasTag(CLASS))
-            enterTypevars(ct.getEnclosingType());
+            enterTypevars(c.owner, ct.getEnclosingType());
 
         // read flags, or skip if this is an inner class
         long f = nextChar();
@@ -2545,6 +2543,11 @@
                     types.subst(ct.supertype_field, missing, found);
                 ct.interfaces_field =
                     types.subst(ct.interfaces_field, missing, found);
+                ct.typarams_field =
+                    types.substBounds(ct.typarams_field, missing, found);
+                for (List<Type> types = ct.typarams_field; types.nonEmpty(); types = types.tail) {
+                    types.head.tsym.type = types.head;
+                }
             } else if (missingTypeVariables.isEmpty() !=
                        foundTypeVariables.isEmpty()) {
                 Name name = missingTypeVariables.head.tsym.name;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Fri Nov 11 16:44:36 2016 +0100
@@ -43,6 +43,7 @@
 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;
@@ -400,7 +401,7 @@
     /**
      * Validates the overall consistency of the options and operands
      * processed by processOptions.
-     * @return true if all args are successfully validating; false otherwise.
+     * @return true if all args are successfully validated; false otherwise.
      * @throws IllegalStateException if a problem is found and errorMode is set to
      *      ILLEGAL_STATE
      */
@@ -610,62 +611,143 @@
         if (obsoleteOptionFound)
             log.warning(LintCategory.OPTIONS, "option.obsolete.suppression");
 
+        SourceVersion sv = Source.toSourceVersion(source);
+        validateAddExports(sv);
+        validateAddModules(sv);
+        validateAddReads(sv);
+        validateLimitModules(sv);
+
+        return !errors && (log.nerrors == 0);
+    }
+
+    private void validateAddExports(SourceVersion sv) {
         String addExports = options.get(Option.ADD_EXPORTS);
         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")) {
+            // Each entry must be of the form sourceModule/sourcePackage=target-list where
+            // target-list is a comma separated list of module or ALL-UNNAMED.
+            // Empty items in the target-list are ignored.
+            // There must be at least one item in the list; this is handled in Option.ADD_EXPORTS.
+            Pattern p = Option.ADD_EXPORTS.getPattern();
+            for (String e : addExports.split("\0")) {
                 Matcher m = p.matcher(e);
-                if (!m.matches()) {
-                    log.error(Errors.XaddexportsMalformedEntry(e));
-                    continue;
+                if (m.matches()) {
+                    String sourceModuleName = m.group(1);
+                    if (!SourceVersion.isName(sourceModuleName, sv)) {
+                        // syntactically invalid source name:  e.g. --add-exports m!/p1=m2
+                        log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, sourceModuleName));
+                    }
+                    String sourcePackageName = m.group(2);
+                    if (!SourceVersion.isName(sourcePackageName, sv)) {
+                        // syntactically invalid source name:  e.g. --add-exports m1/p!=m2
+                        log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, sourcePackageName));
+                    }
+
+                    String targetNames = m.group(3);
+                    for (String targetName : targetNames.split(",")) {
+                        switch (targetName) {
+                            case "":
+                            case "ALL-UNNAMED":
+                                break;
+
+                            default:
+                                if (!SourceVersion.isName(targetName, sv)) {
+                                    // syntactically invalid target name:  e.g. --add-exports m1/p1=m!
+                                    log.warning(Warnings.BadNameForOption(Option.ADD_EXPORTS, targetName));
+                                }
+                                break;
+                        }
+                    }
                 }
-                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
-                }
-            });
         }
+    }
 
+    private void validateAddReads(SourceVersion sv) {
         String addReads = options.get(Option.ADD_READS);
         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")) {
+            // Each entry must be of the form source=target-list where target-list is a
+            // comma-separated list of module or ALL-UNNAMED.
+            // Empty items in the target list are ignored.
+            // There must be at least one item in the list; this is handled in Option.ADD_READS.
+            Pattern p = Option.ADD_READS.getPattern();
+            for (String e : addReads.split("\0")) {
                 Matcher m = p.matcher(e);
-                if (!m.matches()) {
-                    log.error(Errors.XaddreadsMalformedEntry(e));
-                    continue;
+                if (m.matches()) {
+                    String sourceName = m.group(1);
+                    if (!SourceVersion.isName(sourceName, sv)) {
+                        // syntactically invalid source name:  e.g. --add-reads m!=m2
+                        log.warning(Warnings.BadNameForOption(Option.ADD_READS, sourceName));
+                    }
+
+                    String targetNames = m.group(2);
+                    for (String targetName : targetNames.split(",", -1)) {
+                        switch (targetName) {
+                            case "":
+                            case "ALL-UNNAMED":
+                                break;
+
+                            default:
+                                if (!SourceVersion.isName(targetName, sv)) {
+                                    // syntactically invalid target name:  e.g. --add-reads m1=m!
+                                    log.warning(Warnings.BadNameForOption(Option.ADD_READS, targetName));
+                                }
+                                break;
+                        }
+                    }
                 }
-                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
+        }
+    }
+
+    private void validateAddModules(SourceVersion sv) {
+        String addModules = options.get(Option.ADD_MODULES);
+        if (addModules != null) {
+            // Each entry must be of the form target-list where target-list is a
+            // comma separated list of module names, or ALL-DEFAULT, ALL-SYSTEM,
+            // or ALL-MODULE_PATH.
+            // Empty items in the target list are ignored.
+            // There must be at least one item in the list; this is handled in Option.ADD_MODULES.
+            for (String moduleName : addModules.split(",")) {
+                switch (moduleName) {
+                    case "":
+                    case "ALL-DEFAULT":
+                    case "ALL-SYSTEM":
+                    case "ALL-MODULE-PATH":
+                        break;
+
+                    default:
+                        if (!SourceVersion.isName(moduleName, sv)) {
+                            // syntactically invalid module name:  e.g. --add-modules m1,m!
+                            log.warning(Warnings.BadNameForOption(Option.ADD_MODULES, moduleName));
+                        }
+                        break;
                 }
-            });
+            }
         }
+    }
 
+    private void validateLimitModules(SourceVersion sv) {
+        String limitModules = options.get(Option.LIMIT_MODULES);
+        if (limitModules != null) {
+            // Each entry must be of the form target-list where target-list is a
+            // comma separated list of module names, or ALL-DEFAULT, ALL-SYSTEM,
+            // or ALL-MODULE_PATH.
+            // Empty items in the target list are ignored.
+            // There must be at least one item in the list; this is handled in Option.LIMIT_EXPORTS.
+            for (String moduleName : limitModules.split(",")) {
+                switch (moduleName) {
+                    case "":
+                        break;
 
-        return !errors;
+                    default:
+                        if (!SourceVersion.isName(moduleName, sv)) {
+                            // syntactically invalid module name:  e.g. --limit-modules m1,m!
+                            log.warning(Warnings.BadNameForOption(Option.LIMIT_MODULES, moduleName));
+                        }
+                        break;
+                }
+            }
+        }
     }
 
     /**
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java	Fri Nov 11 16:44:36 2016 +0100
@@ -43,6 +43,7 @@
 import java.util.ServiceLoader;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
@@ -556,18 +557,44 @@
     ADD_EXPORTS("--add-exports", "opt.arg.addExports", "opt.addExports", EXTENDED, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option, String arg) {
-            String prev = helper.get(ADD_EXPORTS);
-            helper.put(ADD_EXPORTS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
-            return false;
+            if (arg.isEmpty()) {
+                helper.error("err.no.value.for.option", option);
+                return true;
+            } else if (getPattern().matcher(arg).matches()) {
+                String prev = helper.get(ADD_EXPORTS);
+                helper.put(ADD_EXPORTS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
+                return false;
+            } else {
+                helper.error("err.bad.value.for.option", option, arg);
+                return true;
+            }
+        }
+
+        @Override
+        public Pattern getPattern() {
+            return Pattern.compile("([^/]+)/([^=]+)=(,*[^,].*)");
         }
     },
 
     ADD_READS("--add-reads", "opt.arg.addReads", "opt.addReads", EXTENDED, BASIC) {
         @Override
         public boolean process(OptionHelper helper, String option, String arg) {
-            String prev = helper.get(ADD_READS);
-            helper.put(ADD_READS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
-            return false;
+            if (arg.isEmpty()) {
+                helper.error("err.no.value.for.option", option);
+                return true;
+            } else if (getPattern().matcher(arg).matches()) {
+                String prev = helper.get(ADD_READS);
+                helper.put(ADD_READS.primaryName, (prev == null) ? arg : prev + '\0' + arg);
+                return false;
+            } else {
+                helper.error("err.bad.value.for.option", option, arg);
+                return true;
+            }
+        }
+
+        @Override
+        public Pattern getPattern() {
+            return Pattern.compile("([^=]+)=(,*[^,].*)");
         }
     },
 
@@ -577,6 +604,7 @@
             String prev = helper.get(XMODULE);
             if (prev != null) {
                 helper.error("err.option.too.many", XMODULE.primaryName);
+                return true;
             }
             helper.put(XMODULE.primaryName, arg);
             return false;
@@ -585,9 +613,50 @@
 
     MODULE("--module -m", "opt.arg.m", "opt.m", STANDARD, BASIC),
 
-    ADD_MODULES("--add-modules", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC),
+    ADD_MODULES("--add-modules", "opt.arg.addmods", "opt.addmods", STANDARD, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option, String arg) {
+            if (arg.isEmpty()) {
+                helper.error("err.no.value.for.option", option);
+                return true;
+            } else if (getPattern().matcher(arg).matches()) {
+                String prev = helper.get(ADD_MODULES);
+                // since the individual values are simple names, we can simply join the
+                // values of multiple --add-modules options with ','
+                helper.put(ADD_MODULES.primaryName, (prev == null) ? arg : prev + ',' + arg);
+                return false;
+            } else {
+                helper.error("err.bad.value.for.option", option, arg);
+                return true;
+            }
+        }
 
-    LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC),
+        @Override
+        public Pattern getPattern() {
+            return Pattern.compile(",*[^,].*");
+        }
+    },
+
+    LIMIT_MODULES("--limit-modules", "opt.arg.limitmods", "opt.limitmods", STANDARD, BASIC) {
+        @Override
+        public boolean process(OptionHelper helper, String option, String arg) {
+            if (arg.isEmpty()) {
+                helper.error("err.no.value.for.option", option);
+                return true;
+            } else if (getPattern().matcher(arg).matches()) {
+                helper.put(LIMIT_MODULES.primaryName, arg); // last one wins
+                return false;
+            } else {
+                helper.error("err.bad.value.for.option", option, arg);
+                return true;
+            }
+        }
+
+        @Override
+        public Pattern getPattern() {
+            return Pattern.compile(",*[^,].*");
+        }
+    },
 
     // This option exists only for the purpose of documenting itself.
     // It's actually implemented by the CommandLine class.
@@ -963,20 +1032,24 @@
      */
     public boolean handleOption(OptionHelper helper, String arg, Iterator<String> rest) {
         if (hasArg()) {
+            String option;
             String operand;
             int sep = findSeparator(arg);
             if (getArgKind() == Option.ArgKind.ADJACENT) {
+                option = primaryName; // aliases not supported
                 operand = arg.substring(primaryName.length());
             } else if (sep > 0) {
+                option = arg.substring(0, sep);
                 operand = arg.substring(sep + 1);
             } else {
                 if (!rest.hasNext()) {
                     helper.error("err.req.arg", arg);
                     return false;
                 }
+                option = arg;
                 operand = rest.next();
             }
-            return !process(helper, arg, operand);
+            return !process(helper, option, operand);
         } else {
             return !process(helper, arg);
         }
@@ -1033,6 +1106,15 @@
     }
 
     /**
+     * Returns a pattern to analyze the value for an option.
+     * @return the pattern
+     * @throws UnsupportedOperationException if an option does not provide a pattern.
+     */
+    public Pattern getPattern() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
      * Scans a word to find the first separator character, either colon or equals.
      * @param word the word to be scanned
      * @return the position of the first':' or '=' character in the word,
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -2124,6 +2124,10 @@
 compiler.misc.arg.length.mismatch=\
     actual and formal argument lists differ in length
 
+# 0: string
+compiler.misc.wrong.number.type.args=\
+    wrong number of type arguments; required {0}
+
 # 0: message segment
 compiler.misc.no.conforming.assignment.exists=\
     argument mismatch; {0}
@@ -2766,10 +2770,6 @@
     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.definition.is.enum=\
     the service definition is an enum: {0}
 
@@ -2844,21 +2844,13 @@
 compiler.err.duplicate.module.on.path=\
     duplicate module on {0}\nmodule in {1}
 
-# 0:  string
-compiler.err.xaddexports.malformed.entry=\
-    bad value for --add-exports {0}
-
-# 0: string
-compiler.err.xaddexports.too.many=\
-    multiple --add-exports options for {0}
-
-# 0:  string
-compiler.err.xaddreads.malformed.entry=\
-    bad value for --add-reads {0}
-
-# 0: string
-compiler.err.xaddreads.too.many=\
-    multiple --add-reads options for {0}
+# 0: option name, 1: string
+compiler.warn.bad.name.for.option=\
+    bad name in value for {0} option: ''{1}''
+
+# 0: option name, 1: symbol
+compiler.warn.module.for.option.not.found=\
+    module name in {0} option not found: {1}
 
 compiler.err.addmods.all.module.path.invalid=\
     --add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module
@@ -2878,10 +2870,6 @@
 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}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -357,6 +357,10 @@
     not a file: {0}
 javac.err.cannot.access.runtime.env=\
     cannot access runtime environment
+javac.err.bad.value.for.option=\
+    bad value for {0} option: ''{1}''
+javac.err.no.value.for.option=\
+    no value for {0} option
 
 ## messages
 
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -48,6 +48,7 @@
 import com.sun.tools.javac.code.Type.CapturedType;
 import com.sun.tools.javac.file.PathFileObject;
 import com.sun.tools.javac.jvm.Profile;
+import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.tree.Pretty;
 
@@ -204,6 +205,9 @@
         else if (arg instanceof Profile) {
             return ((Profile)arg).name;
         }
+        else if (arg instanceof Option) {
+            return ((Option)arg).primaryName;
+        }
         else if (arg instanceof Formattable) {
             return ((Formattable)arg).toString(l, messages);
         }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Iterators.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,9 +62,9 @@
         }
 
         public O next() {
-            if (!hasNext())
+            if (currentIterator == EMPTY && !hasNext()) {
                 throw new NoSuchElementException();
-
+            }
             return currentIterator.next();
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocFormatter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,706 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.shellsupport.doc;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.Stack;
+
+import javax.lang.model.element.Name;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+import com.sun.source.doctree.AttributeTree;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.EndElementTree;
+import com.sun.source.doctree.EntityTree;
+import com.sun.source.doctree.InlineTagTree;
+import com.sun.source.doctree.LinkTree;
+import com.sun.source.doctree.LiteralTree;
+import com.sun.source.doctree.ParamTree;
+import com.sun.source.doctree.ReturnTree;
+import com.sun.source.doctree.StartElementTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.doctree.ThrowsTree;
+import com.sun.source.util.DocTreeScanner;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+import com.sun.tools.doclint.Entity;
+import com.sun.tools.doclint.HtmlTag;
+import com.sun.tools.javac.util.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.StringUtils;
+
+/**A javadoc to plain text formatter.
+ *
+ */
+public class JavadocFormatter {
+
+    private static final String CODE_RESET = "\033[0m";
+    private static final String CODE_HIGHLIGHT = "\033[1m";
+    private static final String CODE_UNDERLINE = "\033[4m";
+
+    private final int lineLimit;
+    private final boolean escapeSequencesSupported;
+
+    /** Construct the formatter.
+     *
+     * @param lineLimit maximum line length
+     * @param escapeSequencesSupported whether escape sequences are supported
+     */
+    public JavadocFormatter(int lineLimit, boolean escapeSequencesSupported) {
+        this.lineLimit = lineLimit;
+        this.escapeSequencesSupported = escapeSequencesSupported;
+    }
+
+    private static final int MAX_LINE_LENGTH = 95;
+    private static final int SHORTEST_LINE = 30;
+    private static final int INDENT = 4;
+
+    /**Format javadoc to plain text.
+     *
+     * @param header element caption that should be used
+     * @param javadoc to format
+     * @return javadoc formatted to plain text
+     */
+    public String formatJavadoc(String header, String javadoc) {
+        try {
+            StringBuilder result = new StringBuilder();
+
+            result.append(escape(CODE_HIGHLIGHT)).append(header).append(escape(CODE_RESET)).append("\n");
+
+            if (javadoc == null) {
+                return result.toString();
+            }
+
+            JavacTask task = (JavacTask) ToolProvider.getSystemJavaCompiler().getTask(null, null, null, null, null, null);
+            DocTrees trees = DocTrees.instance(task);
+            DocCommentTree docComment = trees.getDocCommentTree(new SimpleJavaFileObject(new URI("mem://doc.html"), Kind.HTML) {
+                @Override @DefinedBy(Api.COMPILER)
+                public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+                    return "<body>" + javadoc + "</body>";
+                }
+            });
+
+            new FormatJavadocScanner(result, task).scan(docComment, null);
+
+            addNewLineIfNeeded(result);
+
+            return result.toString();
+        } catch (URISyntaxException ex) {
+            throw new InternalError("Unexpected exception", ex);
+        }
+    }
+
+    private class FormatJavadocScanner extends DocTreeScanner<Object, Object> {
+        private final StringBuilder result;
+        private final JavacTask task;
+        private int reflownTo;
+        private int indent;
+        private int limit = Math.min(lineLimit, MAX_LINE_LENGTH);
+        private boolean pre;
+        private Map<StartElementTree, Integer> tableColumns;
+
+        public FormatJavadocScanner(StringBuilder result, JavacTask task) {
+            this.result = result;
+            this.task = task;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitDocComment(DocCommentTree node, Object p) {
+            tableColumns = countTableColumns(node);
+            reflownTo = result.length();
+            scan(node.getFirstSentence(), p);
+            scan(node.getBody(), p);
+            reflow(result, reflownTo, indent, limit);
+            for (Sections current : docSections.keySet()) {
+                boolean seenAny = false;
+                for (DocTree t : node.getBlockTags()) {
+                    if (current.matches(t)) {
+                        if (!seenAny) {
+                            seenAny = true;
+                            if (result.charAt(result.length() - 1) != '\n')
+                                result.append("\n");
+                            result.append("\n");
+                            result.append(escape(CODE_UNDERLINE))
+                                  .append(docSections.get(current))
+                                  .append(escape(CODE_RESET))
+                                  .append("\n");
+                        }
+
+                        scan(t, null);
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitText(TextTree node, Object p) {
+            String text = node.getBody();
+            if (!pre) {
+                text = text.replaceAll("[ \t\r\n]+", " ").trim();
+                if (text.isEmpty()) {
+                    text = " ";
+                }
+            } else {
+                text = text.replaceAll("\n", "\n" + indentString(indent));
+            }
+            result.append(text);
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitLink(LinkTree node, Object p) {
+            if (!node.getLabel().isEmpty()) {
+                scan(node.getLabel(), p);
+            } else {
+                result.append(node.getReference().getSignature());
+            }
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitParam(ParamTree node, Object p) {
+            return formatDef(node.getName().getName(), node.getDescription());
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitThrows(ThrowsTree node, Object p) {
+            return formatDef(node.getExceptionName().getSignature(), node.getDescription());
+        }
+
+        public Object formatDef(CharSequence name, List<? extends DocTree> description) {
+            result.append(name);
+            result.append(" - ");
+            reflownTo = result.length();
+            indent = name.length() + 3;
+
+            if (limit - indent < SHORTEST_LINE) {
+                result.append("\n");
+                result.append(indentString(INDENT));
+                indent = INDENT;
+                reflownTo += INDENT;
+            }
+            try {
+                return scan(description, null);
+            } finally {
+                reflow(result, reflownTo, indent, limit);
+                result.append("\n");
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitLiteral(LiteralTree node, Object p) {
+            return scan(node.getBody(), p);
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitReturn(ReturnTree node, Object p) {
+            reflownTo = result.length();
+            try {
+                return super.visitReturn(node, p);
+            } finally {
+                reflow(result, reflownTo, 0, limit);
+            }
+        }
+
+        Stack<Integer> listStack = new Stack<>();
+        Stack<Integer> defStack = new Stack<>();
+        Stack<Integer> tableStack = new Stack<>();
+        Stack<List<Integer>> cellsStack = new Stack<>();
+        Stack<List<Boolean>> headerStack = new Stack<>();
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitStartElement(StartElementTree node, Object p) {
+            switch (HtmlTag.get(node.getName())) {
+                case P:
+                    if (lastNode!= null && lastNode.getKind() == DocTree.Kind.START_ELEMENT &&
+                        HtmlTag.get(((StartElementTree) lastNode).getName()) == HtmlTag.LI) {
+                        //ignore
+                        break;
+                    }
+                    reflowTillNow();
+                    addNewLineIfNeeded(result);
+                    result.append(indentString(indent));
+                    reflownTo = result.length();
+                    break;
+                case BLOCKQUOTE:
+                    reflowTillNow();
+                    indent += INDENT;
+                    break;
+                case PRE:
+                    reflowTillNow();
+                    pre = true;
+                    break;
+                case UL:
+                    reflowTillNow();
+                    listStack.push(-1);
+                    indent += INDENT;
+                    break;
+                case OL:
+                    reflowTillNow();
+                    listStack.push(1);
+                    indent += INDENT;
+                    break;
+                case DL:
+                    reflowTillNow();
+                    defStack.push(indent);
+                    break;
+                case LI:
+                    reflowTillNow();
+                    if (!listStack.empty()) {
+                        addNewLineIfNeeded(result);
+
+                        int top = listStack.pop();
+
+                        if (top == (-1)) {
+                            result.append(indentString(indent - 2));
+                            result.append("* ");
+                        } else {
+                            result.append(indentString(indent - 3));
+                            result.append("" + top++ + ". ");
+                        }
+
+                        listStack.push(top);
+
+                        reflownTo = result.length();
+                    }
+                    break;
+                case DT:
+                    reflowTillNow();
+                    if (!defStack.isEmpty()) {
+                        addNewLineIfNeeded(result);
+                        indent = defStack.peek();
+                        result.append(escape(CODE_HIGHLIGHT));
+                    }
+                    break;
+                case DD:
+                    reflowTillNow();
+                    if (!defStack.isEmpty()) {
+                        if (indent == defStack.peek()) {
+                            result.append(escape(CODE_RESET));
+                        }
+                        addNewLineIfNeeded(result);
+                        indent = defStack.peek() + INDENT;
+                        result.append(indentString(indent));
+                    }
+                    break;
+                case H1: case H2: case H3:
+                case H4: case H5: case H6:
+                    reflowTillNow();
+                    addNewLineIfNeeded(result);
+                    result.append("\n")
+                          .append(escape(CODE_UNDERLINE));
+                    reflownTo = result.length();
+                    break;
+                case TABLE:
+                    int columns = tableColumns.get(node);
+
+                    if (columns == 0) {
+                        break; //broken input
+                    }
+
+                    reflowTillNow();
+                    addNewLineIfNeeded(result);
+                    reflownTo = result.length();
+
+                    tableStack.push(limit);
+
+                    limit = (limit - 1) / columns - 3;
+
+                    for (int sep = 0; sep < (limit + 3) * columns + 1; sep++) {
+                        result.append("-");
+                    }
+
+                    result.append("\n");
+
+                    break;
+                case TR:
+                    if (cellsStack.size() >= tableStack.size()) {
+                        //unclosed <tr>:
+                        handleEndElement(node.getName());
+                    }
+                    cellsStack.push(new ArrayList<>());
+                    headerStack.push(new ArrayList<>());
+                    break;
+                case TH:
+                case TD:
+                    if (cellsStack.isEmpty()) {
+                        //broken code
+                        break;
+                    }
+                    reflowTillNow();
+                    result.append("\n");
+                    reflownTo = result.length();
+                    cellsStack.peek().add(result.length());
+                    headerStack.peek().add(HtmlTag.get(node.getName()) == HtmlTag.TH);
+                    break;
+                case IMG:
+                    for (DocTree attr : node.getAttributes()) {
+                        if (attr.getKind() != DocTree.Kind.ATTRIBUTE) {
+                            continue;
+                        }
+                        AttributeTree at = (AttributeTree) attr;
+                        if ("alt".equals(StringUtils.toLowerCase(at.getName().toString()))) {
+                            addSpaceIfNeeded(result);
+                            scan(at.getValue(), null);
+                            addSpaceIfNeeded(result);
+                            break;
+                        }
+                    }
+                    break;
+                default:
+                    addSpaceIfNeeded(result);
+                    break;
+            }
+            return null;
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitEndElement(EndElementTree node, Object p) {
+            handleEndElement(node.getName());
+            return super.visitEndElement(node, p);
+        }
+
+        private void handleEndElement(Name name) {
+            switch (HtmlTag.get(name)) {
+                case BLOCKQUOTE:
+                    indent -= INDENT;
+                    break;
+                case PRE:
+                    pre = false;
+                    addNewLineIfNeeded(result);
+                    reflownTo = result.length();
+                    break;
+                case UL: case OL:
+                    if (listStack.isEmpty()) { //ignore stray closing tag
+                        break;
+                    }
+                    reflowTillNow();
+                    listStack.pop();
+                    indent -= INDENT;
+                    addNewLineIfNeeded(result);
+                    break;
+                case DL:
+                    if (defStack.isEmpty()) {//ignore stray closing tag
+                        break;
+                    }
+                    reflowTillNow();
+                    if (indent == defStack.peek()) {
+                        result.append(escape(CODE_RESET));
+                    }
+                    indent = defStack.pop();
+                    addNewLineIfNeeded(result);
+                    break;
+                case H1: case H2: case H3:
+                case H4: case H5: case H6:
+                    reflowTillNow();
+                    result.append(escape(CODE_RESET))
+                          .append("\n");
+                    reflownTo = result.length();
+                    break;
+                case TABLE:
+                    if (cellsStack.size() >= tableStack.size()) {
+                        //unclosed <tr>:
+                        handleEndElement(task.getElements().getName("tr"));
+                    }
+
+                    if (tableStack.isEmpty()) {
+                        break;
+                    }
+
+                    limit = tableStack.pop();
+                    break;
+                case TR:
+                    if (cellsStack.isEmpty()) {
+                        break;
+                    }
+
+                    reflowTillNow();
+
+                    List<Integer> cells = cellsStack.pop();
+                    List<Boolean> headerFlags = headerStack.pop();
+                    List<String[]> content = new ArrayList<>();
+                    int maxLines = 0;
+
+                    result.append("\n");
+
+                    while (!cells.isEmpty()) {
+                        int currentCell = cells.remove(cells.size() - 1);
+                        String[] lines = result.substring(currentCell, result.length()).split("\n");
+
+                        result.delete(currentCell - 1, result.length());
+
+                        content.add(lines);
+                        maxLines = Math.max(maxLines, lines.length);
+                    }
+
+                    Collections.reverse(content);
+
+                    for (int line = 0; line < maxLines; line++) {
+                        for (int column = 0; column < content.size(); column++) {
+                            String[] lines = content.get(column);
+                            String currentLine = line < lines.length ? lines[line] : "";
+                            result.append("| ");
+                            boolean header = headerFlags.get(column);
+                            if (header) {
+                                result.append(escape(CODE_HIGHLIGHT));
+                            }
+                            result.append(currentLine);
+                            if (header) {
+                                result.append(escape(CODE_RESET));
+                            }
+                            int padding = limit - currentLine.length();
+                            if (padding > 0)
+                                result.append(indentString(padding));
+                            result.append(" ");
+                        }
+                        result.append("|\n");
+                    }
+
+                    for (int sep = 0; sep < (limit + 3) * content.size() + 1; sep++) {
+                        result.append("-");
+                    }
+
+                    result.append("\n");
+
+                    reflownTo = result.length();
+                    break;
+                case TD:
+                case TH:
+                    break;
+                default:
+                    addSpaceIfNeeded(result);
+                    break;
+            }
+        }
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object visitEntity(EntityTree node, Object p) {
+            String name = node.getName().toString();
+            int code = -1;
+            if (name.startsWith("#")) {
+                try {
+                    int v = StringUtils.toLowerCase(name).startsWith("#x")
+                            ? Integer.parseInt(name.substring(2), 16)
+                            : Integer.parseInt(name.substring(1), 10);
+                    if (Entity.isValid(v)) {
+                        code = v;
+                    }
+                } catch (NumberFormatException ex) {
+                    //ignore
+                }
+            } else {
+                Entity entity = Entity.get(name);
+                if (entity != null) {
+                    code = entity.code;
+                }
+            }
+            if (code != (-1)) {
+                result.appendCodePoint(code);
+            } else {
+                result.append(node.toString());
+            }
+            return super.visitEntity(node, p);
+        }
+
+        private DocTree lastNode;
+
+        @Override @DefinedBy(Api.COMPILER_TREE)
+        public Object scan(DocTree node, Object p) {
+            if (node instanceof InlineTagTree) {
+                addSpaceIfNeeded(result);
+            }
+            try {
+                return super.scan(node, p);
+            } finally {
+                if (node instanceof InlineTagTree) {
+                    addSpaceIfNeeded(result);
+                }
+                lastNode = node;
+            }
+        }
+
+        private void reflowTillNow() {
+            while (result.length() > 0 && result.charAt(result.length() - 1) == ' ')
+                result.delete(result.length() - 1, result.length());
+            reflow(result, reflownTo, indent, limit);
+            reflownTo = result.length();
+        }
+    };
+
+    private String escape(String sequence) {
+        return this.escapeSequencesSupported ? sequence : "";
+    }
+
+    private static final Map<Sections, String> docSections = new LinkedHashMap<>();
+
+    static {
+        ResourceBundle bundle =
+                ResourceBundle.getBundle("jdk.internal.shellsupport.doc.resources.javadocformatter");
+        docSections.put(Sections.TYPE_PARAMS, bundle.getString("CAP_TypeParameters"));
+        docSections.put(Sections.PARAMS, bundle.getString("CAP_Parameters"));
+        docSections.put(Sections.RETURNS, bundle.getString("CAP_Returns"));
+        docSections.put(Sections.THROWS, bundle.getString("CAP_Thrown_Exceptions"));
+    }
+
+    private static String indentString(int indent) {
+        char[] content = new char[indent];
+        Arrays.fill(content, ' ');
+        return new String(content);
+    }
+
+    private static void reflow(StringBuilder text, int from, int indent, int limit) {
+        int lineStart = from;
+
+        while (lineStart > 0 && text.charAt(lineStart - 1) != '\n') {
+            lineStart--;
+        }
+
+        int lineChars = from - lineStart;
+        int pointer = from;
+        int lastSpace = -1;
+
+        while (pointer < text.length()) {
+            if (text.charAt(pointer) == ' ')
+                lastSpace = pointer;
+            if (lineChars >= limit) {
+                if (lastSpace != (-1)) {
+                    text.setCharAt(lastSpace, '\n');
+                    text.insert(lastSpace + 1, indentString(indent));
+                    lineChars = indent + pointer - lastSpace - 1;
+                    pointer += indent;
+                    lastSpace = -1;
+                }
+            }
+            lineChars++;
+            pointer++;
+        }
+    }
+
+    private static void addNewLineIfNeeded(StringBuilder text) {
+        if (text.length() > 0 && text.charAt(text.length() - 1) != '\n') {
+            text.append("\n");
+        }
+    }
+
+    private static void addSpaceIfNeeded(StringBuilder text) {
+        if (text.length() == 0)
+            return ;
+
+        char last = text.charAt(text.length() - 1);
+
+        if (last != ' ' && last != '\n') {
+            text.append(" ");
+        }
+    }
+
+    private static Map<StartElementTree, Integer> countTableColumns(DocCommentTree dct) {
+        Map<StartElementTree, Integer> result = new IdentityHashMap<>();
+
+        new DocTreeScanner<Void, Void>() {
+            private StartElementTree currentTable;
+            private int currentMaxColumns;
+            private int currentRowColumns;
+
+            @Override @DefinedBy(Api.COMPILER_TREE)
+            public Void visitStartElement(StartElementTree node, Void p) {
+                switch (HtmlTag.get(node.getName())) {
+                    case TABLE: currentTable = node; break;
+                    case TR:
+                        currentMaxColumns = Math.max(currentMaxColumns, currentRowColumns);
+                        currentRowColumns = 0;
+                        break;
+                    case TD:
+                    case TH: currentRowColumns++; break;
+                }
+                return super.visitStartElement(node, p);
+            }
+
+            @Override @DefinedBy(Api.COMPILER_TREE)
+            public Void visitEndElement(EndElementTree node, Void p) {
+                if (HtmlTag.get(node.getName()) == HtmlTag.TABLE) {
+                    closeTable();
+                }
+                return super.visitEndElement(node, p);
+            }
+
+            @Override @DefinedBy(Api.COMPILER_TREE)
+            public Void visitDocComment(DocCommentTree node, Void p) {
+                try {
+                    return super.visitDocComment(node, p);
+                } finally {
+                    closeTable();
+                }
+            }
+
+            private void closeTable() {
+                if (currentTable != null) {
+                    result.put(currentTable, Math.max(currentMaxColumns, currentRowColumns));
+                    currentTable = null;
+                }
+            }
+        }.scan(dct, null);
+
+        return result;
+    }
+
+    private enum Sections {
+        TYPE_PARAMS {
+            @Override public boolean matches(DocTree t) {
+                return t.getKind() == DocTree.Kind.PARAM && ((ParamTree) t).isTypeParameter();
+            }
+        },
+        PARAMS {
+            @Override public boolean matches(DocTree t) {
+                return t.getKind() == DocTree.Kind.PARAM && !((ParamTree) t).isTypeParameter();
+            }
+        },
+        RETURNS {
+            @Override public boolean matches(DocTree t) {
+                return t.getKind() == DocTree.Kind.RETURN;
+            }
+        },
+        THROWS {
+            @Override public boolean matches(DocTree t) {
+                return t.getKind() == DocTree.Kind.THROWS;
+            }
+        };
+
+        public abstract boolean matches(DocTree t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/JavadocHelper.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,661 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.shellsupport.doc;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+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.TreeMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.InheritDocTree;
+import com.sun.source.doctree.ParamTree;
+import com.sun.source.doctree.ReturnTree;
+import com.sun.source.doctree.ThrowsTree;
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.DocTreePath;
+import com.sun.source.util.DocTreeScanner;
+import com.sun.source.util.DocTrees;
+import com.sun.source.util.JavacTask;
+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.DefinedBy;
+import com.sun.tools.javac.util.DefinedBy.Api;
+import com.sun.tools.javac.util.Pair;
+
+/**Helper to find javadoc and resolve @inheritDoc.
+ */
+public abstract class JavadocHelper implements AutoCloseable {
+    private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+
+    /**Create the helper.
+     *
+     * @param mainTask JavacTask from which the further Elements originate
+     * @param sourceLocations paths where source files should be searched
+     * @return a JavadocHelper
+     */
+    public static JavadocHelper create(JavacTask mainTask, Collection<? extends Path> sourceLocations) {
+        StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
+        try {
+            fm.setLocationFromPaths(StandardLocation.SOURCE_PATH, sourceLocations);
+            return new OnDemandJavadocHelper(mainTask, fm);
+        } catch (IOException ex) {
+            try {
+                fm.close();
+            } catch (IOException closeEx) {
+            }
+            return new JavadocHelper() {
+                @Override
+                public String getResolvedDocComment(Element forElement) throws IOException {
+                    return null;
+                }
+                @Override
+                public Element getSourceElement(Element forElement) throws IOException {
+                    return forElement;
+                }
+                @Override
+                public void close() throws IOException {}
+            };
+        }
+    }
+
+    /**Returns javadoc for the given element, if it can be found, or null otherwise. The javadoc
+     * will have @inheritDoc resolved.
+     *
+     * @param forElement element for which the javadoc should be searched
+     * @return javadoc if found, null otherwise
+     * @throws IOException if something goes wrong in the search
+     */
+    public abstract String getResolvedDocComment(Element forElement) throws IOException;
+
+    /**Returns an element representing the same given program element, but the returned element will
+     * be resolved from source, if it can be found. Returns the original element if the source for
+     * the given element cannot be found.
+     *
+     * @param forElement element for which the source element should be searched
+     * @return source element if found, the original element otherwise
+     * @throws IOException if something goes wrong in the search
+     */
+    public abstract Element getSourceElement(Element forElement) throws IOException;
+
+    /**Closes the helper.
+     *
+     * @throws IOException if something foes wrong during the close
+     */
+    @Override
+    public abstract void close() throws IOException;
+
+    private static final class OnDemandJavadocHelper extends JavadocHelper {
+        private final JavacTask mainTask;
+        private final JavaFileManager baseFileManager;
+        private final StandardJavaFileManager fm;
+        private final Map<String, Pair<JavacTask, TreePath>> signature2Source = new HashMap<>();
+
+        private OnDemandJavadocHelper(JavacTask mainTask, StandardJavaFileManager fm) {
+            this.mainTask = mainTask;
+            this.baseFileManager = ((JavacTaskImpl) mainTask).getContext().get(JavaFileManager.class);
+            this.fm = fm;
+        }
+
+        @Override
+        public String getResolvedDocComment(Element forElement) throws IOException {
+            Pair<JavacTask, TreePath> sourceElement = getSourceElement(mainTask, forElement);
+
+            if (sourceElement == null)
+                return null;
+
+            return getResolvedDocComment(sourceElement.fst, sourceElement.snd);
+        }
+
+        @Override
+        public Element getSourceElement(Element forElement) throws IOException {
+            Pair<JavacTask, TreePath> sourceElement = getSourceElement(mainTask, forElement);
+
+            if (sourceElement == null)
+                return forElement;
+
+            Element result = Trees.instance(sourceElement.fst).getElement(sourceElement.snd);
+
+            if (result == null)
+                return forElement;
+
+            return result;
+        }
+
+        private String getResolvedDocComment(JavacTask task, TreePath el) throws IOException {
+            DocTrees trees = DocTrees.instance(task);
+            Element element = trees.getElement(el);
+            String docComment = trees.getDocComment(el);
+
+            if (docComment == null && element.getKind() == ElementKind.METHOD) {
+                ExecutableElement executableElement = (ExecutableElement) element;
+                Iterable<Element> superTypes =
+                        () -> superTypeForInheritDoc(task, element.getEnclosingElement()).iterator();
+                for (Element sup : superTypes) {
+                   for (ExecutableElement supMethod : ElementFilter.methodsIn(sup.getEnclosedElements())) {
+                       TypeElement clazz = (TypeElement) executableElement.getEnclosingElement();
+                       if (task.getElements().overrides(executableElement, supMethod, clazz)) {
+                           Pair<JavacTask, TreePath> source = getSourceElement(task, supMethod);
+
+                           if (source != null) {
+                               String overriddenComment = getResolvedDocComment(source.fst, source.snd);
+
+                               if (overriddenComment != null) {
+                                   return overriddenComment;
+                               }
+                           }
+                       }
+                   }
+                }
+            }
+
+            DocCommentTree docCommentTree = parseDocComment(task, docComment);
+            IOException[] exception = new IOException[1];
+            Map<int[], String> replace = new TreeMap<>((span1, span2) -> span2[0] - span1[0]);
+
+            new DocTreeScanner<Void, Void>() {
+                private Stack<DocTree> interestingParent = new Stack<>();
+                private DocCommentTree dcTree;
+                private JavacTask inheritedJavacTask;
+                private TreePath inheritedTreePath;
+                private String inherited;
+                private Map<DocTree, String> syntheticTrees = new IdentityHashMap<>();
+                private long lastPos = 0;
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitDocComment(DocCommentTree node, Void p) {
+                    dcTree = node;
+                    interestingParent.push(node);
+                    try {
+                        scan(node.getFirstSentence(), p);
+                        scan(node.getBody(), p);
+                        List<DocTree> augmentedBlockTags = new ArrayList<>(node.getBlockTags());
+                        if (element.getKind() == ElementKind.METHOD) {
+                            ExecutableElement executableElement = (ExecutableElement) element;
+                            List<String> parameters =
+                                    executableElement.getParameters()
+                                                     .stream()
+                                                     .map(param -> param.getSimpleName().toString())
+                                                     .collect(Collectors.toList());
+                            List<String> throwsList =
+                                    executableElement.getThrownTypes()
+                                                     .stream()
+                                                     .map(exc -> exc.toString())
+                                                     .collect(Collectors.toList());
+                            Set<String> missingParams = new HashSet<>(parameters);
+                            Set<String> missingThrows = new HashSet<>(throwsList);
+                            boolean hasReturn = false;
+
+                            for (DocTree dt : augmentedBlockTags) {
+                                switch (dt.getKind()) {
+                                    case PARAM:
+                                        missingParams.remove(((ParamTree) dt).getName().getName().toString());
+                                        break;
+                                    case THROWS:
+                                        missingThrows.remove(getThrownException(task, el, docCommentTree, (ThrowsTree) dt));
+                                        break;
+                                    case RETURN:
+                                        hasReturn = true;
+                                        break;
+                                }
+                            }
+
+                            for (String missingParam : missingParams) {
+                                DocTree syntheticTag = parseBlockTag(task, "@param " + missingParam + " {@inheritDoc}");
+                                syntheticTrees.put(syntheticTag, "@param " + missingParam + " ");
+                                insertTag(augmentedBlockTags, syntheticTag, parameters, throwsList);
+                            }
+
+                            for (String missingThrow : missingThrows) {
+                                DocTree syntheticTag = parseBlockTag(task, "@throws " + missingThrow + " {@inheritDoc}");
+                                syntheticTrees.put(syntheticTag, "@throws " + missingThrow + " ");
+                                insertTag(augmentedBlockTags, syntheticTag, parameters, throwsList);
+                            }
+
+                            if (!hasReturn) {
+                                DocTree syntheticTag = parseBlockTag(task, "@return {@inheritDoc}");
+                                syntheticTrees.put(syntheticTag, "@return ");
+                                insertTag(augmentedBlockTags, syntheticTag, parameters, throwsList);
+                            }
+                        }
+                        scan(augmentedBlockTags, p);
+                        return null;
+                    } finally {
+                        interestingParent.pop();
+                    }
+                }
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitParam(ParamTree node, Void p) {
+                    interestingParent.push(node);
+                    try {
+                        return super.visitParam(node, p);
+                    } finally {
+                        interestingParent.pop();
+                    }
+                }
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitThrows(ThrowsTree node, Void p) {
+                    interestingParent.push(node);
+                    try {
+                        return super.visitThrows(node, p);
+                    } finally {
+                        interestingParent.pop();
+                    }
+                }
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitReturn(ReturnTree node, Void p) {
+                    interestingParent.push(node);
+                    try {
+                        return super.visitReturn(node, p);
+                    } finally {
+                        interestingParent.pop();
+                    }
+                }
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void visitInheritDoc(InheritDocTree node, Void p) {
+                    if (inherited == null) {
+                        try {
+                            if (element.getKind() == ElementKind.METHOD) {
+                                ExecutableElement executableElement = (ExecutableElement) element;
+                                Iterable<Element> superTypes = () -> superTypeForInheritDoc(task, element.getEnclosingElement()).iterator();
+                                OUTER: for (Element sup : superTypes) {
+                                   for (ExecutableElement supMethod : ElementFilter.methodsIn(sup.getEnclosedElements())) {
+                                       if (task.getElements().overrides(executableElement, supMethod, (TypeElement) executableElement.getEnclosingElement())) {
+                                           Pair<JavacTask, TreePath> source = getSourceElement(task, supMethod);
+
+                                           if (source != null) {
+                                               String overriddenComment = getResolvedDocComment(source.fst, source.snd);
+
+                                               if (overriddenComment != null) {
+                                                   inheritedJavacTask = source.fst;
+                                                   inheritedTreePath = source.snd;
+                                                   inherited = overriddenComment;
+                                                   break OUTER;
+                                               }
+                                           }
+                                       }
+                                   }
+                                }
+                            }
+                        } catch (IOException ex) {
+                            exception[0] = ex;
+                            return null;
+                        }
+                    }
+                    if (inherited == null) {
+                        return null;
+                    }
+                    DocCommentTree inheritedDocTree = parseDocComment(inheritedJavacTask, inherited);
+                    List<List<? extends DocTree>> inheritedText = new ArrayList<>();
+                    DocTree parent = interestingParent.peek();
+                    switch (parent.getKind()) {
+                        case DOC_COMMENT:
+                            inheritedText.add(inheritedDocTree.getFullBody());
+                            break;
+                        case PARAM:
+                            String paramName = ((ParamTree) parent).getName().getName().toString();
+                            new DocTreeScanner<Void, Void>() {
+                                @Override @DefinedBy(Api.COMPILER_TREE)
+                                public Void visitParam(ParamTree node, Void p) {
+                                    if (node.getName().getName().contentEquals(paramName)) {
+                                        inheritedText.add(node.getDescription());
+                                    }
+                                    return super.visitParam(node, p);
+                                }
+                            }.scan(inheritedDocTree, null);
+                            break;
+                        case THROWS:
+                            String thrownName = getThrownException(task, el, docCommentTree, (ThrowsTree) parent);
+                            new DocTreeScanner<Void, Void>() {
+                                @Override @DefinedBy(Api.COMPILER_TREE)
+                                public Void visitThrows(ThrowsTree node, Void p) {
+                                    if (Objects.equals(getThrownException(inheritedJavacTask, inheritedTreePath, inheritedDocTree, node), thrownName)) {
+                                        inheritedText.add(node.getDescription());
+                                    }
+                                    return super.visitThrows(node, p);
+                                }
+                            }.scan(inheritedDocTree, null);
+                            break;
+                        case RETURN:
+                            new DocTreeScanner<Void, Void>() {
+                                @Override @DefinedBy(Api.COMPILER_TREE)
+                                public Void visitReturn(ReturnTree node, Void p) {
+                                    inheritedText.add(node.getDescription());
+                                    return super.visitReturn(node, p);
+                                }
+                            }.scan(inheritedDocTree, null);
+                            break;
+                    }
+                    if (!inheritedText.isEmpty()) {
+                        long offset = trees.getSourcePositions().getStartPosition(null, inheritedDocTree, inheritedDocTree);
+                        long start = Long.MAX_VALUE;
+                        long end = Long.MIN_VALUE;
+
+                        for (DocTree t : inheritedText.get(0)) {
+                            start = Math.min(start, trees.getSourcePositions().getStartPosition(null, inheritedDocTree, t) - offset);
+                            end   = Math.max(end,   trees.getSourcePositions().getEndPosition(null, inheritedDocTree, t) - offset);
+                        }
+                        String text = inherited.substring((int) start, (int) end);
+
+                        if (syntheticTrees.containsKey(parent)) {
+                            replace.put(new int[] {(int) lastPos + 1, (int) lastPos}, "\n" + syntheticTrees.get(parent) + text);
+                        } else {
+                            long inheritedStart = trees.getSourcePositions().getStartPosition(null, dcTree, node);
+                            long inheritedEnd   = trees.getSourcePositions().getEndPosition(null, dcTree, node);
+
+                            replace.put(new int[] {(int) inheritedStart, (int) inheritedEnd}, text);
+                        }
+                    }
+                    return super.visitInheritDoc(node, p);
+                }
+                private boolean inSynthetic;
+                @Override @DefinedBy(Api.COMPILER_TREE)
+                public Void scan(DocTree tree, Void p) {
+                    if (exception[0] != null) {
+                        return null;
+                    }
+                    boolean prevInSynthetic = inSynthetic;
+                    try {
+                        inSynthetic |= syntheticTrees.containsKey(tree);
+                        return super.scan(tree, p);
+                    } finally {
+                        if (!inSynthetic) {
+                            lastPos = trees.getSourcePositions().getEndPosition(null, dcTree, tree);
+                        }
+                        inSynthetic = prevInSynthetic;
+                    }
+                }
+
+                private void insertTag(List<DocTree> tags, DocTree toInsert, List<String> parameters, List<String> throwsTypes) {
+                    Comparator<DocTree> comp = (tag1, tag2) -> {
+                        if (tag1.getKind() == tag2.getKind()) {
+                            switch (toInsert.getKind()) {
+                                case PARAM: {
+                                    ParamTree p1 = (ParamTree) tag1;
+                                    ParamTree p2 = (ParamTree) tag2;
+                                    int i1 = parameters.indexOf(p1.getName().getName().toString());
+                                    int i2 = parameters.indexOf(p2.getName().getName().toString());
+
+                                    return i1 - i2;
+                                }
+                                case THROWS: {
+                                    ThrowsTree t1 = (ThrowsTree) tag1;
+                                    ThrowsTree t2 = (ThrowsTree) tag2;
+                                    int i1 = throwsTypes.indexOf(getThrownException(task, el, docCommentTree, t1));
+                                    int i2 = throwsTypes.indexOf(getThrownException(task, el, docCommentTree, t2));
+
+                                    return i1 - i2;
+                                }
+                            }
+                        }
+
+                        int i1 = tagOrder.indexOf(tag1.getKind());
+                        int i2 = tagOrder.indexOf(tag2.getKind());
+
+                        return i1 - i2;
+                    };
+
+                    for (int i = 0; i < tags.size(); i++) {
+                        if (comp.compare(tags.get(i), toInsert) >= 0) {
+                            tags.add(i, toInsert);
+                            return ;
+                        }
+                    }
+                    tags.add(toInsert);
+                }
+
+                private final List<DocTree.Kind> tagOrder = Arrays.asList(DocTree.Kind.PARAM, DocTree.Kind.THROWS, DocTree.Kind.RETURN);
+            }.scan(docCommentTree, null);
+
+            if (replace.isEmpty())
+                return docComment;
+
+            StringBuilder replacedInheritDoc = new StringBuilder(docComment);
+            int offset = (int) trees.getSourcePositions().getStartPosition(null, docCommentTree, docCommentTree);
+
+            for (Entry<int[], String> e : replace.entrySet()) {
+                replacedInheritDoc.delete(e.getKey()[0] - offset, e.getKey()[1] - offset + 1);
+                replacedInheritDoc.insert(e.getKey()[0] - offset, e.getValue());
+            }
+
+            return replacedInheritDoc.toString();
+        }
+
+        private Stream<Element> superTypeForInheritDoc(JavacTask task, Element type) {
+            TypeElement clazz = (TypeElement) type;
+            Stream<Element> result = interfaces(clazz);
+            result = Stream.concat(result, interfaces(clazz).flatMap(el -> superTypeForInheritDoc(task, el)));
+
+            if (clazz.getSuperclass().getKind() == TypeKind.DECLARED) {
+                Element superClass = ((DeclaredType) clazz.getSuperclass()).asElement();
+                result = Stream.concat(result, Stream.of(superClass));
+                result = Stream.concat(result, superTypeForInheritDoc(task, superClass));
+            }
+
+            return result;
+        }
+        //where:
+            private Stream<Element> interfaces(TypeElement clazz) {
+                return clazz.getInterfaces()
+                            .stream()
+                            .filter(tm -> tm.getKind() == TypeKind.DECLARED)
+                            .map(tm -> ((DeclaredType) tm).asElement());
+            }
+
+         private DocTree parseBlockTag(JavacTask task, String blockTag) {
+            DocCommentTree dc = parseDocComment(task, blockTag);
+
+            return dc.getBlockTags().get(0);
+        }
+
+        private DocCommentTree parseDocComment(JavacTask task, String javadoc) {
+            DocTrees trees = DocTrees.instance(task);
+            try {
+                return trees.getDocCommentTree(new SimpleJavaFileObject(new URI("mem://doc.html"), javax.tools.JavaFileObject.Kind.HTML) {
+                    @Override @DefinedBy(Api.COMPILER)
+                    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+                        return "<body>" + javadoc + "</body>";
+                    }
+                });
+            } catch (URISyntaxException ex) {
+                return null;
+            }
+        }
+
+        private String getThrownException(JavacTask task, TreePath rootOn, DocCommentTree comment, ThrowsTree tt) {
+            DocTrees trees = DocTrees.instance(task);
+            Element exc = trees.getElement(new DocTreePath(new DocTreePath(rootOn, comment), tt.getExceptionName()));
+            return exc != null ? exc.toString() : null;
+        }
+
+        private Pair<JavacTask, TreePath> getSourceElement(JavacTask origin, Element el) throws IOException {
+            String handle = elementSignature(el);
+            Pair<JavacTask, TreePath> cached = signature2Source.get(handle);
+
+            if (cached != null) {
+                return cached.fst != null ? cached : null;
+            }
+
+            TypeElement type = topLevelType(el);
+
+            if (type == null)
+                return null;
+
+            String binaryName = origin.getElements().getBinaryName(type).toString();
+            Pair<JavacTask, CompilationUnitTree> source = findSource(binaryName);
+
+            if (source == null)
+                return null;
+
+            fillElementCache(source.fst, source.snd);
+
+            cached = signature2Source.get(handle);
+
+            if (cached != null) {
+                return cached;
+            } else {
+                signature2Source.put(handle, Pair.of(null, null));
+                return null;
+            }
+        }
+        //where:
+            private String elementSignature(Element el) {
+                switch (el.getKind()) {
+                    case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE:
+                        return ((TypeElement) el).getQualifiedName().toString();
+                    case FIELD:
+                        return elementSignature(el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType();
+                    case ENUM_CONSTANT:
+                        return elementSignature(el.getEnclosingElement()) + "." + el.getSimpleName();
+                    case EXCEPTION_PARAMETER: case LOCAL_VARIABLE: case PARAMETER: case RESOURCE_VARIABLE:
+                        return el.getSimpleName() + ":" + el.asType();
+                    case CONSTRUCTOR: case METHOD:
+                        StringBuilder header = new StringBuilder();
+                        header.append(elementSignature(el.getEnclosingElement()));
+                        if (el.getKind() == ElementKind.METHOD) {
+                            header.append(".");
+                            header.append(el.getSimpleName());
+                        }
+                        header.append("(");
+                        String sep = "";
+                        ExecutableElement method = (ExecutableElement) el;
+                        for (Iterator<? extends VariableElement> i = method.getParameters().iterator(); i.hasNext();) {
+                            VariableElement p = i.next();
+                            header.append(sep);
+                            header.append(p.asType());
+                            sep = ", ";
+                        }
+                        header.append(")");
+                        return header.toString();
+                   default:
+                        return el.toString();
+                }
+            }
+
+            private TypeElement topLevelType(Element el) {
+                if (el.getKind() == ElementKind.PACKAGE)
+                    return null;
+
+                while (el != null && el.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
+                    el = el.getEnclosingElement();
+                }
+
+                return el != null && (el.getKind().isClass() || el.getKind().isInterface()) ? (TypeElement) el : null;
+            }
+
+            private void fillElementCache(JavacTask task, CompilationUnitTree cut) throws IOException {
+                Trees trees = Trees.instance(task);
+
+                new TreePathScanner<Void, Void>() {
+                    @Override @DefinedBy(Api.COMPILER_TREE)
+                    public Void visitMethod(MethodTree node, Void p) {
+                        handleDeclaration();
+                        return null;
+                    }
+
+                    @Override @DefinedBy(Api.COMPILER_TREE)
+                    public Void visitClass(ClassTree node, Void p) {
+                        handleDeclaration();
+                        return super.visitClass(node, p);
+                    }
+
+                    @Override @DefinedBy(Api.COMPILER_TREE)
+                    public Void visitVariable(VariableTree node, Void p) {
+                        handleDeclaration();
+                        return super.visitVariable(node, p);
+                    }
+
+                    private void handleDeclaration() {
+                        Element currentElement = trees.getElement(getCurrentPath());
+
+                        if (currentElement != null) {
+                            signature2Source.put(elementSignature(currentElement), Pair.of(task, getCurrentPath()));
+                        }
+                    }
+                }.scan(cut, null);
+            }
+
+        private Pair<JavacTask, CompilationUnitTree> findSource(String binaryName) throws IOException {
+            JavaFileObject jfo = fm.getJavaFileForInput(StandardLocation.SOURCE_PATH,
+                                                        binaryName,
+                                                        JavaFileObject.Kind.SOURCE);
+
+            if (jfo == null)
+                return null;
+
+            List<JavaFileObject> jfos = Arrays.asList(jfo);
+            JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, baseFileManager, d -> {}, null, null, jfos);
+            Iterable<? extends CompilationUnitTree> cuts = task.parse();
+
+            task.enter();
+
+            return Pair.of(task, cuts.iterator().next());
+        }
+
+        @Override
+        public void close() throws IOException {
+            fm.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/jdk/internal/shellsupport/doc/resources/javadocformatter.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+CAP_TypeParameters=Type Parameters:
+CAP_Parameters=Parameters:
+CAP_Returns=Returns:
+CAP_Thrown_Exceptions=Thrown Exceptions:
--- a/langtools/src/jdk.compiler/share/classes/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.compiler/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -65,6 +65,9 @@
         jdk.jdeps,
         jdk.javadoc,
         jdk.jshell;
+    exports jdk.internal.shellsupport.doc to
+        jdk.jshell,
+        jdk.scripting.nashorn.shell;
 
     uses javax.annotation.processing.Processor;
     uses com.sun.source.util.Plugin;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Main.java	Fri Nov 11 16:44:36 2016 +0100
@@ -638,6 +638,8 @@
 
         // now the scanning phase
 
+        boolean scanStatus = true;
+
         switch (scanMode) {
             case LIST:
                 for (DeprData dd : deprList) {
@@ -661,24 +663,22 @@
                 Scan scan = new Scan(out, err, cp, db, verbose);
 
                 for (String a : args) {
-                    boolean success;
-
+                    boolean s;
                     if (a.endsWith(".jar")) {
-                        success = scan.scanJar(a);
+                        s = scan.scanJar(a);
+                    } else if (a.endsWith(".class")) {
+                        s = scan.processClassFile(a);
                     } else if (Files.isDirectory(Paths.get(a))) {
-                        success = scan.scanDir(a);
+                        s = scan.scanDir(a);
                     } else {
-                        success = scan.processClassName(a.replace('.', '/'));
+                        s = scan.processClassName(a.replace('.', '/'));
                     }
-
-                    if (!success) {
-                        return false;
-                    }
+                    scanStatus = scanStatus && s;
                 }
                 break;
         }
 
-        return true;
+        return scanStatus;
     }
 
     /**
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Messages.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/Messages.java	Fri Nov 11 16:44:36 2016 +0100
@@ -34,6 +34,10 @@
  * Message handling class for localization.
  */
 public class Messages {
+    /** Indicates whether line separators in messages need replacement. */
+    static final boolean REPLACE_LINESEP = ! System.lineSeparator().equals("\n");
+
+    /** The resource bundle, must be non-null. */
     static final ResourceBundle bundle;
 
     static {
@@ -41,13 +45,25 @@
         try {
             bundle = ResourceBundle.getBundle("com.sun.tools.jdeprscan.resources.jdeprscan", locale);
         } catch (MissingResourceException e) {
-            throw new InternalError("Cannot find jdeps resource bundle for locale " + locale, e);
+            throw new InternalError("Cannot find jdeprscan resource bundle for locale " + locale, e);
         }
     }
 
+    /**
+     * Gets a message from the resource bundle. If necessary, translates "\n",
+     * the line break string used in the message file, to the system-specific
+     * line break string.
+     *
+     * @param key the message key
+     * @param args the message arguments
+     */
     public static String get(String key, Object... args) {
         try {
-            return MessageFormat.format(bundle.getString(key), args);
+            String msg = MessageFormat.format(bundle.getString(key), args);
+            if (REPLACE_LINESEP) {
+                msg = msg.replace("\n", System.lineSeparator());
+            }
+            return msg;
         } catch (MissingResourceException e) {
             throw new InternalError("Missing message: " + key, e);
         }
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/readme.md	Fri Nov 11 16:44:36 2016 +0100
@@ -92,6 +92,9 @@
 that jar file and report information about how those classes use
 deprecated APIs.
 
+Given a class file, **jdeprscan** will scan that class and report
+its use of deprecated APIs.
+
 Given a class name, **jdeprscan** will search for that class on the
 classpath, scan that class, and report information about how that
 class uses deprecated APIs. The class name must use the fully
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/resources/jdeprscan.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -14,9 +14,9 @@
 main.help=\
 Scans each argument for usages of deprecated APIs. An argument\n\
 may be a directory specifying the root of a package hierarchy,\n\
-a JAR file, or a class name. The class name must be specified\n\
-using a fully qualified class name using the $ separator character\n\
-for nested classes, for example,\n\
+a JAR file, a class file, or a class name. The class name must be\n\
+specified using a fully qualified class name using the $ separator\n\
+character for nested classes, for example,\n\
 \n\
 \    java.lang.Thread$State\n\
 \n\
@@ -73,24 +73,26 @@
 \      Prints a CSV file containing the loaded deprecation information\n\
 \      instead of scanning any classes or JAR files.
 
-error.prefix=Error:
-
 scan.process.class=Processing class {0}...
 
-scan.dep.normal=deprecated
-scan.dep.removal=deprecated FOR REMOVAL
+scan.dep.normal=
+scan.dep.removal=(forRemoval=true)
+
+scan.err.exception=error: unexpected exception {0}
+scan.err.noclass=error: cannot find class {0}
+scan.err.nofile=error: cannot find file {0}
+scan.err.nomethod=error: cannot resolve Methodref {0}.{1}:{2}
+
+scan.head.jar=Jar file {0}:
+scan.head.dir=Directory {0}:
 
-scan.out.extends={0} {1} extends class {2} {3}
-scan.out.implements={0} {1} implements interface {2} {3}
-scan.out.usestype={0} {1} uses type {2} {3}
-scan.out.usesmethodintype={0} {1} uses method in type {2} {3}
-scan.out.usesmethod={0} {1} uses method {2} {3} {4} {5}
-scan.out.usesintfmethodintype={0} {1} uses interface method in type {2} {3}
-scan.out.usesintfmethod={0} {1} uses interface method {2} {3} {4} {5}
-scan.out.usesfieldintype={0} {1} uses field in type {2} {3}
-scan.out.usesfield={0} {1} uses field {2} {3} {4}
-scan.out.usesfieldoftype={0} {1} uses field of type {2} {3} {4} {5}
-scan.out.hasfield={0} {1} has field {2} of type {3} {4}
-scan.out.methodparmtype={0} {1} method {2} has parameter type {3} {4}
-scan.out.methodrettype={0} {1} method {2} has return type {3} {4}
-scan.out.methodoverride={0} {1} overrides method {2} {3} {4} {5}
+scan.out.extends={0} {1} extends deprecated class {2} {3}
+scan.out.implements={0} {1} implements deprecated interface {2} {3}
+scan.out.usesclass={0} {1} uses deprecated class {2} {3}
+scan.out.usesmethod={0} {1} uses deprecated method {2}::{3}{4} {5}
+scan.out.usesintfmethod={0} {1} uses deprecated method {2}::{3}{4} {5}
+scan.out.usesfield={0} {1} uses deprecated field {2}::{3} {4}
+scan.out.hasfield={0} {1} has field named {2} of deprecated type {3} {4}
+scan.out.methodparmtype={0} {1} has method named {2} having deprecated parameter type {3} {4}
+scan.out.methodrettype={0} {1} has method named {2} having deprecated return type {3} {4}
+scan.out.methodoverride={0} {1} overrides deprecated method {2}::{3}{4} {5}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/Scan.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/Scan.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,7 @@
 import java.io.IOException;
 import java.io.PrintStream;
 import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayDeque;
@@ -62,7 +63,7 @@
     final boolean verbose;
 
     final ClassFinder finder;
-    boolean error = false;
+    boolean errorOccurred = false;
 
     public Scan(PrintStream out,
                 PrintStream err,
@@ -124,71 +125,72 @@
         }
     }
 
-    void printType(String key, ClassFile cf, String cname, boolean forRemoval)
+    String dep(boolean forRemoval) {
+        return Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
+    }
+
+    void printType(String key, ClassFile cf, String cname, boolean r)
             throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, dep));
+        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, dep(r)));
     }
 
     void printMethod(String key, ClassFile cf, String cname, String mname, String rtype,
-                     boolean forRemoval) throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, mname, rtype, dep));
+                     boolean r) throws ConstantPoolException {
+        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, mname, rtype, dep(r)));
     }
 
     void printField(String key, ClassFile cf, String cname, String fname,
-                     boolean forRemoval) throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, dep));
+                     boolean r) throws ConstantPoolException {
+        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, dep(r)));
     }
 
     void printFieldType(String key, ClassFile cf, String cname, String fname, String type,
-                     boolean forRemoval) throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, type, dep));
+                     boolean r) throws ConstantPoolException {
+        out.println(Messages.get(key, typeKind(cf), cf.getName(), cname, fname, type, dep(r)));
     }
 
-    void printHasField(ClassFile cf, String fname, String type, boolean forRemoval)
+    void printHasField(ClassFile cf, String fname, String type, boolean r)
             throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get("scan.out.hasfield", typeKind(cf), cf.getName(), fname, type, dep));
+        out.println(Messages.get("scan.out.hasfield", typeKind(cf), cf.getName(), fname, type, dep(r)));
     }
 
-    void printHasMethodParmType(ClassFile cf, String mname, String parmType, boolean forRemoval)
+    void printHasMethodParmType(ClassFile cf, String mname, String parmType, boolean r)
             throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get("scan.out.methodparmtype", typeKind(cf), cf.getName(), mname, parmType, dep));
+        out.println(Messages.get("scan.out.methodparmtype", typeKind(cf), cf.getName(), mname, parmType, dep(r)));
     }
 
-    void printHasMethodRetType(ClassFile cf, String mname, String retType, boolean forRemoval)
+    void printHasMethodRetType(ClassFile cf, String mname, String retType, boolean r)
             throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
-        out.println(Messages.get("scan.out.methodrettype", typeKind(cf), cf.getName(), mname, retType, dep));
+        out.println(Messages.get("scan.out.methodrettype", typeKind(cf), cf.getName(), mname, retType, dep(r)));
     }
 
-    void printHasOverriddenMethod(ClassFile cf, String overridden, String mname, String desc, boolean forRemoval)
+    void printHasOverriddenMethod(ClassFile cf, String overridden, String mname, String desc, boolean r)
             throws ConstantPoolException {
-        String dep = Messages.get(forRemoval ? "scan.dep.removal" : "scan.dep.normal");
         out.println(Messages.get("scan.out.methodoverride", typeKind(cf), cf.getName(), overridden,
-                                 mname, desc, dep));
+                                 mname, desc, dep(r)));
+    }
+
+    void errorException(Exception ex) {
+        errorOccurred = true;
+        err.println(Messages.get("scan.err.exception", ex.toString()));
+        if (verbose) {
+            ex.printStackTrace(err);
+        }
     }
 
-    // format should not have a newline
-    void err(String format, Object... args) {
-        error = true;
-        err.print("error: ");
-        err.printf(format, args);
-        err.println();
+    void errorNoClass(String className) {
+        errorOccurred = true;
+        err.println(Messages.get("scan.err.noclass", className));
     }
 
-    void printException(Exception ex) {
-        err.print(Messages.get("error.prefix"));
-        err.print(" ");
-        if (verbose) {
-            ex.printStackTrace(err);
-        } else {
-            err.print(ex);
-        }
+    void errorNoFile(String fileName) {
+        errorOccurred = true;
+        err.println(Messages.get("scan.err.nofile", fileName));
+    }
+
+    void errorNoMethod(String className, String methodName, String desc) {
+        errorOccurred = true;
+        err.println(Messages.get("scan.err.nomethod", className, methodName, desc));
     }
 
     /**
@@ -271,7 +273,7 @@
         } else {
             startClass = finder.find(startClassName);
             if (startClass == null) {
-                err("can't find class %s", startClassName);
+                errorNoClass(startClassName);
                 return startClassName;
             }
         }
@@ -295,7 +297,7 @@
             String superName = curClass.getSuperclassName();
             curClass = finder.find(superName);
             if (curClass == null) {
-                err("can't find class %s", superName);
+                errorNoClass(superName);
                 break;
             }
             addInterfaces(intfs, curClass);
@@ -310,7 +312,7 @@
                 String intf = intfs.removeFirst();
                 curClass = finder.find(intf);
                 if (curClass == null) {
-                    err("can't find interface %s", intf);
+                    errorNoClass(intf);
                     break;
                 }
 
@@ -324,8 +326,7 @@
 
         if (curClass == null) {
             if (checkStartClass) {
-                err("can't resolve methodref %s %s %s",
-                    startClassName, findName, findDesc);
+                errorNoMethod(startClassName, findName, findDesc);
                 return startClassName;
             } else {
                 // TODO: refactor this
@@ -372,18 +373,18 @@
     }
 
     /**
-     * Checks types referred to from the constant pool.
+     * Checks Class_info entries in the constant pool.
      *
      * @param cf the ClassFile of this class
      * @param entries constant pool entries collected from this class
      * @throws ConstantPoolException if a constant pool entry cannot be found
      */
-    void checkTypes(ClassFile cf, CPEntries entries) throws ConstantPoolException {
+    void checkClasses(ClassFile cf, CPEntries entries) throws ConstantPoolException {
         for (ConstantPool.CONSTANT_Class_info ci : entries.classes) {
-            String typeName = ci.getName();
-            DeprData dd = db.getTypeDeprecated(flatten(typeName));
+            String className = ci.getName();
+            DeprData dd = db.getTypeDeprecated(flatten(className));
             if (dd != null) {
-                printType("scan.out.usestype", cf, typeName, dd.isForRemoval());
+                printType("scan.out.usesclass", cf, className, dd.isForRemoval());
             }
         }
     }
@@ -394,26 +395,19 @@
      * @param cf the ClassFile of this class
      * @param nti the NameAndType_info from a MethodRef or InterfaceMethodRef entry
      * @param clname the class name
-     * @param typeKey key for the type message
-     * @param methKey key for the method message
+     * @param msgKey message key for localization
      * @throws ConstantPoolException if a constant pool entry cannot be found
      */
     void checkMethodRef(ClassFile cf,
+                        String clname,
                         CONSTANT_NameAndType_info nti,
-                        String clname,
-                        String typeKey,
-                        String methKey) throws ConstantPoolException {
-        DeprData dd = db.getTypeDeprecated(flatten(clname));
-        if (dd != null) {
-            printType(typeKey, cf, clname, dd.isForRemoval());
-        }
-
+                        String msgKey) throws ConstantPoolException {
         String name = nti.getName();
         String type = nti.getType();
         clname = resolveMember(cf, flatten(clname), name, type, true, true);
-        dd = db.getMethodDeprecated(clname, name, type);
+        DeprData dd = db.getMethodDeprecated(clname, name, type);
         if (dd != null) {
-            printMethod(methKey, cf, clname, name, type, dd.isForRemoval());
+            printMethod(msgKey, cf, clname, name, type, dd.isForRemoval());
         }
     }
 
@@ -425,26 +419,16 @@
      */
     void checkFieldRef(ClassFile cf,
                        ConstantPool.CONSTANT_Fieldref_info fri) throws ConstantPoolException {
+        String clname = fri.getClassName();
         CONSTANT_NameAndType_info nti = fri.getNameAndTypeInfo();
-        String clname = fri.getClassName();
         String name = nti.getName();
         String type = nti.getType();
-        DeprData dd = db.getTypeDeprecated(clname);
-
-        if (dd != null) {
-            printType("scan.out.usesfieldintype", cf, clname, dd.isForRemoval());
-        }
 
         clname = resolveMember(cf, flatten(clname), name, type, false, true);
-        dd = db.getFieldDeprecated(clname, name);
+        DeprData dd = db.getFieldDeprecated(clname, name);
         if (dd != null) {
             printField("scan.out.usesfield", cf, clname, name, dd.isForRemoval());
         }
-
-        dd = db.getTypeDeprecated(flatten(type));
-        if (dd != null) {
-            printFieldType("scan.out.usesfieldoftype", cf, clname, name, type, dd.isForRemoval());
-        }
     }
 
     /**
@@ -515,18 +499,18 @@
 
         checkSuper(cf);
         checkInterfaces(cf);
-        checkTypes(cf, entries);
+        checkClasses(cf, entries);
 
         for (ConstantPool.CONSTANT_Methodref_info mri : entries.methodRefs) {
+            String clname = mri.getClassName();
             CONSTANT_NameAndType_info nti = mri.getNameAndTypeInfo();
-            String clname = mri.getClassName();
-            checkMethodRef(cf, nti, clname, "scan.out.usesmethodintype", "scan.out.usesmethod");
+            checkMethodRef(cf, clname, nti, "scan.out.usesmethod");
         }
 
         for (ConstantPool.CONSTANT_InterfaceMethodref_info imri : entries.intfMethodRefs) {
+            String clname = imri.getClassName();
             CONSTANT_NameAndType_info nti = imri.getNameAndTypeInfo();
-            String clname = imri.getClassName();
-            checkMethodRef(cf, nti, clname, "scan.out.usesintfmethodintype", "scan.out.usesintfmethod");
+            checkMethodRef(cf, clname, nti, "scan.out.usesintfmethod");
         }
 
         for (ConstantPool.CONSTANT_Fieldref_info fri : entries.fieldRefs) {
@@ -545,6 +529,7 @@
      */
     public boolean scanJar(String jarname) {
         try (JarFile jf = new JarFile(jarname)) {
+            out.println(Messages.get("scan.head.jar", jarname));
             finder.addJar(jarname);
             Enumeration<JarEntry> entries = jf.entries();
             while (entries.hasMoreElements()) {
@@ -557,10 +542,12 @@
                 }
             }
             return true;
+        } catch (NoSuchFileException nsfe) {
+            errorNoFile(jarname);
         } catch (IOException | ConstantPoolException ex) {
-            printException(ex);
-            return false;
+            errorException(ex);
         }
+        return false;
     }
 
     /**
@@ -580,12 +567,15 @@
                      .filter(path -> !path.toString().endsWith("package-info.class"))
                      .filter(path -> !path.toString().endsWith("module-info.class"))
                      .collect(Collectors.toList());
+
+            out.println(Messages.get("scan.head.dir", dirname));
+
             for (Path p : classes) {
                 processClass(ClassFile.read(p));
             }
             return true;
         } catch (IOException | ConstantPoolException ex) {
-            printException(ex);
+            errorException(ex);
             return false;
         }
     }
@@ -600,15 +590,35 @@
         try {
             ClassFile cf = finder.find(className);
             if (cf == null) {
-                err("can't find class %s", className);
+                errorNoClass(className);
                 return false;
             } else {
                 processClass(cf);
                 return true;
             }
         } catch (ConstantPoolException ex) {
-            printException(ex);
+            errorException(ex);
             return false;
         }
     }
+
+    /**
+     * Scans the named class file for uses of deprecated APIs.
+     *
+     * @param fileName the class file to scan
+     * @return true on success, false on failure
+     */
+    public boolean processClassFile(String fileName) {
+        Path path = Paths.get(fileName);
+        try {
+            ClassFile cf = ClassFile.read(path);
+            processClass(cf);
+            return true;
+        } catch (NoSuchFileException nsfe) {
+            errorNoFile(fileName);
+        } catch (IOException | ConstantPoolException ex) {
+            errorException(ex);
+        }
+        return false;
+    }
 }
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/DepsAnalyzer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -50,7 +50,7 @@
  *
  * Type of filters:
  * source filter: -include <pattern>
- * target filter: -package, -regex, -requires
+ * target filter: -package, -regex, --require
  *
  * The initial archive set for analysis includes
  * 1. archives specified in the command line arguments
@@ -146,7 +146,9 @@
             // analyze the dependencies collected
             analyzer.run(archives, finder.locationToArchive());
 
-            writer.generateOutput(archives, analyzer);
+            if (writer != null) {
+                writer.generateOutput(archives, analyzer);
+            }
         } finally {
             finder.shutdown();
         }
@@ -156,7 +158,7 @@
     /**
      * Returns the archives for reporting that has matching dependences.
      *
-     * If -requires is set, they should be excluded.
+     * If --require is set, they should be excluded.
      */
     Set<Archive> archives() {
         if (filter.requiresFilter().isEmpty()) {
@@ -165,7 +167,7 @@
                 .filter(Archive::hasDependences)
                 .collect(Collectors.toSet());
         } else {
-            // use the archives that have dependences and not specified in -requires
+            // use the archives that have dependences and not specified in --require
             return archives.stream()
                 .filter(filter::include)
                 .filter(source -> !filter.requiresFilter().contains(source))
@@ -360,16 +362,17 @@
         Archive source = dep.originArchive();
         Archive target = dep.targetArchive();
         String pn = dep.target();
-        if ((verbose == CLASS || verbose == VERBOSE)) {
+        if (verbose == CLASS || verbose == VERBOSE) {
             int i = dep.target().lastIndexOf('.');
             pn = i > 0 ? dep.target().substring(0, i) : "";
         }
         final Info info;
+        Module targetModule = target.getModule();
         if (source == target) {
             info = Info.MODULE_PRIVATE;
-        } else if (!target.getModule().isNamed()) {
+        } else if (!targetModule.isNamed()) {
             info = Info.EXPORTED_API;
-        } else if (target.getModule().isExported(pn)) {
+        } else if (targetModule.isExported(pn) && !targetModule.isJDKUnsupported()) {
             info = Info.EXPORTED_API;
         } else {
             Module module = target.getModule();
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java	Fri Nov 11 16:44:36 2016 +0100
@@ -397,6 +397,11 @@
                             }
 
                             @Override
+                            public Stream<String> list() {
+                                return Stream.empty();
+                            }
+
+                            @Override
                             public void close() throws IOException {
                             }
                         };
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsFilter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -41,7 +41,7 @@
  * 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. -requires specifies to match target dependence from the given module
+ * 3. --require specifies to match target dependence 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
@@ -166,7 +166,7 @@
             // accepts target that is JDK class but not exported
             Module module = targetArchive.getModule();
             return originArchive != targetArchive &&
-                    module.isJDK() && !module.isExported(target.getPackageName());
+                    isJDKInternalPackage(module, target.getPackageName());
         } else if (filterSameArchive) {
             // accepts origin and target that from different archive
             return originArchive != targetArchive;
@@ -174,6 +174,18 @@
         return true;
     }
 
+    /**
+     * Tests if the package is an internal package of the given module.
+     */
+    public boolean isJDKInternalPackage(Module module, String pn) {
+        if (module.isJDKUnsupported()) {
+            // its exported APIs are unsupported
+            return true;
+        }
+
+        return module.isJDK() && !module.isExported(pn);
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder();
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsTask.java	Fri Nov 11 16:44:36 2016 +0100
@@ -221,6 +221,12 @@
                 }
             }
         },
+        new Option(false, "--list-deps", "--list-reduced-deps") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.showModulesAddExports = true;
+                task.options.reduced = opt.equals("--list-reduced-deps");
+            }
+        },
 
         // ---- paths option ----
         new Option(true, "-cp", "-classpath", "--class-path") {
@@ -517,13 +523,13 @@
                 .forEach(e -> System.out.format("split package: %s %s%n", e.getKey(),
                     e.getValue().toString()));
 
-            // check if any module specified in -requires is missing
+            // check if any module specified in --require is missing
             Stream.concat(options.addmods.stream(), options.requires.stream())
                 .filter(mn -> !config.isValidToken(mn))
                 .forEach(mn -> config.findModule(mn).orElseThrow(() ->
                     new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));
 
-            // --gen-module-info
+            // --generate-module-info
             if (options.genModuleInfo != null) {
                 return genModuleInfo(config);
             }
@@ -533,6 +539,13 @@
                 return new ModuleAnalyzer(config, log, options.checkModuleDeps).run();
             }
 
+            if (options.showModulesAddExports) {
+                return new ModuleExportsAnalyzer(config,
+                                                 dependencyFilter(config),
+                                                 options.reduced,
+                                                 log).run();
+            }
+
             if (options.dotOutputDir != null &&
                 (options.verbose == SUMMARY || options.verbose == MODULE) &&
                 !options.addmods.isEmpty() && inputArgs.isEmpty()) {
@@ -555,7 +568,7 @@
                .appModulePath(options.modulePath)
                .addmods(options.addmods);
 
-        if (options.checkModuleDeps != null) {
+        if (options.checkModuleDeps != null || options.showModulesAddExports) {
             // check all system modules in the image
             builder.allModules();
         }
@@ -597,10 +610,10 @@
 
         // analyze the dependencies
         DepsAnalyzer analyzer = new DepsAnalyzer(config,
-                                        dependencyFilter(config),
-                                        writer,
-                                        options.verbose,
-                                        options.apiOnly);
+                                                 dependencyFilter(config),
+                                                 writer,
+                                                 options.verbose,
+                                                 options.apiOnly);
 
         boolean ok = analyzer.run(options.compileTimeView, options.depth);
 
@@ -727,7 +740,7 @@
      * Returns a filter used during dependency analysis
      */
     private JdepsFilter dependencyFilter(JdepsConfiguration config) {
-        // Filter specified by -filter, -package, -regex, and -requires options
+        // Filter specified by -filter, -package, -regex, and --require options
         JdepsFilter.Builder builder = new JdepsFilter.Builder();
 
         // source filters
@@ -737,7 +750,7 @@
         builder.filter(options.filterSamePackage, options.filterSameArchive);
         builder.findJDKInternals(options.findJDKInternals);
 
-        // -requires
+        // --require
         if (!options.requires.isEmpty()) {
             options.requires.stream()
                 .forEach(mn -> {
@@ -757,8 +770,8 @@
 
         // check if system module is set
         config.rootModules().stream()
-            .map(Module::name)
-            .forEach(builder::includeIfSystemModule);
+              .map(Module::name)
+              .forEach(builder::includeIfSystemModule);
 
         return builder.build();
     }
@@ -886,6 +899,8 @@
         String rootModule;
         Set<String> addmods = new HashSet<>();
         Runtime.Version multiRelease;
+        boolean showModulesAddExports;
+        boolean reduced;
 
         boolean hasFilter() {
             return numFilters() > 0;
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsWriter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -50,7 +50,7 @@
     final boolean showProfile;
     final boolean showModule;
 
-    private JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
+    JdepsWriter(Analyzer.Type type, boolean showProfile, boolean showModule) {
         this.type = type;
         this.showProfile = showProfile;
         this.showModule = showModule;
@@ -318,8 +318,7 @@
         }
 
         // exported API
-        boolean jdkunsupported = Module.JDK_UNSUPPORTED.equals(module.name());
-        if (module.isExported(pn) && !jdkunsupported) {
+        if (module.isExported(pn) && !module.isJDKUnsupported()) {
             return showProfileOrModule(module);
         }
 
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Module.java	Fri Nov 11 16:44:36 2016 +0100
@@ -126,12 +126,13 @@
      * Tests if the package of the given name is exported.
      */
     public boolean isExported(String pn) {
-        if (JDK_UNSUPPORTED.equals(this.name())) {
-            return false;
-        }
         return exports.containsKey(pn) ? exports.get(pn).isEmpty() : false;
     }
 
+    public boolean isJDKUnsupported() {
+        return JDK_UNSUPPORTED.equals(this.name());
+    }
+
     /**
      * Converts this module to a strict module with the given dependences
      *
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleAnalyzer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -41,10 +41,8 @@
 import java.nio.file.Path;
 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.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -179,50 +177,43 @@
             return builder.build();
         }
 
-        ModuleDescriptor reduced() {
-            Graph.Builder<Module> bd = new Graph.Builder<>();
+        private Graph<Module> buildReducedGraph() {
+            ModuleGraphBuilder rpBuilder = new ModuleGraphBuilder(configuration);
+            rpBuilder.addModule(root);
             requiresPublic.stream()
-                .forEach(m -> {
-                    bd.addNode(m);
-                    bd.addEdge(root, m);
-                });
+                          .forEach(m -> rpBuilder.addEdge(root, m));
 
             // requires public graph
-            Graph<Module> rbg = bd.build().reduce();
+            Graph<Module> rbg = rpBuilder.build().reduce();
+
+            ModuleGraphBuilder gb = new ModuleGraphBuilder(configuration);
+            gb.addModule(root);
+            requires.stream()
+                    .forEach(m -> gb.addEdge(root, m));
 
             // transitive reduction
-            Graph<Module> newGraph = buildGraph(requires).reduce(rbg);
+            Graph<Module> newGraph = gb.buildGraph().reduce(rbg);
             if (DEBUG) {
                 System.err.println("after transitive reduction: ");
                 newGraph.printGraph(log);
             }
-
-            return descriptor(requiresPublic, newGraph.adjacentNodes(root));
+            return newGraph;
         }
 
+        /**
+         * Apply the transitive reduction on the module graph
+         * and returns the corresponding ModuleDescriptor
+         */
+        ModuleDescriptor reduced() {
+            Graph<Module> g = buildReducedGraph();
+            return descriptor(requiresPublic, g.adjacentNodes(root));
+        }
 
         /**
          * Apply transitive reduction on the resulting graph and reports
          * recommended requires.
          */
         private void analyzeDeps() {
-            Graph.Builder<Module> builder = new Graph.Builder<>();
-            requiresPublic.stream()
-                .forEach(m -> {
-                    builder.addNode(m);
-                    builder.addEdge(root, m);
-                });
-
-            // requires public graph
-            Graph<Module> rbg = buildGraph(requiresPublic).reduce();
-
-            // transitive reduction
-            Graph<Module> newGraph = buildGraph(requires).reduce(builder.build().reduce());
-            if (DEBUG) {
-                System.err.println("after transitive reduction: ");
-                newGraph.printGraph(log);
-            }
-
             printModuleDescriptor(log, root);
 
             ModuleDescriptor analyzedDescriptor = descriptor();
@@ -277,45 +268,6 @@
 
 
         /**
-         * 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(Set<Module> deps) {
-            Graph.Builder<Module> builder = new Graph.Builder<>();
-            builder.addNode(root);
-            Set<Module> visited = new HashSet<>();
-            visited.add(root);
-            Deque<Module> deque = new LinkedList<>();
-            deps.stream()
-                .forEach(m -> {
-                    deque.add(m);
-                    builder.addEdge(root, 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(configuration::findModule)
-                    .flatMap(Optional::stream)
-                    .forEach(m -> {
-                        deque.add(m);
-                        builder.addEdge(from, m);
-                    });
-            }
-            return builder.build();
-        }
-
-        /**
          * Detects any qualified exports not used by the target module.
          */
         private Map<String, Set<String>> unusedQualifiedExports() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleExportsAnalyzer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.lang.module.ModuleDescriptor;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static com.sun.tools.jdeps.Analyzer.NOT_FOUND;
+
+/**
+ * Analyze module dependences and any reference to JDK internal APIs.
+ * It can apply transition reduction on the resulting module graph.
+ *
+ * The result prints one line per module it depends on
+ * one line per JDK internal API package it references:
+ *     $MODULE[/$PACKAGE]
+ *
+ */
+public class ModuleExportsAnalyzer extends DepsAnalyzer {
+    // source archive to its dependences and JDK internal APIs it references
+    private final Map<Archive, Map<Archive,Set<String>>> deps = new HashMap<>();
+    private final boolean reduced;
+    private final PrintWriter writer;
+    public ModuleExportsAnalyzer(JdepsConfiguration config,
+                                 JdepsFilter filter,
+                                 boolean reduced,
+                                 PrintWriter writer) {
+        super(config, filter, null,
+              Analyzer.Type.PACKAGE,
+              false /* all classes */);
+        this.reduced = reduced;
+        this.writer = writer;
+    }
+
+    @Override
+    public boolean run() throws IOException {
+        // analyze dependences
+        boolean rc = super.run();
+
+        // A visitor to record the module-level dependences as well as
+        // use of JDK internal APIs
+        Analyzer.Visitor visitor = new Analyzer.Visitor() {
+            @Override
+            public void visitDependence(String origin, Archive originArchive,
+                                        String target, Archive targetArchive)
+            {
+                Set<String> jdkInternals =
+                    deps.computeIfAbsent(originArchive, _k -> new HashMap<>())
+                        .computeIfAbsent(targetArchive, _k -> new HashSet<>());
+
+                Module module = targetArchive.getModule();
+                if (originArchive.getModule() != module &&
+                        module.isJDK() && !module.isExported(target)) {
+                    // use of JDK internal APIs
+                    jdkInternals.add(target);
+                }
+            }
+        };
+
+        // visit the dependences
+        archives.stream()
+            .filter(analyzer::hasDependences)
+            .sorted(Comparator.comparing(Archive::getName))
+            .forEach(archive -> analyzer.visitDependences(archive, visitor));
+
+
+        // print the dependences on named modules
+        printDependences();
+
+        // print the dependences on unnamed module
+        deps.values().stream()
+            .flatMap(map -> map.keySet().stream())
+            .filter(archive -> !archive.getModule().isNamed())
+            .map(archive -> archive != NOT_FOUND
+                                ? "unnamed module: " + archive.getPathName()
+                                : archive.getPathName())
+            .distinct()
+            .sorted()
+            .forEach(archive -> writer.format("   %s%n", archive));
+
+        return rc;
+    }
+
+    private void printDependences() {
+        // find use of JDK internals
+        Map<Module, Set<String>> jdkinternals = new HashMap<>();
+        deps.keySet().stream()
+            .filter(source -> !source.getModule().isNamed())
+            .map(deps::get)
+            .flatMap(map -> map.entrySet().stream())
+            .filter(e -> e.getValue().size() > 0)
+            .forEach(e -> jdkinternals.computeIfAbsent(e.getKey().getModule(),
+                                                       _k -> new HashSet<>())
+                                      .addAll(e.getValue()));
+
+
+        // build module graph
+        ModuleGraphBuilder builder = new ModuleGraphBuilder(configuration);
+        Module root = new RootModule("root");
+        builder.addModule(root);
+        // find named module dependences
+        deps.keySet().stream()
+            .filter(source -> !source.getModule().isNamed())
+            .map(deps::get)
+            .flatMap(map -> map.keySet().stream())
+            .filter(m -> m.getModule().isNamed())
+            .map(Archive::getModule)
+            .forEach(m -> builder.addEdge(root, m));
+
+        // module dependences
+        Set<Module> modules = builder.build().adjacentNodes(root);
+
+        // if reduced is set, apply transition reduction
+        Set<Module> reducedSet = reduced ? builder.reduced().adjacentNodes(root)
+                                         : modules;
+
+        modules.stream()
+               .sorted(Comparator.comparing(Module::name))
+               .forEach(m -> {
+                if (jdkinternals.containsKey(m)) {
+                    jdkinternals.get(m).stream()
+                        .sorted()
+                        .forEach(pn -> writer.format("   %s/%s%n", m, pn));
+                } else if (reducedSet.contains(m)){
+                    // if the transition reduction is applied, show the reduced graph
+                    writer.format("   %s%n", m);
+                }
+            });
+    }
+
+
+    private class RootModule extends Module {
+        final ModuleDescriptor descriptor;
+        RootModule(String name) {
+            super(name);
+
+            ModuleDescriptor.Builder builder = new ModuleDescriptor.Builder(name);
+            this.descriptor = builder.build();
+        }
+
+        @Override
+        public ModuleDescriptor descriptor() {
+            return descriptor;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/ModuleGraphBuilder.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.PrintWriter;
+import java.lang.module.ModuleDescriptor;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
+import static com.sun.tools.jdeps.Module.*;
+
+/**
+ * A builder to create a Graph<Module>
+ */
+public class ModuleGraphBuilder extends Graph.Builder<Module> {
+    final JdepsConfiguration config;
+
+    ModuleGraphBuilder(JdepsConfiguration config) {
+        this.config = config;
+    }
+
+    /**
+     * Adds a module to the graph.
+     */
+    ModuleGraphBuilder addModule(Module module) {
+        addNode(module);
+        return this;
+    }
+
+    /**
+     * Apply transitive reduction on the resulting graph
+     */
+    public Graph<Module> reduced() {
+        Graph<Module> graph = build();
+        // transitive reduction
+        Graph<Module> newGraph = buildGraph(graph.edges()).reduce();
+
+        if (DEBUG) {
+            PrintWriter log = new PrintWriter(System.err);
+            System.err.println("before transitive reduction: ");
+            graph.printGraph(log);
+            System.err.println("after transitive reduction: ");
+            newGraph.printGraph(log);
+        }
+
+        return newGraph;
+    }
+
+    public Graph<Module> buildGraph() {
+        Graph<Module> graph = build();
+        return buildGraph(graph.edges());
+    }
+
+    /**
+     * Build a graph of module from the given dependences.
+     *
+     * It transitively includes all implied read edges.
+     */
+    private Graph<Module> buildGraph(Map<Module, Set<Module>> edges) {
+        Graph.Builder<Module> builder = new Graph.Builder<>();
+        Set<Module> visited = new HashSet<>();
+        Deque<Module> deque = new LinkedList<>();
+        edges.entrySet().stream().forEach(e -> {
+            Module m = e.getKey();
+            deque.add(m);
+            e.getValue().stream().forEach(v -> {
+                deque.add(v);
+                builder.addEdge(m, v);
+            });
+        });
+
+        // read requires public from ModuleDescriptor
+        Module source;
+        while ((source = deque.poll()) != null) {
+            if (visited.contains(source))
+                continue;
+
+            visited.add(source);
+            builder.addNode(source);
+            Module from = source;
+            requiresPublic(from).forEach(m -> {
+                deque.add(m);
+                builder.addEdge(from, m);
+            });
+        }
+        return builder.build();
+    }
+
+    /*
+     * Returns a stream of modules upon which the given module `requires public`
+     */
+    public Stream<Module> requiresPublic(Module m) {
+        // find requires public
+        return m.descriptor()
+                .requires().stream()
+                .filter(req -> req.modifiers().contains(PUBLIC))
+                .map(ModuleDescriptor.Requires::name)
+                .map(config::findModule)
+                .flatMap(Optional::stream);
+    }
+}
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -149,6 +149,15 @@
 \                                used with -p, -e and -s options.\n\
 \                                WARNING: JDK internal APIs are inaccessible.
 
+main.opt.list-deps=\
+\  --list-deps                   Lists the dependences and use of JDK internal\n\
+\                                APIs.\n\
+\  --list-reduced-deps           Same as --list-deps with not listing\n\
+\                                the implied reads edges from the module graph\n\
+\                                If module M1 depends on M2 and M3,\n\
+\                                M2 requires public on M3, then M1 reading M3 is\n\
+\                                implied and removed from the module graph.
+
 main.opt.depth=\
 \  -depth=<depth>                Specify the depth of the transitive\n\
 \                                dependency analysis
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,36 +25,39 @@
 
 package jdk.internal.jshell.tool;
 
+import jdk.jshell.SourceCodeAnalysis.Documentation;
 import jdk.jshell.SourceCodeAnalysis.QualifiedNames;
 import jdk.jshell.SourceCodeAnalysis.Suggestion;
 
-import java.awt.event.ActionListener;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.io.PrintStream;
 import java.io.UncheckedIOException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.function.Supplier;
+import java.util.function.Function;
 import java.util.prefs.BackingStoreException;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import jdk.internal.shellsupport.doc.JavadocFormatter;
 import jdk.internal.jline.NoInterruptUnixTerminal;
 import jdk.internal.jline.Terminal;
 import jdk.internal.jline.TerminalFactory;
 import jdk.internal.jline.TerminalSupport;
 import jdk.internal.jline.WindowsTerminal;
 import jdk.internal.jline.console.ConsoleReader;
+import jdk.internal.jline.console.CursorBuffer;
 import jdk.internal.jline.console.KeyMap;
 import jdk.internal.jline.console.UserInterruptException;
 import jdk.internal.jline.console.completer.Completer;
@@ -167,10 +170,10 @@
                 return anchor[0];
             }
         });
-        bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl));
+        bind(DOCUMENTATION_SHORTCUT, (Runnable) () -> documentation(repl));
         for (FixComputer computer : FIX_COMPUTERS) {
             for (String shortcuts : SHORTCUT_FIXES) {
-                bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer));
+                bind(shortcuts + computer.shortcut, (Runnable) () -> fixes(computer));
             }
         }
         try {
@@ -259,22 +262,118 @@
         "\u001BO3P" //Alt-F1 (Linux)
     };
 
+    private String lastDocumentationBuffer;
+    private int lastDocumentationCursor = (-1);
+
     private void documentation(JShellTool repl) {
         String buffer = in.getCursorBuffer().buffer.toString();
         int cursor = in.getCursorBuffer().cursor;
-        String doc;
+        boolean firstInvocation = !buffer.equals(lastDocumentationBuffer) || cursor != lastDocumentationCursor;
+        lastDocumentationBuffer = buffer;
+        lastDocumentationCursor = cursor;
+        List<String> doc;
+        String seeMore;
+        Terminal term = in.getTerminal();
         if (prefix.isEmpty() && buffer.trim().startsWith("/")) {
-            doc = repl.commandDocumentation(buffer, cursor);
+            doc = Arrays.asList(repl.commandDocumentation(buffer, cursor, firstInvocation));
+            seeMore = "jshell.console.see.help";
         } else {
-            doc = repl.analysis.documentation(prefix + buffer, cursor + prefix.length());
+            JavadocFormatter formatter = new JavadocFormatter(term.getWidth(),
+                                                              term.isAnsiSupported());
+            Function<Documentation, String> convertor;
+            if (firstInvocation) {
+                convertor = d -> d.signature();
+            } else {
+                convertor = d -> formatter.formatJavadoc(d.signature(),
+                                                         d.javadoc() != null ? d.javadoc()
+                                                                             : repl.messageFormat("jshell.console.no.javadoc"));
+            }
+            doc = repl.analysis.documentation(prefix + buffer, cursor + prefix.length(), !firstInvocation)
+                               .stream()
+                               .map(convertor)
+                               .collect(Collectors.toList());
+            seeMore = "jshell.console.see.javadoc";
         }
 
         try {
-            if (doc != null) {
-                in.println();
-                in.println(doc);
-                in.redrawLine();
-                in.flush();
+            if (doc != null && !doc.isEmpty()) {
+                if (firstInvocation) {
+                    in.println();
+                    in.println(doc.stream().collect(Collectors.joining("\n")));
+                    in.println(repl.messageFormat(seeMore));
+                    in.redrawLine();
+                    in.flush();
+                } else {
+                    in.println();
+
+                    int height = term.getHeight();
+                    String lastNote = "";
+
+                    PRINT_DOC: for (Iterator<String> docIt = doc.iterator(); docIt.hasNext(); ) {
+                        String currentDoc = docIt.next();
+                        String[] lines = currentDoc.split("\n");
+                        int firstLine = 0;
+
+                        PRINT_PAGE: while (true) {
+                            int toPrint = height - 1;
+
+                            while (toPrint > 0 && firstLine < lines.length) {
+                                in.println(lines[firstLine++]);
+                                toPrint--;
+                            }
+
+                            if (firstLine >= lines.length) {
+                                break;
+                            }
+
+                            lastNote = repl.getResourceString("jshell.console.see.next.page");
+                            in.print(lastNote + ConsoleReader.RESET_LINE);
+                            in.flush();
+
+                            while (true) {
+                                int r = in.readCharacter();
+
+                                switch (r) {
+                                    case ' ': continue PRINT_PAGE;
+                                    case 'q':
+                                    case 3:
+                                        break PRINT_DOC;
+                                    default:
+                                        in.beep();
+                                        break;
+                                }
+                            }
+                        }
+
+                        if (docIt.hasNext()) {
+                            lastNote = repl.getResourceString("jshell.console.see.next.javadoc");
+                            in.print(lastNote + ConsoleReader.RESET_LINE);
+                            in.flush();
+
+                            while (true) {
+                                int r = in.readCharacter();
+
+                                switch (r) {
+                                    case ' ': continue PRINT_DOC;
+                                    case 'q':
+                                    case 3:
+                                        break PRINT_DOC;
+                                    default:
+                                        in.beep();
+                                        break;
+                                }
+                            }
+                        }
+                    }
+                    //clear the "press space" line:
+                    in.getCursorBuffer().buffer.replace(0, buffer.length(), lastNote);
+                    in.getCursorBuffer().cursor = 0;
+                    in.killLine();
+                    in.getCursorBuffer().buffer.append(buffer);
+                    in.getCursorBuffer().cursor = cursor;
+                    in.redrawLine();
+                    in.flush();
+                }
             } else {
                 in.beep();
             }
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/EditPad.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +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.jshell.tool;
-
-import java.awt.BorderLayout;
-import java.awt.FlowLayout;
-import java.awt.event.KeyEvent;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
-import java.util.concurrent.CountDownLatch;
-import java.util.function.Consumer;
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.SwingUtilities;
-
-/**
- * A minimal Swing editor as a fallback when the user does not specify an
- * external editor.
- */
-@SuppressWarnings("serial")             // serialVersionUID intentionally omitted
-public class EditPad extends JFrame implements Runnable {
-    private final Consumer<String> errorHandler; // For possible future error handling
-    private final String initialText;
-    private final CountDownLatch closeLock;
-    private final Consumer<String> saveHandler;
-
-    EditPad(Consumer<String> errorHandler, String initialText,
-            CountDownLatch closeLock, Consumer<String> saveHandler) {
-        super("JShell Edit Pad");
-        this.errorHandler = errorHandler;
-        this.initialText = initialText;
-        this.closeLock = closeLock;
-        this.saveHandler = saveHandler;
-    }
-
-    @Override
-    public void run() {
-        addWindowListener(new WindowAdapter() {
-            @Override
-            public void windowClosing(WindowEvent e) {
-                EditPad.this.dispose();
-                closeLock.countDown();
-            }
-        });
-        setLocationRelativeTo(null);
-        setLayout(new BorderLayout());
-        JTextArea textArea = new JTextArea(initialText);
-        add(new JScrollPane(textArea), BorderLayout.CENTER);
-        add(buttons(textArea), BorderLayout.SOUTH);
-
-        setSize(800, 600);
-        setVisible(true);
-    }
-
-    private JPanel buttons(JTextArea textArea) {
-        FlowLayout flow = new FlowLayout();
-        flow.setHgap(35);
-        JPanel buttons = new JPanel(flow);
-        JButton cancel = new JButton("Cancel");
-        cancel.setMnemonic(KeyEvent.VK_C);
-        JButton accept = new JButton("Accept");
-        accept.setMnemonic(KeyEvent.VK_A);
-        JButton exit = new JButton("Exit");
-        exit.setMnemonic(KeyEvent.VK_X);
-        buttons.add(cancel);
-        buttons.add(accept);
-        buttons.add(exit);
-
-        cancel.addActionListener(e -> {
-            close();
-        });
-        accept.addActionListener(e -> {
-            saveHandler.accept(textArea.getText());
-        });
-        exit.addActionListener(e -> {
-            saveHandler.accept(textArea.getText());
-            close();
-        });
-
-        return buttons;
-    }
-
-    private void close() {
-        setVisible(false);
-        dispose();
-        closeLock.countDown();
-    }
-
-    public static void edit(Consumer<String> errorHandler, String initialText,
-            Consumer<String> saveHandler) {
-        CountDownLatch closeLock = new CountDownLatch(1);
-        SwingUtilities.invokeLater(
-                new EditPad(errorHandler, initialText, closeLock, saveHandler));
-        do {
-            try {
-                closeLock.await();
-                break;
-            } catch (InterruptedException ex) {
-                // ignore and loop
-            }
-        } while (true);
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ExternalEditor.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,170 +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.jshell.tool;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.ClosedWatchServiceException;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.WatchKey;
-import java.nio.file.WatchService;
-import java.util.Arrays;
-import java.util.Scanner;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
-import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
-import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
-
-/**
- * Wrapper for controlling an external editor.
- */
-public class ExternalEditor {
-    private final Consumer<String> errorHandler;
-    private final Consumer<String> saveHandler;
-    private final Consumer<String> printHandler;
-    private final IOContext input;
-    private final boolean wait;
-
-    private WatchService watcher;
-    private Thread watchedThread;
-    private Path dir;
-    private Path tmpfile;
-
-    ExternalEditor(Consumer<String> errorHandler, Consumer<String> saveHandler,
-            IOContext input, boolean wait, Consumer<String> printHandler) {
-        this.errorHandler = errorHandler;
-        this.saveHandler = saveHandler;
-        this.printHandler = printHandler;
-        this.input = input;
-        this.wait = wait;
-    }
-
-    private void edit(String[] cmd, String initialText) {
-        try {
-            setupWatch(initialText);
-            launch(cmd);
-        } catch (IOException ex) {
-            errorHandler.accept(ex.getMessage());
-        }
-    }
-
-    /**
-     * Creates a WatchService and registers the given directory
-     */
-    private void setupWatch(String initialText) throws IOException {
-        this.watcher = FileSystems.getDefault().newWatchService();
-        this.dir = Files.createTempDirectory("jshelltemp");
-        this.tmpfile = Files.createTempFile(dir, null, ".java");
-        Files.write(tmpfile, initialText.getBytes(Charset.forName("UTF-8")));
-        dir.register(watcher,
-                ENTRY_CREATE,
-                ENTRY_DELETE,
-                ENTRY_MODIFY);
-        watchedThread = new Thread(() -> {
-            for (;;) {
-                WatchKey key;
-                try {
-                    key = watcher.take();
-                } catch (ClosedWatchServiceException ex) {
-                    // The watch service has been closed, we are done
-                    break;
-                } catch (InterruptedException ex) {
-                    // tolerate an interrupt
-                    continue;
-                }
-
-                if (!key.pollEvents().isEmpty()) {
-                    // Changes have occurred in temp edit directory,
-                    // transfer the new sources to JShell (unless the editor is
-                    // running directly in JShell's window -- don't make a mess)
-                    if (!input.terminalEditorRunning()) {
-                        saveFile();
-                    }
-                }
-
-                boolean valid = key.reset();
-                if (!valid) {
-                    // The watch service has been closed, we are done
-                    break;
-                }
-            }
-        });
-        watchedThread.start();
-    }
-
-    private void launch(String[] cmd) throws IOException {
-        String[] params = Arrays.copyOf(cmd, cmd.length + 1);
-        params[cmd.length] = tmpfile.toString();
-        ProcessBuilder pb = new ProcessBuilder(params);
-        pb = pb.inheritIO();
-
-        try {
-            input.suspend();
-            Process process = pb.start();
-            // wait to exit edit mode in one of these ways...
-            if (wait) {
-                // -wait option -- ignore process exit, wait for carriage-return
-                Scanner scanner = new Scanner(System.in);
-                printHandler.accept("jshell.msg.press.return.to.leave.edit.mode");
-                scanner.nextLine();
-            } else {
-                // wait for process to exit
-                process.waitFor();
-            }
-        } catch (IOException ex) {
-            errorHandler.accept("process IO failure: " + ex.getMessage());
-        } catch (InterruptedException ex) {
-            errorHandler.accept("process interrupt: " + ex.getMessage());
-        } finally {
-            try {
-                watcher.close();
-                watchedThread.join(); //so that saveFile() is finished.
-                saveFile();
-            } catch (InterruptedException ex) {
-                errorHandler.accept("process interrupt: " + ex.getMessage());
-            } finally {
-                input.resume();
-            }
-        }
-    }
-
-    private void saveFile() {
-        try {
-            saveHandler.accept(Files.lines(tmpfile).collect(Collectors.joining("\n", "", "\n")));
-        } catch (IOException ex) {
-            errorHandler.accept("Failure in read edit file: " + ex.getMessage());
-        }
-    }
-
-    static void edit(String[] cmd, Consumer<String> errorHandler, String initialText,
-            Consumer<String> saveHandler, IOContext input, boolean wait, Consumer<String> printHandler) {
-        ExternalEditor ed = new ExternalEditor(errorHandler, saveHandler, input, wait, printHandler);
-        ed.edit(cmd, initialText);
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java	Fri Nov 11 16:44:36 2016 +0100
@@ -116,6 +116,10 @@
                 name, type, value, unresolved, errorLines);
     }
 
+    public String truncateVarValue(String value) {
+        return mode.truncateVarValue(value);
+    }
+
     public String getPrompt(String nextId) {
         return mode.getPrompt(nextId);
     }
@@ -416,6 +420,45 @@
             return sb.toString();
         }
 
+        String truncateVarValue(String value) {
+            return truncateValue(value,
+                    bits(FormatCase.VARVALUE, FormatAction.ADDED,
+                            FormatWhen.PRIMARY, FormatResolve.OK,
+                            FormatUnresolved.UNRESOLVED0, FormatErrors.ERROR0));
+        }
+
+        String truncateValue(String value, long bits) {
+            if (value==null) {
+                return "";
+            } else {
+                // Retrieve the truncation length
+                String truncField = format(TRUNCATION_FIELD, bits);
+                if (truncField.isEmpty()) {
+                    // No truncation set, use whole value
+                    return value;
+                } else {
+                    // Convert truncation length to int
+                    // this is safe since it has been tested before it is set
+                    int trunc = Integer.parseUnsignedInt(truncField);
+                    int len = value.length();
+                    if (len > trunc) {
+                        if (trunc <= 13) {
+                            // Very short truncations have no room for "..."
+                            return value.substring(0, trunc);
+                        } else {
+                            // Normal truncation, make total length equal truncation length
+                            int endLen = trunc / 3;
+                            int startLen = trunc - 5 - endLen;
+                            return value.substring(0, startLen) + " ... " + value.substring(len -endLen);
+                        }
+                    } else {
+                        // Within truncation length, use whole value
+                        return value;
+                    }
+                }
+            }
+        }
+
         // Compute the display output given full context and values
         String format(FormatCase fc, FormatAction fa, FormatWhen fw,
                     FormatResolve fr, FormatUnresolved fu, FormatErrors fe,
@@ -425,33 +468,7 @@
             String fname = name==null? "" : name;
             String ftype = type==null? "" : type;
             // Compute the representation of value
-            String fvalue;
-            if (value==null) {
-                fvalue = "";
-            } else {
-                // Retrieve the truncation length
-                String truncField = format(TRUNCATION_FIELD, bits);
-                if (truncField.isEmpty()) {
-                    // No truncation set, use whole value
-                    fvalue = value;
-                } else {
-                    // Convert truncation length to int
-                    // this is safe since it has been tested before it is set
-                    int trunc = Integer.parseUnsignedInt(truncField);
-                    if (value.length() > trunc) {
-                        if (trunc <= 5) {
-                            // Very short truncations have no room for "..."
-                            fvalue = value.substring(0, trunc);
-                        } else {
-                            // Normal truncation, make total length equal truncation length
-                            fvalue = value.substring(0, trunc - 4) + " ...";
-                        }
-                    } else {
-                        // Within truncation length, use whole value
-                        fvalue = value;
-                    }
-                }
-            }
+            String fvalue = truncateValue(value, bits);
             String funresolved = unresolved==null? "" : unresolved;
             String errors = errorLines.stream()
                     .map(el -> String.format(
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Fri Nov 11 16:44:36 2016 +0100
@@ -89,6 +89,7 @@
 import java.util.MissingResourceException;
 import java.util.Optional;
 import java.util.ResourceBundle;
+import java.util.ServiceLoader;
 import java.util.Spliterators;
 import java.util.function.Function;
 import java.util.function.Supplier;
@@ -99,6 +100,8 @@
 import jdk.internal.jshell.tool.Feedback.FormatResolve;
 import jdk.internal.jshell.tool.Feedback.FormatUnresolved;
 import jdk.internal.jshell.tool.Feedback.FormatWhen;
+import jdk.internal.editor.spi.BuildInEditorProvider;
+import jdk.internal.editor.external.ExternalEditor;
 import static java.util.Arrays.asList;
 import static java.util.Arrays.stream;
 import static java.util.stream.Collectors.joining;
@@ -323,7 +326,7 @@
     }
 
     /**
-     * Print using resource bundle look-up and adding prefix and postfix
+     * Resource bundle look-up
      *
      * @param key the resource key
      */
@@ -523,7 +526,7 @@
             runFile(loadFile, "jshell");
         }
 
-        if (regenerateOnDeath) {
+        if (regenerateOnDeath && feedback.shouldDisplayCommandFluff()) {
             hardmsg("jshell.msg.welcome", version());
         }
 
@@ -565,6 +568,8 @@
     private List<String> processCommandArgs(String[] args) {
         OptionParser parser = new OptionParser();
         OptionSpec<String> cp = parser.accepts("class-path").withRequiredArg();
+        OptionSpec<String> mpath = parser.accepts("module-path").withRequiredArg();
+        OptionSpec<String> amods = parser.accepts("add-modules").withRequiredArg();
         OptionSpec<String> st = parser.accepts("startup").withRequiredArg();
         parser.acceptsAll(asList("n", "no-startup"));
         OptionSpec<String> fb = parser.accepts("feedback").withRequiredArg();
@@ -658,6 +663,18 @@
         if (options.has(c)) {
             compilerOptions.addAll(options.valuesOf(c));
         }
+        if (options.has(mpath)) {
+            compilerOptions.add("--module-path");
+            compilerOptions.addAll(options.valuesOf(mpath));
+            remoteVMOptions.add("--module-path");
+            remoteVMOptions.addAll(options.valuesOf(mpath));
+        }
+        if (options.has(amods)) {
+            compilerOptions.add("--add-modules");
+            compilerOptions.addAll(options.valuesOf(amods));
+            remoteVMOptions.add("--add-modules");
+            remoteVMOptions.addAll(options.valuesOf(amods));
+        }
 
         if (options.has(addExports)) {
             List<String> exports = options.valuesOf(addExports).stream()
@@ -1294,7 +1311,7 @@
         return commandCompletions.completionSuggestions(code, cursor, anchor);
     }
 
-    public String commandDocumentation(String code, int cursor) {
+    public String commandDocumentation(String code, int cursor, boolean shortDescription) {
         code = code.substring(0, cursor);
         int space = code.indexOf(' ');
 
@@ -1302,7 +1319,7 @@
             String cmd = code.substring(0, space);
             Command command = commands.get(cmd);
             if (command != null) {
-                return getResourceString(command.helpKey + ".summary");
+                return getResourceString(command.helpKey + (shortDescription ? ".summary" : ""));
             }
         }
 
@@ -1964,20 +1981,59 @@
         Consumer<String> saveHandler = new SaveHandler(src, srcSet);
         Consumer<String> errorHandler = s -> hard("Edit Error: %s", s);
         if (editor == BUILT_IN_EDITOR) {
-            try {
-                EditPad.edit(errorHandler, src, saveHandler);
-            } catch (RuntimeException ex) {
-                errormsg("jshell.err.cant.launch.editor", ex);
-                fluffmsg("jshell.msg.try.set.editor");
-                return false;
+            return builtInEdit(src, saveHandler, errorHandler);
+        } else {
+            // Changes have occurred in temp edit directory,
+            // transfer the new sources to JShell (unless the editor is
+            // running directly in JShell's window -- don't make a mess)
+            String[] buffer = new String[1];
+            Consumer<String> extSaveHandler = s -> {
+                if (input.terminalEditorRunning()) {
+                    buffer[0] = s;
+                } else {
+                    saveHandler.accept(s);
+                }
+            };
+            ExternalEditor.edit(editor.cmd, src,
+                    errorHandler, extSaveHandler,
+                    () -> input.suspend(),
+                    () -> input.resume(),
+                    editor.wait,
+                    () -> hardrb("jshell.msg.press.return.to.leave.edit.mode"));
+            if (buffer[0] != null) {
+                saveHandler.accept(buffer[0]);
             }
-        } else {
-            ExternalEditor.edit(editor.cmd, errorHandler, src, saveHandler, input,
-                    editor.wait, this::hardrb);
         }
         return true;
     }
     //where
+    // start the built-in editor
+    private boolean builtInEdit(String initialText,
+            Consumer<String> saveHandler, Consumer<String> errorHandler) {
+        try {
+            ServiceLoader<BuildInEditorProvider> sl
+                    = ServiceLoader.load(BuildInEditorProvider.class);
+            // Find the highest ranking provider
+            BuildInEditorProvider provider = null;
+            for (BuildInEditorProvider p : sl) {
+                if (provider == null || p.rank() > provider.rank()) {
+                    provider = p;
+                }
+            }
+            if (provider != null) {
+                provider.edit(getResourceString("jshell.label.editpad"),
+                        initialText, saveHandler, errorHandler);
+                return true;
+            } else {
+                errormsg("jshell.err.no.builtin.editor");
+            }
+        } catch (RuntimeException ex) {
+            errormsg("jshell.err.cant.launch.editor", ex);
+        }
+        fluffmsg("jshell.msg.try.set.editor");
+        return false;
+    }
+    //where
     // receives editor requests to save
     private class SaveHandler implements Consumer<String> {
 
@@ -2184,7 +2240,7 @@
         stream.forEachOrdered(vk ->
         {
             String val = state.status(vk) == Status.VALID
-                    ? state.varValue(vk)
+                    ? feedback.truncateVarValue(state.varValue(vk))
                     : getResourceString("jshell.msg.vars.not.active");
             hard("  %s %s = %s", vk.typeName(), vk.name(), val);
         });
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -54,10 +54,12 @@
 jshell.err.command.ambiguous = Command: ''{0}'' is ambiguous: {1}
 jshell.msg.set.editor.set = Editor set to: {0}
 jshell.msg.set.editor.retain = Editor setting retained: {0}
-jshell.err.cant.launch.editor = Cannot launch editor -- unexpected exception: {0}
-jshell.msg.try.set.editor = Try /set editor to use external editor.
+jshell.err.no.builtin.editor = Built-in editor not available.
+jshell.err.cant.launch.editor = Cannot launch built-in editor -- unexpected exception: {0}
+jshell.msg.try.set.editor = See ''/help /set editor'' to use external editor.
 jshell.msg.press.return.to.leave.edit.mode = Press return to leave edit mode.
 jshell.err.wait.applies.to.external.editor = -wait applies to external editors
+jshell.label.editpad = JShell Edit Pad
 
 jshell.err.setting.to.retain.must.be.specified = The setting to retain must be specified -- {0}
 jshell.msg.set.show.mode.settings = \nTo show mode settings use ''/set prompt'', ''/set truncation'', ...\n\
@@ -145,6 +147,11 @@
 jshell.err.retained.mode.failure = Failure in retained modes (modes cleared) -- {0} {1}
 
 jshell.console.see.more = <press tab to see more>
+jshell.console.see.javadoc = <press shift-tab again to see javadoc>
+jshell.console.see.help = <press shift-tab again to see detailed help>
+jshell.console.see.next.page = -- Press space for next page, Q to quit. --
+jshell.console.see.next.javadoc = -- Press space for next javadoc, Q to quit. --
+jshell.console.no.javadoc = <no javadoc found>
 jshell.console.do.nothing = Do nothing
 jshell.console.choice = Choice: \
 
@@ -158,6 +165,10 @@
 Usage:   jshell <options> <load files>\n\
 where possible options include:\n\
 \    --class-path <path>   Specify where to find user class files\n\
+\    --module-path <path>  Specify where to find application modules\n\
+\    --add-modules <module>(,<module>)*\n\
+\                          Specify modules to resolve, or all modules on the\n\
+\                           module path if <module> is ALL-MODULE-PATHs\n\
 \    --startup <file>      One run replacement for the start-up definitions\n\
 \    --no-startup          Do not run the start-up definitions\n\
 \    --feedback <mode>     Specify the initial feedback mode. The mode may be\n\
@@ -316,8 +327,8 @@
 help.reload.summary = reset and replay relevant history -- current or previous (-restore)
 help.reload.args = [-restore] [-quiet]
 help.reload =\
-Reset the jshell tool code and execution state then replay each\n\
-jshell valid command and valid snippet in the order they were entered.\n\
+Reset the jshell tool code and execution state then replay each valid snippet\n\
+and any /drop or /classpath commands in the order they were entered.\n\
 \n\
 /reload\n\t\
      Reset and replay the valid history since jshell was entered, or\n\t\
@@ -327,7 +338,7 @@
      Reset and replay the valid history between the previous and most\n\t\
      recent time that jshell was entered, or a /reset, or /reload\n\t\
      command was executed. This can thus be used to restore a previous\n\t\
-     jshell tool sesson.\n\n\
+     jshell tool session.\n\n\
 /reload [-restore] -quiet\n\t\
      With the '-quiet' argument the replay is not shown.  Errors will display.
 
@@ -790,7 +801,7 @@
 /set format verbose unrerr '{unresolved} is declared and these errors are corrected: {errors}'  unresolved1-error2    \n\
 /set format verbose unrerr '{unresolved} are declared and these errors are corrected: {errors}' unresolved2-error2    \n\
 \n\
-/set format verbose resolve '{until}{unrerr}'                                                   added,modified,replaced,used    \n\
+/set format verbose resolve '{until}{unrerr}'                                                   defined,notdefined-added,modified,replaced,used    \n\
 \n\
 /set format verbose typeKind 'class'                  class    \n\
 /set format verbose typeKind 'interface'              interface    \n\
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Fri Nov 11 16:44:36 2016 +0100
@@ -855,6 +855,8 @@
                 case PUBLIC:
                 case PROTECTED:
                 case PRIVATE:
+                    // quietly ignore, user cannot see effects one way or the other
+                    break;
                 case STATIC:
                 case FINAL:
                     list.add(mod);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Fri Nov 11 16:44:36 2016 +0100
@@ -47,7 +47,7 @@
 import java.util.stream.Stream;
 import jdk.internal.jshell.debug.InternalDebugControl;
 import jdk.jshell.Snippet.Status;
-import jdk.jshell.execution.JDIDefaultExecutionControl;
+import jdk.jshell.execution.JdiDefaultExecutionControl;
 import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
 import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
 import jdk.jshell.spi.ExecutionEnv;
@@ -117,10 +117,9 @@
         this.extraRemoteVMOptions = b.extraRemoteVMOptions;
         this.extraCompilerOptions = b.extraCompilerOptions;
         this.executionControlGenerator = b.executionControlGenerator==null
-                ? failOverExecutionControlGenerator(
-                        JDIDefaultExecutionControl.launch(),
-                        JDIDefaultExecutionControl.listen("localhost"),
-                        JDIDefaultExecutionControl.listen(null))
+                ? failOverExecutionControlGenerator(JdiDefaultExecutionControl.launch(),
+                        JdiDefaultExecutionControl.listen("localhost"),
+                        JdiDefaultExecutionControl.listen(null))
                 : b.executionControlGenerator;
 
         this.maps = new SnippetMaps(this);
@@ -506,6 +505,9 @@
         if (!closed) {
             closeDown();
             executionControl().close();
+            if (sourceCodeAnalysis != null) {
+                sourceCodeAnalysis.close();
+            }
         }
     }
 
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/MaskCommentsAndModifiers.java	Fri Nov 11 16:44:36 2016 +0100
@@ -36,10 +36,14 @@
  */
 class MaskCommentsAndModifiers {
 
-    private final static Set<String> IGNORED_MODIFERS =
+    private final static Set<String> IGNORED_MODIFIERS =
             Stream.of( "public", "protected", "private", "static", "final" )
                     .collect( Collectors.toSet() );
 
+    private final static Set<String> OTHER_MODIFIERS =
+            Stream.of( "abstract", "strictfp", "transient", "volatile", "synchronized", "native", "default" )
+                    .collect( Collectors.toSet() );
+
     // Builder to accumulate non-masked characters
     private final StringBuilder sbCleared = new StringBuilder();
 
@@ -52,24 +56,28 @@
     // Entire input string length
     private final int length;
 
-    // Should leading modifiers be masked away
-    private final boolean maskModifiers;
-
-    // The next character
+    // The next character position
     private int next = 0;
 
-    // We have past any point where a top-level modifier could be
-    private boolean inside = false;
+    // The current character
+    private int c;
+
+    // Do we mask-off ignored modifiers?  Set by parameter and turned off after
+    // initial modifier section
+    private boolean maskModifiers;
 
     // Does the string end with an unclosed '/*' style comment?
     private boolean openComment = false;
 
-    @SuppressWarnings("empty-statement")
     MaskCommentsAndModifiers(String s, boolean maskModifiers) {
         this.str = s;
         this.length = s.length();
         this.maskModifiers = maskModifiers;
-        do { } while (next());
+        read();
+        while (c >= 0) {
+            next();
+            read();
+        }
     }
 
     String cleared() {
@@ -90,24 +98,33 @@
      * Read the next character
      */
     private int read() {
-        if (next >= length) {
-            return -1;
-        }
-        return str.charAt(next++);
+        return c = (next >= length)
+                ? -1
+                : str.charAt(next++);
     }
 
-    private void write(StringBuilder sb, int ch) {
+    private void unread() {
+        if (c >= 0) {
+            --next;
+        }
+    }
+
+    private void writeTo(StringBuilder sb, int ch) {
         sb.append((char)ch);
     }
 
     private void write(int ch) {
-        write(sbCleared, ch);
-        write(sbMask, Character.isWhitespace(ch) ? ch : ' ');
+        if (ch != -1) {
+            writeTo(sbCleared, ch);
+            writeTo(sbMask, Character.isWhitespace(ch) ? ch : ' ');
+        }
     }
 
     private void writeMask(int ch) {
-        write(sbMask, ch);
-        write(sbCleared, Character.isWhitespace(ch) ? ch : ' ');
+        if (ch != -1) {
+            writeTo(sbMask, ch);
+            writeTo(sbCleared, Character.isWhitespace(ch) ? ch : ' ');
+        }
     }
 
     private void write(CharSequence s) {
@@ -122,99 +139,105 @@
         }
     }
 
-    private boolean next() {
-        return next(read());
-    }
-
-    private boolean next(int c) {
-        if (c < 0) {
-            return false;
-        }
-
-        if (c == '\'' || c == '"') {
-            inside = true;
-            write(c);
-            int match = c;
-            c = read();
-            while (c != match) {
-                if (c < 0) {
-                    return false;
-                }
-                if (c == '\n' || c == '\r') {
-                    write(c);
-                    return true;
-                }
-                if (c == '\\') {
-                    write(c);
-                    c = read();
-                }
+    private void next() {
+        switch (c) {
+            case '\'':
+            case '"':
+                maskModifiers = false;
                 write(c);
-                c = read();
-            }
-            write(c);
-            return true;
-        }
-
-        if (c == '/') {
-            c = read();
-            if (c == '*') {
-                writeMask('/');
-                writeMask(c);
-                int prevc = 0;
-                while ((c = read()) != '/' || prevc != '*') {
-                    if (c < 0) {
-                        openComment = true;
-                        return false;
-                    }
-                    writeMask(c);
-                    prevc = c;
-                }
-                writeMask(c);
-                return true;
-            } else if (c == '/') {
-                writeMask('/');
-                writeMask(c);
-                while ((c = read()) != '\n' && c != '\r') {
-                    if (c < 0) {
-                        return false;
-                    }
-                    writeMask(c);
-                }
-                writeMask(c);
-                return true;
-            } else {
-                inside = true;
-                write('/');
-                // read character falls through
-            }
-        }
-
-        if (Character.isJavaIdentifierStart(c)) {
-            if (maskModifiers && !inside) {
-                StringBuilder sb = new StringBuilder();
-                do {
-                    write(sb, c);
-                    c = read();
-                } while (Character.isJavaIdentifierPart(c));
-                String id = sb.toString();
-                if (IGNORED_MODIFERS.contains(id)) {
-                    writeMask(sb);
-                } else {
-                    write(sb);
-                    if (id.equals("import")) {
-                        inside = true;
+                int match = c;
+                while (read() >= 0 && c != match && c != '\n' && c != '\r') {
+                    write(c);
+                    if (c == '\\') {
+                        write(read());
                     }
                 }
-                return next(c); // recurse to handle left-over character
-            }
-        } else if (!Character.isWhitespace(c)) {
-            inside = true;
+                write(c); // write match // line-end
+                break;
+            case '/':
+                read();
+                switch (c) {
+                    case '*':
+                        writeMask('/');
+                        writeMask(c);
+                        int prevc = 0;
+                        while (read() >= 0 && (c != '/' || prevc != '*')) {
+                            writeMask(c);
+                            prevc = c;
+                        }
+                        writeMask(c);
+                        openComment = c < 0;
+                        break;
+                    case '/':
+                        writeMask('/');
+                        writeMask(c);
+                        while (read() >= 0 && c != '\n' && c != '\r') {
+                            writeMask(c);
+                        }
+                        writeMask(c);
+                        break;
+                    default:
+                        maskModifiers = false;
+                        write('/');
+                        unread();
+                        break;
+                }
+                break;
+            case '@':
+                do {
+                    write(c);
+                    read();
+                } while (Character.isJavaIdentifierPart(c));
+                while (Character.isWhitespace(c)) {
+                    write(c);
+                    read();
+                }
+                // if this is an annotation with arguments, process those recursively
+                if (c == '(') {
+                    write(c);
+                    boolean prevMaskModifiers = maskModifiers;
+                    int parenCnt = 1;
+                    while (read() >= 0) {
+                        if (c == ')') {
+                            if (--parenCnt == 0) {
+                                break;
+                            }
+                        } else if (c == '(') {
+                            ++parenCnt;
+                        }
+                        next(); // recurse to handle quotes and comments
+                    }
+                    write(c);
+                    // stuff in annotation arguments doesn't effect inside determination
+                    maskModifiers = prevMaskModifiers;
+                } else {
+                    unread();
+                }
+                break;
+            default:
+                if (Character.isJavaIdentifierStart(c)) {
+                    StringBuilder sb = new StringBuilder();
+                    do {
+                        writeTo(sb, c);
+                        read();
+                    } while (Character.isJavaIdentifierPart(c));
+                    unread();
+                    String id = sb.toString();
+                    if (maskModifiers && IGNORED_MODIFIERS.contains(id)) {
+                        writeMask(sb);
+                    } else {
+                        write(sb);
+                        if (maskModifiers && !OTHER_MODIFIERS.contains(id)) {
+                            maskModifiers = false;
+                        }
+                    }
+                } else {
+                    if (!Character.isWhitespace(c)) {
+                        maskModifiers = false;
+                    }
+                    write(c);
+                }
+                break;
         }
-
-        if (c < 0) {
-            return false;
-        }
-        write(c);
-        return true;
     }
 }
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java	Fri Nov 11 16:44:36 2016 +0100
@@ -63,12 +63,16 @@
     public abstract List<Suggestion> completionSuggestions(String input, int cursor, int[] anchor);
 
     /**
-     * Compute a description/help string for the given user's input.
+     * Compute documentation for the given user's input. Multiple {@code Documentation} objects may
+     * be returned when multiple elements match the user's input (like for overloaded methods).
      * @param input the snippet the user wrote so far
      * @param cursor the current position of the cursors in the given {@code input} text
-     * @return description/help string for the given user's input
+     * @param computeJavadoc true if the javadoc for the given input should be computed in
+     *                       addition to the signature
+     * @return the documentations for the given user's input, if multiple elements match the input,
+     *         multiple {@code Documentation} objects are returned.
      */
-    public abstract String documentation(String input, int cursor);
+    public abstract List<Documentation> documentation(String input, int cursor, boolean computeJavadoc);
 
     /**
      * Infer the type of the given expression. The expression spans from the beginning of {@code code}
@@ -266,6 +270,26 @@
     }
 
     /**
+     * A documentation for a candidate for continuation of the given user's input.
+     */
+    public interface Documentation {
+
+        /**
+         * The signature of the given element.
+         *
+         * @return the signature
+         */
+        String signature();
+
+        /**
+         * The javadoc of the given element.
+         *
+         * @return the javadoc, or null if not found or not requested
+         */
+        String javadoc();
+    }
+
+    /**
      * List of possible qualified names.
      */
     public static final class QualifiedNames {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -42,19 +42,17 @@
 import com.sun.source.tree.Tree.Kind;
 import com.sun.source.tree.TypeParameterTree;
 import com.sun.source.tree.VariableTree;
-import com.sun.source.util.JavacTask;
 import com.sun.source.util.SourcePositions;
 import com.sun.source.util.TreePath;
 import com.sun.source.util.TreePathScanner;
-import com.sun.source.util.Trees;
 import com.sun.tools.javac.api.JavacScope;
-import com.sun.tools.javac.api.JavacTaskImpl;
 import com.sun.tools.javac.code.Flags;
 import com.sun.tools.javac.code.Symbol.CompletionFailure;
 import com.sun.tools.javac.code.Symbol.VarSymbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
 import com.sun.tools.javac.code.Type.ClassType;
+import jdk.internal.shellsupport.doc.JavadocHelper;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import com.sun.tools.javac.util.Pair;
@@ -105,6 +103,7 @@
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.joining;
 import static java.util.stream.Collectors.toCollection;
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
@@ -123,15 +122,10 @@
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.util.ElementFilter;
 import javax.lang.model.util.Types;
-import javax.tools.JavaCompiler;
 import javax.tools.JavaFileManager.Location;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
 import javax.tools.StandardLocation;
-import javax.tools.ToolProvider;
 
 import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME;
-import static java.util.stream.Collectors.joining;
 import static jdk.jshell.SourceCodeAnalysis.Completeness.DEFINITELY_INCOMPLETE;
 import static jdk.jshell.TreeDissector.printType;
 
@@ -151,6 +145,7 @@
 
     private final JShell proc;
     private final CompletenessAnalyzer ca;
+    private final List<AutoCloseable> closeables = new ArrayList<>();
     private final Map<Path, ClassIndex> currentIndexes = new HashMap<>();
     private int indexVersion;
     private int classpathVersion;
@@ -1097,10 +1092,10 @@
     }
 
     @Override
-    public String documentation(String code, int cursor) {
+    public List<Documentation> documentation(String code, int cursor, boolean computeJavadoc) {
         suspendIndexing();
         try {
-            return documentationImpl(code, cursor);
+            return documentationImpl(code, cursor, computeJavadoc);
         } finally {
             resumeIndexing();
         }
@@ -1112,14 +1107,14 @@
         "-parameters"
     };
 
-    private String documentationImpl(String code, int cursor) {
+    private List<Documentation> documentationImpl(String code, int cursor, boolean computeJavadoc) {
         code = code.substring(0, cursor);
         if (code.trim().isEmpty()) { //TODO: comment handling
             code += ";";
         }
 
         if (guessKind(code) == Kind.IMPORT)
-            return null;
+            return Collections.<Documentation>emptyList();
 
         OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code));
         AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap, keepParameterNames);
@@ -1128,46 +1123,120 @@
         TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(cursor));
 
         if (tp == null)
-            return null;
+            return Collections.<Documentation>emptyList();
 
         TreePath prevPath = null;
-        while (tp != null && tp.getLeaf().getKind() != Kind.METHOD_INVOCATION && tp.getLeaf().getKind() != Kind.NEW_CLASS) {
+        while (tp != null && tp.getLeaf().getKind() != Kind.METHOD_INVOCATION &&
+               tp.getLeaf().getKind() != Kind.NEW_CLASS && tp.getLeaf().getKind() != Kind.IDENTIFIER &&
+               tp.getLeaf().getKind() != Kind.MEMBER_SELECT) {
             prevPath = tp;
             tp = tp.getParentPath();
         }
 
         if (tp == null)
-            return null;
+            return Collections.<Documentation>emptyList();
 
+        Stream<Element> elements;
         Iterable<Pair<ExecutableElement, ExecutableType>> candidates;
         List<? extends ExpressionTree> arguments;
 
-        if (tp.getLeaf().getKind() == Kind.METHOD_INVOCATION) {
-            MethodInvocationTree mit = (MethodInvocationTree) tp.getLeaf();
-            candidates = methodCandidates(at, tp);
-            arguments = mit.getArguments();
+        if (tp.getLeaf().getKind() == Kind.METHOD_INVOCATION || tp.getLeaf().getKind() == Kind.NEW_CLASS) {
+            if (tp.getLeaf().getKind() == Kind.METHOD_INVOCATION) {
+                MethodInvocationTree mit = (MethodInvocationTree) tp.getLeaf();
+                candidates = methodCandidates(at, tp);
+                arguments = mit.getArguments();
+            } else {
+                NewClassTree nct = (NewClassTree) tp.getLeaf();
+                candidates = newClassCandidates(at, tp);
+                arguments = nct.getArguments();
+            }
+
+            if (!isEmptyArgumentsContext(arguments)) {
+                List<TypeMirror> actuals = computeActualInvocationTypes(at, arguments, prevPath);
+                List<TypeMirror> fullActuals = actuals != null ? actuals : Collections.emptyList();
+
+                candidates =
+                        this.filterExecutableTypesByArguments(at, candidates, fullActuals)
+                            .stream()
+                            .filter(method -> parameterType(method.fst, method.snd, fullActuals.size(), true).findAny().isPresent())
+                            .collect(Collectors.toList());
+            }
+
+            elements = Util.stream(candidates).map(method -> method.fst);
+        } else if (tp.getLeaf().getKind() == Kind.IDENTIFIER || tp.getLeaf().getKind() == Kind.MEMBER_SELECT) {
+            Element el = at.trees().getElement(tp);
+
+            if (el == null ||
+                el.asType().getKind() == TypeKind.ERROR ||
+                (el.getKind() == ElementKind.PACKAGE && el.getEnclosedElements().isEmpty())) {
+                //erroneous element:
+                return Collections.<Documentation>emptyList();
+            }
+
+            elements = Stream.of(el);
         } else {
-            NewClassTree nct = (NewClassTree) tp.getLeaf();
-            candidates = newClassCandidates(at, tp);
-            arguments = nct.getArguments();
+            return Collections.<Documentation>emptyList();
+        }
+
+        List<Documentation> result = Collections.emptyList();
+
+        try (JavadocHelper helper = JavadocHelper.create(at.task, findSources())) {
+            result = elements.map(el -> constructDocumentation(at, helper, el, computeJavadoc))
+                             .filter(r -> r != null)
+                             .collect(Collectors.toList());
+        } catch (IOException ex) {
+            proc.debug(ex, "JavadocHelper.close()");
         }
 
-        if (!isEmptyArgumentsContext(arguments)) {
-            List<TypeMirror> actuals = computeActualInvocationTypes(at, arguments, prevPath);
-            List<TypeMirror> fullActuals = actuals != null ? actuals : Collections.emptyList();
+        return result;
+    }
+
+    private Documentation constructDocumentation(AnalyzeTask at, JavadocHelper helper, Element el, boolean computeJavadoc) {
+        String javadoc = null;
+        try {
+            if (hasSyntheticParameterNames(el)) {
+                el = helper.getSourceElement(el);
+            }
+            if (computeJavadoc) {
+                javadoc = helper.getResolvedDocComment(el);
+            }
+        } catch (IOException ex) {
+            proc.debug(ex, "SourceCodeAnalysisImpl.element2String(..., " + el + ")");
+        }
+        String signature = Util.expunge(elementHeader(at, el, !hasSyntheticParameterNames(el), true));
+        return new DocumentationImpl(signature,  javadoc);
+    }
 
-            candidates =
-                    this.filterExecutableTypesByArguments(at, candidates, fullActuals)
-                        .stream()
-                        .filter(method -> parameterType(method.fst, method.snd, fullActuals.size(), true).findAny().isPresent())
-                        .collect(Collectors.toList());
+    public void close() {
+        for (AutoCloseable closeable : closeables) {
+            try {
+                closeable.close();
+            } catch (Exception ex) {
+                proc.debug(ex, "SourceCodeAnalysisImpl.close()");
+            }
+        }
+    }
+
+    private static final class DocumentationImpl implements Documentation {
+
+        private final String signature;
+        private final String javadoc;
+
+        public DocumentationImpl(String signature, String javadoc) {
+            this.signature = signature;
+            this.javadoc = javadoc;
         }
 
-        try (SourceCache sourceCache = new SourceCache(at)) {
-            return Util.stream(candidates)
-                    .map(method -> Util.expunge(element2String(sourceCache, method.fst)))
-                    .collect(joining("\n"));
+        @Override
+        public String signature() {
+            return signature;
         }
+
+        @Override
+        public String javadoc() {
+            return javadoc;
+        }
+
     }
 
     private boolean isEmptyArgumentsContext(List<? extends ExpressionTree> arguments) {
@@ -1178,18 +1247,6 @@
         return false;
     }
 
-    private String element2String(SourceCache sourceCache, Element el) {
-        try {
-            if (hasSyntheticParameterNames(el)) {
-                el = sourceCache.getSourceMethod(el);
-            }
-        } catch (IOException ex) {
-            proc.debug(ex, "SourceCodeAnalysisImpl.element2String(..., " + el + ")");
-        }
-
-        return Util.expunge(elementHeader(sourceCache.originalTask, el, !hasSyntheticParameterNames(el)));
-    }
-
     private boolean hasSyntheticParameterNames(Element el) {
         if (el.getKind() != ElementKind.CONSTRUCTOR && el.getKind() != ElementKind.METHOD)
             return false;
@@ -1204,119 +1261,6 @@
                  .allMatch(param -> param.getSimpleName().toString().startsWith("arg"));
     }
 
-    private final class SourceCache implements AutoCloseable {
-        private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        private final Map<String, Map<String, Element>> topLevelName2Signature2Method = new HashMap<>();
-        private final AnalyzeTask originalTask;
-        private final StandardJavaFileManager fm;
-
-        public SourceCache(AnalyzeTask originalTask) {
-            this.originalTask = originalTask;
-            List<Path> sources = findSources();
-            if (sources.iterator().hasNext()) {
-                StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null);
-                try {
-                    fm.setLocationFromPaths(StandardLocation.SOURCE_PATH, sources);
-                } catch (IOException ex) {
-                    proc.debug(ex, "SourceCodeAnalysisImpl.SourceCache.<init>(...)");
-                    try {
-                        fm.close();
-                    } catch (IOException closeEx) {
-                        proc.debug(closeEx, "SourceCodeAnalysisImpl.SourceCache.close()");
-                    }
-                    fm = null;
-                }
-                this.fm = fm;
-            } else {
-                //don't waste time if there are no sources
-                this.fm = null;
-            }
-        }
-
-        public Element getSourceMethod(Element method) throws IOException {
-            if (fm == null)
-                return method;
-
-            TypeElement type = topLevelType(method);
-
-            if (type == null)
-                return method;
-
-            String binaryName = originalTask.task.getElements().getBinaryName(type).toString();
-
-            Map<String, Element> cache = topLevelName2Signature2Method.get(binaryName);
-
-            if (cache == null) {
-                topLevelName2Signature2Method.put(binaryName, cache = createMethodCache(binaryName));
-            }
-
-            String handle = elementHeader(originalTask, method, false);
-
-            return cache.getOrDefault(handle, method);
-        }
-
-        private TypeElement topLevelType(Element el) {
-            while (el != null && el.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
-                el = el.getEnclosingElement();
-            }
-
-            return el != null && (el.getKind().isClass() || el.getKind().isInterface()) ? (TypeElement) el : null;
-        }
-
-        private Map<String, Element> createMethodCache(String binaryName) throws IOException {
-            Pair<JavacTask, CompilationUnitTree> source = findSource(binaryName);
-
-            if (source == null)
-                return Collections.emptyMap();
-
-            Map<String, Element> signature2Method = new HashMap<>();
-            Trees trees = Trees.instance(source.fst);
-
-            new TreePathScanner<Void, Void>() {
-                @Override
-                public Void visitMethod(MethodTree node, Void p) {
-                    Element currentMethod = trees.getElement(getCurrentPath());
-
-                    if (currentMethod != null) {
-                        signature2Method.put(elementHeader(originalTask, currentMethod, false), currentMethod);
-                    }
-
-                    return null;
-                }
-            }.scan(source.snd, null);
-
-            return signature2Method;
-        }
-
-        private Pair<JavacTask, CompilationUnitTree> findSource(String binaryName) throws IOException {
-            JavaFileObject jfo = fm.getJavaFileForInput(StandardLocation.SOURCE_PATH,
-                                                        binaryName,
-                                                        JavaFileObject.Kind.SOURCE);
-
-            if (jfo == null)
-                return null;
-
-            List<JavaFileObject> jfos = Arrays.asList(jfo);
-            JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, d -> {}, null, null, jfos);
-            Iterable<? extends CompilationUnitTree> cuts = task.parse();
-
-            task.enter();
-
-            return Pair.of(task, cuts.iterator().next());
-        }
-
-        @Override
-        public void close() {
-            try {
-                if (fm != null) {
-                    fm.close();
-                }
-            } catch (IOException ex) {
-                proc.debug(ex, "SourceCodeAnalysisImpl.SourceCache.close()");
-            }
-        }
-    }
-
     private List<Path> availableSources;
 
     private List<Path> findSources() {
@@ -1328,25 +1272,59 @@
         Path srcZip = home.resolve("src.zip");
         if (!Files.isReadable(srcZip))
             srcZip = home.getParent().resolve("src.zip");
-        if (Files.isReadable(srcZip))
-            result.add(srcZip);
+        if (Files.isReadable(srcZip)) {
+            boolean keepOpen = false;
+            FileSystem zipFO = null;
+
+            try {
+                URI uri = URI.create("jar:" + srcZip.toUri());
+                zipFO = FileSystems.newFileSystem(uri, Collections.emptyMap());
+                Path root = zipFO.getRootDirectories().iterator().next();
+
+                if (Files.exists(root.resolve("java/lang/Object.java".replace("/", zipFO.getSeparator())))) {
+                    //non-modular format:
+                    result.add(srcZip);
+                } else if (Files.exists(root.resolve("java.base/java/lang/Object.java".replace("/", zipFO.getSeparator())))) {
+                    //modular format:
+                    try (DirectoryStream<Path> ds = Files.newDirectoryStream(root)) {
+                        for (Path p : ds) {
+                            if (Files.isDirectory(p)) {
+                                result.add(p);
+                            }
+                        }
+                    }
+
+                    keepOpen = true;
+                }
+            } catch (IOException ex) {
+                proc.debug(ex, "SourceCodeAnalysisImpl.findSources()");
+            } finally {
+                if (zipFO != null) {
+                    if (keepOpen) {
+                        closeables.add(zipFO);
+                    } else {
+                        try {
+                            zipFO.close();
+                        } catch (IOException ex) {
+                            proc.debug(ex, "SourceCodeAnalysisImpl.findSources()");
+                        }
+                    }
+                }
+            }
+        }
         return availableSources = result;
     }
 
-    private String elementHeader(AnalyzeTask at, Element el) {
-        return elementHeader(at, el, true);
-    }
-
-    private String elementHeader(AnalyzeTask at, Element el, boolean includeParameterNames) {
+    private String elementHeader(AnalyzeTask at, Element el, boolean includeParameterNames, boolean useFQN) {
         switch (el.getKind()) {
             case ANNOTATION_TYPE: case CLASS: case ENUM: case INTERFACE: {
                 TypeElement type = (TypeElement)el;
                 String fullname = type.getQualifiedName().toString();
                 Element pkg = at.getElements().getPackageOf(el);
-                String name = pkg == null ? fullname :
+                String name = pkg == null || useFQN ? fullname :
                         proc.maps.fullClassNameAndPackageToClass(fullname, ((PackageElement)pkg).getQualifiedName().toString());
 
-                return name + typeParametersOpt(at, type.getTypeParameters());
+                return name + typeParametersOpt(at, type.getTypeParameters(), includeParameterNames);
             }
             case TYPE_PARAMETER: {
                 TypeParameterElement tp = (TypeParameterElement)el;
@@ -1363,9 +1341,9 @@
                                 .collect(joining(" & "));
             }
             case FIELD:
-                return elementHeader(at, el.getEnclosingElement()) + "." + el.getSimpleName() + ":" + el.asType();
+                return elementHeader(at, el.getEnclosingElement(), includeParameterNames, false) + "." + el.getSimpleName() + ":" + el.asType();
             case ENUM_CONSTANT:
-                return elementHeader(at, el.getEnclosingElement()) + "." + el.getSimpleName();
+                return elementHeader(at, el.getEnclosingElement(), includeParameterNames, false) + "." + el.getSimpleName();
             case EXCEPTION_PARAMETER: case LOCAL_VARIABLE: case PARAMETER: case RESOURCE_VARIABLE:
                 return el.getSimpleName() + ":" + el.asType();
             case CONSTRUCTOR: case METHOD: {
@@ -1379,20 +1357,20 @@
                     header.append(printType(at, proc, method.getReturnType())).append(" ");
                 } else {
                     // type parameters for the constructor
-                    String typeParameters = typeParametersOpt(at, method.getTypeParameters());
+                    String typeParameters = typeParametersOpt(at, method.getTypeParameters(), includeParameterNames);
                     if (!typeParameters.isEmpty()) {
                         header.append(typeParameters).append(" ");
                     }
                 }
 
                 // receiver type
-                String clazz = elementHeader(at, el.getEnclosingElement());
+                String clazz = elementHeader(at, el.getEnclosingElement(), includeParameterNames, false);
                 header.append(clazz);
 
                 if (isMethod) {
                     //method name with type parameters
                     (clazz.isEmpty() ? header : header.append("."))
-                            .append(typeParametersOpt(at, method.getTypeParameters()))
+                            .append(typeParametersOpt(at, method.getTypeParameters(), includeParameterNames))
                             .append(el.getSimpleName());
                 }
 
@@ -1435,10 +1413,10 @@
         }
         return arrayType;
     }
-    private String typeParametersOpt(AnalyzeTask at, List<? extends TypeParameterElement> typeParameters) {
+    private String typeParametersOpt(AnalyzeTask at, List<? extends TypeParameterElement> typeParameters, boolean includeParameterNames) {
         return typeParameters.isEmpty() ? ""
                 : typeParameters.stream()
-                        .map(tp -> elementHeader(at, tp))
+                        .map(tp -> elementHeader(at, tp, includeParameterNames, false))
                         .collect(joining(", ", "<", ">"));
     }
 
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIDefaultExecutionControl.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,282 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.jshell.execution;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.OutputStream;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Consumer;
-import com.sun.jdi.BooleanValue;
-import com.sun.jdi.ClassNotLoadedException;
-import com.sun.jdi.Field;
-import com.sun.jdi.IncompatibleThreadStateException;
-import com.sun.jdi.InvalidTypeException;
-import com.sun.jdi.ObjectReference;
-import com.sun.jdi.StackFrame;
-import com.sun.jdi.ThreadReference;
-import com.sun.jdi.VMDisconnectedException;
-import com.sun.jdi.VirtualMachine;
-import jdk.jshell.spi.ExecutionControl;
-import jdk.jshell.spi.ExecutionEnv;
-import static jdk.jshell.execution.Util.remoteInputOutput;
-
-/**
- * The implementation of {@link jdk.jshell.spi.ExecutionControl} that the
- * JShell-core uses by default.
- * Launches a remote process -- the "remote agent".
- * Interfaces to the remote agent over a socket and via JDI.
- * Designed to work with {@link RemoteExecutionControl}.
- *
- * @author Robert Field
- * @author Jan Lahoda
- */
-public class JDIDefaultExecutionControl extends JDIExecutionControl {
-
-    private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
-
-    private VirtualMachine vm;
-    private Process process;
-
-    private final Object STOP_LOCK = new Object();
-    private boolean userCodeRunning = false;
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI
-     * {@code LaunchingConnector}.
-     *
-     * @return the generator
-     */
-    public static ExecutionControl.Generator launch() {
-        return env -> create(env, true, null);
-    }
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI
-     * {@code ListeningConnector}.
-     *
-     * @param host explicit hostname to use, if null use discovered
-     * hostname, applies to listening only (!isLaunch)
-     * @return the generator
-     */
-    public static ExecutionControl.Generator listen(String host) {
-        return env -> create(env, false, host);
-    }
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI
-     * {@code ListeningConnector} or {@code LaunchingConnector}.
-     *
-     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
-     * commands and results. This socket also transports the user
-     * input/output/error.
-     *
-     * @param env the context passed by
-     * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
-     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
-     * otherwise we start explicitly and use ListeningConnector
-     * @param host explicit hostname to use, if null use discovered
-     * hostname, applies to listening only (!isLaunch)
-     * @return the channel
-     * @throws IOException if there are errors in set-up
-     */
-    private static ExecutionControl create(ExecutionEnv env,
-            boolean isLaunch, String host) throws IOException {
-        try (final ServerSocket listener = new ServerSocket(0)) {
-            // timeout after 60 seconds
-            listener.setSoTimeout(60000);
-            int port = listener.getLocalPort();
-
-            // Set-up the JDI connection
-            JDIInitiator jdii = new JDIInitiator(port,
-                    env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
-            VirtualMachine vm = jdii.vm();
-            Process process = jdii.process();
-
-            List<Consumer<String>> deathListeners = new ArrayList<>();
-            deathListeners.add(s -> env.closeDown());
-            Util.detectJDIExitEvent(vm, s -> {
-                for (Consumer<String> h : deathListeners) {
-                    h.accept(s);
-                }
-            });
-
-            // Set-up the commands/reslts on the socket.  Piggy-back snippet
-            // output.
-            Socket socket = listener.accept();
-            // out before in -- match remote creation so we don't hang
-            OutputStream out = socket.getOutputStream();
-            Map<String, OutputStream> outputs = new HashMap<>();
-            outputs.put("out", env.userOut());
-            outputs.put("err", env.userErr());
-            Map<String, InputStream> input = new HashMap<>();
-            input.put("in", env.userIn());
-            return remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new JDIDefaultExecutionControl(objOut, objIn, vm, process, deathListeners));
-        }
-    }
-
-    /**
-     * Create an instance.
-     *
-     * @param cmdout the output for commands
-     * @param cmdin the input for responses
-     */
-    private JDIDefaultExecutionControl(ObjectOutput cmdout, ObjectInput cmdin,
-            VirtualMachine vm, Process process, List<Consumer<String>> deathListeners) {
-        super(cmdout, cmdin);
-        this.vm = vm;
-        this.process = process;
-        deathListeners.add(s -> disposeVM());
-    }
-
-    @Override
-    public String invoke(String classname, String methodname)
-            throws RunException,
-            EngineTerminationException, InternalException {
-        String res;
-        synchronized (STOP_LOCK) {
-            userCodeRunning = true;
-        }
-        try {
-            res = super.invoke(classname, methodname);
-        } finally {
-            synchronized (STOP_LOCK) {
-                userCodeRunning = false;
-            }
-        }
-        return res;
-    }
-
-    /**
-     * Interrupts a running remote invoke by manipulating remote variables
-     * and sending a stop via JDI.
-     *
-     * @throws EngineTerminationException the execution engine has terminated
-     * @throws InternalException an internal problem occurred
-     */
-    @Override
-    public void stop() throws EngineTerminationException, InternalException {
-        synchronized (STOP_LOCK) {
-            if (!userCodeRunning) {
-                return;
-            }
-
-            vm().suspend();
-            try {
-                OUTER:
-                for (ThreadReference thread : vm().allThreads()) {
-                    // could also tag the thread (e.g. using name), to find it easier
-                    for (StackFrame frame : thread.frames()) {
-                        if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
-                                (    "invoke".equals(frame.location().method().name())
-                                || "varValue".equals(frame.location().method().name()))) {
-                            ObjectReference thiz = frame.thisObject();
-                            Field inClientCode = thiz.referenceType().fieldByName("inClientCode");
-                            Field expectingStop = thiz.referenceType().fieldByName("expectingStop");
-                            Field stopException = thiz.referenceType().fieldByName("stopException");
-                            if (((BooleanValue) thiz.getValue(inClientCode)).value()) {
-                                thiz.setValue(expectingStop, vm().mirrorOf(true));
-                                ObjectReference stopInstance = (ObjectReference) thiz.getValue(stopException);
-
-                                vm().resume();
-                                debug("Attempting to stop the client code...\n");
-                                thread.stop(stopInstance);
-                                thiz.setValue(expectingStop, vm().mirrorOf(false));
-                            }
-
-                            break OUTER;
-                        }
-                    }
-                }
-            } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) {
-                throw new InternalException("Exception on remote stop: " + ex);
-            } finally {
-                vm().resume();
-            }
-        }
-    }
-
-    @Override
-    public void close() {
-        super.close();
-        disposeVM();
-    }
-
-    private synchronized void disposeVM() {
-        try {
-            if (vm != null) {
-                vm.dispose(); // This could NPE, so it is caught below
-                vm = null;
-            }
-        } catch (VMDisconnectedException ex) {
-            // Ignore if already closed
-        } catch (Throwable ex) {
-            debug(ex, "disposeVM");
-        } finally {
-            if (process != null) {
-                process.destroy();
-                process = null;
-            }
-        }
-    }
-
-    @Override
-    protected synchronized VirtualMachine vm() throws EngineTerminationException {
-        if (vm == null) {
-            throw new EngineTerminationException("VM closed");
-        } else {
-            return vm;
-        }
-    }
-
-    /**
-     * Log debugging information. Arguments as for {@code printf}.
-     *
-     * @param format a format string as described in Format string syntax
-     * @param args arguments referenced by the format specifiers in the format
-     * string.
-     */
-    private static void debug(String format, Object... args) {
-        // Reserved for future logging
-    }
-
-    /**
-     * Log a serious unexpected internal exception.
-     *
-     * @param ex the exception
-     * @param where a description of the context of the exception
-     */
-    private static void debug(Throwable ex, String where) {
-        // Reserved for future logging
-    }
-
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIEventHandler.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +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 jdk.jshell.execution;
-
-import java.util.function.Consumer;
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-
-/**
- * Handler of Java Debug Interface events.
- * Adapted from jdb EventHandler.
- * Only exit and disconnect events processed.
- */
-class JDIEventHandler implements Runnable {
-
-    private final Thread thread;
-    private volatile boolean connected = true;
-    private boolean completed = false;
-    private final VirtualMachine vm;
-    private final Consumer<String> reportVMExit;
-
-    /**
-     * Creates an event handler. Start with {@code start()}.
-     *
-     * @param vm the virtual machine for which to handle events
-     * @param reportVMExit callback to report exit/disconnect
-     * (passed true if the VM has died)
-     */
-    JDIEventHandler(VirtualMachine vm, Consumer<String> reportVMExit) {
-        this.vm = vm;
-        this.reportVMExit = reportVMExit;
-        this.thread = new Thread(this, "event-handler");
-        this.thread.setDaemon(true);
-    }
-
-    /**
-     * Starts the event handler.
-     */
-    void start() {
-        thread.start();
-    }
-
-    synchronized void shutdown() {
-        connected = false;  // force run() loop termination
-        thread.interrupt();
-        while (!completed) {
-            try {wait();} catch (InterruptedException exc) {}
-        }
-    }
-
-    @Override
-    public void run() {
-        EventQueue queue = vm.eventQueue();
-        while (connected) {
-            try {
-                EventSet eventSet = queue.remove();
-                boolean resumeStoppedApp = false;
-                EventIterator it = eventSet.eventIterator();
-                while (it.hasNext()) {
-                    resumeStoppedApp |= handleEvent(it.nextEvent());
-                }
-
-                if (resumeStoppedApp) {
-                    eventSet.resume();
-                }
-            } catch (InterruptedException exc) {
-                // Do nothing. Any changes will be seen at top of loop.
-            } catch (VMDisconnectedException discExc) {
-                handleDisconnectedException();
-                break;
-            }
-        }
-        synchronized (this) {
-            completed = true;
-            notifyAll();
-        }
-    }
-
-    private boolean handleEvent(Event event) {
-        handleExitEvent(event);
-        return true;
-    }
-
-    private void handleExitEvent(Event event) {
-        if (event instanceof VMDeathEvent) {
-            reportVMExit.accept("VM Died");
-        } else if (event instanceof VMDisconnectEvent) {
-            connected = false;
-            reportVMExit.accept("VM Disconnected");
-        } else {
-            // ignore everything else
-        }
-    }
-
-    private synchronized void handleDisconnectedException() {
-        /*
-         * A VMDisconnectedException has happened while dealing with
-         * another event. We need to flush the event queue, dealing only
-         * with exit events (VMDeath, VMDisconnect) so that we terminate
-         * correctly.
-         */
-        EventQueue queue = vm.eventQueue();
-        while (connected) {
-            try {
-                EventSet eventSet = queue.remove();
-                EventIterator iter = eventSet.eventIterator();
-                while (iter.hasNext()) {
-                    handleExitEvent(iter.next());
-                }
-            } catch (InterruptedException exc) {
-                // ignore
-            } catch (InternalError exc) {
-                // ignore
-            }
-        }
-    }
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIExecutionControl.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * 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.jshell.execution;
-
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-import com.sun.jdi.ReferenceType;
-import com.sun.jdi.VirtualMachine;
-import jdk.jshell.spi.ExecutionControl;
-import static java.util.stream.Collectors.toMap;
-
-/**
- * Abstract JDI implementation of {@link jdk.jshell.spi.ExecutionControl}
- */
-public abstract class JDIExecutionControl extends StreamingExecutionControl implements ExecutionControl {
-
-    /**
-     * Mapping from class names to JDI {@link ReferenceType}.
-     */
-    private final Map<String, ReferenceType> toReferenceType = new HashMap<>();
-
-    /**
-     * Create an instance.
-     * @param out the output from the remote agent
-     * @param in the input to the remote agent
-     */
-    protected JDIExecutionControl(ObjectOutput out, ObjectInput in) {
-        super(out, in);
-    }
-
-    /**
-     * Returns the JDI {@link VirtualMachine} instance.
-     *
-     * @return the virtual machine
-     * @throws EngineTerminationException if the VM is dead/disconnected
-     */
-    protected abstract VirtualMachine vm() throws EngineTerminationException;
-
-    /**
-     * Redefine the specified classes. Where 'redefine' is, as in JDI and JVMTI,
-     * an in-place replacement of the classes (preserving class identity) --
-     * that is, existing references to the class do not need to be recompiled.
-     * This implementation uses JDI
-     * {@link com.sun.jdi.VirtualMachine#redefineClasses(java.util.Map) }.
-     * It will be unsuccessful if
-     * the signature of the class has changed (see the JDI spec). The
-     * JShell-core is designed to adapt to unsuccessful redefine.
-     */
-    @Override
-    public void redefine(ClassBytecodes[] cbcs)
-            throws ClassInstallException, EngineTerminationException {
-        try {
-            // Convert to the JDI ReferenceType to class bytes map form needed
-            // by JDI.
-            VirtualMachine vm = vm();
-            Map<ReferenceType, byte[]> rmp = Stream.of(cbcs)
-                    .collect(toMap(
-                            cbc -> referenceType(vm, cbc.name()),
-                            cbc -> cbc.bytecodes()));
-            // Attempt redefine.  Throws exceptions on failure.
-            vm().redefineClasses(rmp);
-        } catch (EngineTerminationException ex) {
-            throw ex;
-        } catch (Exception ex) {
-            throw new ClassInstallException("redefine: " + ex.getMessage(), new boolean[cbcs.length]);
-        }
-    }
-
-    /**
-     * Returns the JDI {@link ReferenceType} corresponding to the specified
-     * class name.
-     *
-     * @param vm the current JDI {@link VirtualMachine} as returned by
-     * {@code vm()}
-     * @param name the class name to look-up
-     * @return the corresponding {@link ReferenceType}
-     */
-    protected ReferenceType referenceType(VirtualMachine vm, String name) {
-        return toReferenceType.computeIfAbsent(name, n -> nameToRef(vm, n));
-    }
-
-    private static ReferenceType nameToRef(VirtualMachine vm, String name) {
-        List<ReferenceType> rtl = vm.classesByName(name);
-        if (rtl.size() != 1) {
-            return null;
-        }
-        return rtl.get(0);
-    }
-
-}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JDIInitiator.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,223 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package jdk.jshell.execution;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import com.sun.jdi.Bootstrap;
-import com.sun.jdi.VirtualMachine;
-import com.sun.jdi.connect.Connector;
-import com.sun.jdi.connect.LaunchingConnector;
-import com.sun.jdi.connect.ListeningConnector;
-
-/**
- * Sets up a JDI connection, providing the resulting JDI {@link VirtualMachine}
- * and the {@link Process} the remote agent is running in.
- */
-public class JDIInitiator {
-
-    private VirtualMachine vm;
-    private Process process = null;
-    private final Connector connector;
-    private final String remoteAgent;
-    private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
-
-    /**
-     * Start the remote agent and establish a JDI connection to it.
-     *
-     * @param port the socket port for (non-JDI) commands
-     * @param remoteVMOptions any user requested VM options
-     * @param remoteAgent full class name of remote agent to launch
-     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
-     * otherwise we start explicitly and use ListeningConnector
-     * @param host explicit hostname to use, if null use discovered
-     * hostname, applies to listening only (!isLaunch)
-     */
-    public JDIInitiator(int port, List<String> remoteVMOptions, String remoteAgent,
-            boolean isLaunch, String host) {
-        this.remoteAgent = remoteAgent;
-        String connectorName
-                = isLaunch
-                        ? "com.sun.jdi.CommandLineLaunch"
-                        : "com.sun.jdi.SocketListen";
-        this.connector = findConnector(connectorName);
-        if (connector == null) {
-            throw new IllegalArgumentException("No connector named: " + connectorName);
-        }
-        Map<String, String> argumentName2Value
-                = isLaunch
-                        ? launchArgs(port, String.join(" ", remoteVMOptions))
-                        : new HashMap<>();
-        if (host != null && !isLaunch) {
-            argumentName2Value.put("localAddress", host);
-        }
-        this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
-        this.vm = isLaunch
-                ? launchTarget()
-                : listenTarget(port, remoteVMOptions);
-
-    }
-
-    /**
-     * Returns the resulting {@code VirtualMachine} instance.
-     *
-     * @return the virtual machine
-     */
-    public VirtualMachine vm() {
-        return vm;
-    }
-
-    /**
-     * Returns the launched process.
-     *
-     * @return the remote agent process
-     */
-    public Process process() {
-        return process;
-    }
-
-    /* launch child target vm */
-    private VirtualMachine launchTarget() {
-        LaunchingConnector launcher = (LaunchingConnector) connector;
-        try {
-            VirtualMachine new_vm = launcher.launch(connectorArgs);
-            process = new_vm.process();
-            return new_vm;
-        } catch (Exception ex) {
-            reportLaunchFail(ex, "launch");
-        }
-        return null;
-    }
-
-    /**
-     * Directly launch the remote agent and connect JDI to it with a
-     * ListeningConnector.
-     */
-    private VirtualMachine listenTarget(int port, List<String> remoteVMOptions) {
-        ListeningConnector listener = (ListeningConnector) connector;
-        try {
-            // Start listening, get the JDI connection address
-            String addr = listener.startListening(connectorArgs);
-            debug("Listening at address: " + addr);
-
-            // Launch the RemoteAgent requesting a connection on that address
-            String javaHome = System.getProperty("java.home");
-            List<String> args = new ArrayList<>();
-            args.add(javaHome == null
-                    ? "java"
-                    : javaHome + File.separator + "bin" + File.separator + "java");
-            args.add("-agentlib:jdwp=transport=" + connector.transport().name() +
-                    ",address=" + addr);
-            args.addAll(remoteVMOptions);
-            args.add(remoteAgent);
-            args.add("" + port);
-            ProcessBuilder pb = new ProcessBuilder(args);
-            process = pb.start();
-
-            // Forward out, err, and in
-            // Accept the connection from the remote agent
-            vm = listener.accept(connectorArgs);
-            listener.stopListening(connectorArgs);
-            return vm;
-        } catch (Exception ex) {
-            reportLaunchFail(ex, "listen");
-        }
-        return null;
-    }
-
-    private Connector findConnector(String name) {
-        for (Connector cntor
-                : Bootstrap.virtualMachineManager().allConnectors()) {
-            if (cntor.name().equals(name)) {
-                return cntor;
-            }
-        }
-        return null;
-    }
-
-    private Map<String, Connector.Argument> mergeConnectorArgs(Connector connector, Map<String, String> argumentName2Value) {
-        Map<String, Connector.Argument> arguments = connector.defaultArguments();
-
-        for (Entry<String, String> argumentEntry : argumentName2Value.entrySet()) {
-            String name = argumentEntry.getKey();
-            String value = argumentEntry.getValue();
-            Connector.Argument argument = arguments.get(name);
-
-            if (argument == null) {
-                throw new IllegalArgumentException("Argument is not defined for connector:" +
-                        name + " -- " + connector.name());
-            }
-
-            argument.setValue(value);
-        }
-
-        return arguments;
-    }
-
-    /**
-     * The JShell specific Connector args for the LaunchingConnector.
-     *
-     * @param portthe socket port for (non-JDI) commands
-     * @param remoteVMOptions any user requested VM options
-     * @return the argument map
-     */
-    private Map<String, String> launchArgs(int port, String remoteVMOptions) {
-        Map<String, String> argumentName2Value = new HashMap<>();
-        argumentName2Value.put("main", remoteAgent + " " + port);
-        argumentName2Value.put("options", remoteVMOptions);
-        return argumentName2Value;
-    }
-
-    private void reportLaunchFail(Exception ex, String context) {
-        throw new InternalError("Failed remote " + context + ": " + connector +
-                " -- " + connectorArgs, ex);
-    }
-
-    /**
-     * Log debugging information. Arguments as for {@code printf}.
-     *
-     * @param format a format string as described in Format string syntax
-     * @param args arguments referenced by the format specifiers in the format
-     * string.
-     */
-    private void debug(String format, Object... args) {
-        // Reserved for future logging
-    }
-
-    /**
-     * Log a serious unexpected internal exception.
-     *
-     * @param ex the exception
-     * @param where a description of the context of the exception
-     */
-    private void debug(Throwable ex, String where) {
-        // Reserved for future logging
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jshell.execution;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+import com.sun.jdi.BooleanValue;
+import com.sun.jdi.ClassNotLoadedException;
+import com.sun.jdi.Field;
+import com.sun.jdi.IncompatibleThreadStateException;
+import com.sun.jdi.InvalidTypeException;
+import com.sun.jdi.ObjectReference;
+import com.sun.jdi.StackFrame;
+import com.sun.jdi.ThreadReference;
+import com.sun.jdi.VMDisconnectedException;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionEnv;
+import static jdk.jshell.execution.Util.remoteInputOutput;
+
+/**
+ * The implementation of {@link jdk.jshell.spi.ExecutionControl} that the
+ * JShell-core uses by default.
+ * Launches a remote process -- the "remote agent".
+ * Interfaces to the remote agent over a socket and via JDI.
+ * Designed to work with {@link RemoteExecutionControl}.
+ *
+ * @author Robert Field
+ * @author Jan Lahoda
+ */
+public class JdiDefaultExecutionControl extends JdiExecutionControl {
+
+    private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
+
+    private VirtualMachine vm;
+    private Process process;
+
+    private final Object STOP_LOCK = new Object();
+    private boolean userCodeRunning = false;
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code LaunchingConnector}.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator launch() {
+        return env -> create(env, true, null);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector}.
+     *
+     * @param host explicit hostname to use, if null use discovered
+     * hostname, applies to listening only (!isLaunch)
+     * @return the generator
+     */
+    public static ExecutionControl.Generator listen(String host) {
+        return env -> create(env, false, host);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector} or {@code LaunchingConnector}.
+     *
+     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
+     * commands and results. This socket also transports the user
+     * input/output/error.
+     *
+     * @param env the context passed by
+     * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
+     * otherwise we start explicitly and use ListeningConnector
+     * @param host explicit hostname to use, if null use discovered
+     * hostname, applies to listening only (!isLaunch)
+     * @return the channel
+     * @throws IOException if there are errors in set-up
+     */
+    private static ExecutionControl create(ExecutionEnv env,
+            boolean isLaunch, String host) throws IOException {
+        try (final ServerSocket listener = new ServerSocket(0)) {
+            // timeout after 60 seconds
+            listener.setSoTimeout(60000);
+            int port = listener.getLocalPort();
+
+            // Set-up the JDI connection
+            JdiInitiator jdii = new JdiInitiator(port,
+                    env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
+            VirtualMachine vm = jdii.vm();
+            Process process = jdii.process();
+
+            List<Consumer<String>> deathListeners = new ArrayList<>();
+            deathListeners.add(s -> env.closeDown());
+            Util.detectJdiExitEvent(vm, s -> {
+                for (Consumer<String> h : deathListeners) {
+                    h.accept(s);
+                }
+            });
+
+            // Set-up the commands/reslts on the socket.  Piggy-back snippet
+            // output.
+            Socket socket = listener.accept();
+            // out before in -- match remote creation so we don't hang
+            OutputStream out = socket.getOutputStream();
+            Map<String, OutputStream> outputs = new HashMap<>();
+            outputs.put("out", env.userOut());
+            outputs.put("err", env.userErr());
+            Map<String, InputStream> input = new HashMap<>();
+            input.put("in", env.userIn());
+            return remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new JdiDefaultExecutionControl(objOut, objIn, vm, process, deathListeners));
+        }
+    }
+
+    /**
+     * Create an instance.
+     *
+     * @param cmdout the output for commands
+     * @param cmdin the input for responses
+     */
+    private JdiDefaultExecutionControl(ObjectOutput cmdout, ObjectInput cmdin,
+            VirtualMachine vm, Process process, List<Consumer<String>> deathListeners) {
+        super(cmdout, cmdin);
+        this.vm = vm;
+        this.process = process;
+        deathListeners.add(s -> disposeVM());
+    }
+
+    @Override
+    public String invoke(String classname, String methodname)
+            throws RunException,
+            EngineTerminationException, InternalException {
+        String res;
+        synchronized (STOP_LOCK) {
+            userCodeRunning = true;
+        }
+        try {
+            res = super.invoke(classname, methodname);
+        } finally {
+            synchronized (STOP_LOCK) {
+                userCodeRunning = false;
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Interrupts a running remote invoke by manipulating remote variables
+     * and sending a stop via JDI.
+     *
+     * @throws EngineTerminationException the execution engine has terminated
+     * @throws InternalException an internal problem occurred
+     */
+    @Override
+    public void stop() throws EngineTerminationException, InternalException {
+        synchronized (STOP_LOCK) {
+            if (!userCodeRunning) {
+                return;
+            }
+
+            vm().suspend();
+            try {
+                OUTER:
+                for (ThreadReference thread : vm().allThreads()) {
+                    // could also tag the thread (e.g. using name), to find it easier
+                    for (StackFrame frame : thread.frames()) {
+                        if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
+                                (    "invoke".equals(frame.location().method().name())
+                                || "varValue".equals(frame.location().method().name()))) {
+                            ObjectReference thiz = frame.thisObject();
+                            Field inClientCode = thiz.referenceType().fieldByName("inClientCode");
+                            Field expectingStop = thiz.referenceType().fieldByName("expectingStop");
+                            Field stopException = thiz.referenceType().fieldByName("stopException");
+                            if (((BooleanValue) thiz.getValue(inClientCode)).value()) {
+                                thiz.setValue(expectingStop, vm().mirrorOf(true));
+                                ObjectReference stopInstance = (ObjectReference) thiz.getValue(stopException);
+
+                                vm().resume();
+                                debug("Attempting to stop the client code...\n");
+                                thread.stop(stopInstance);
+                                thiz.setValue(expectingStop, vm().mirrorOf(false));
+                            }
+
+                            break OUTER;
+                        }
+                    }
+                }
+            } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) {
+                throw new InternalException("Exception on remote stop: " + ex);
+            } finally {
+                vm().resume();
+            }
+        }
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        disposeVM();
+    }
+
+    private synchronized void disposeVM() {
+        try {
+            if (vm != null) {
+                vm.dispose(); // This could NPE, so it is caught below
+                vm = null;
+            }
+        } catch (VMDisconnectedException ex) {
+            // Ignore if already closed
+        } catch (Throwable ex) {
+            debug(ex, "disposeVM");
+        } finally {
+            if (process != null) {
+                process.destroy();
+                process = null;
+            }
+        }
+    }
+
+    @Override
+    protected synchronized VirtualMachine vm() throws EngineTerminationException {
+        if (vm == null) {
+            throw new EngineTerminationException("VM closed");
+        } else {
+            return vm;
+        }
+    }
+
+    /**
+     * Log debugging information. Arguments as for {@code printf}.
+     *
+     * @param format a format string as described in Format string syntax
+     * @param args arguments referenced by the format specifiers in the format
+     * string.
+     */
+    private static void debug(String format, Object... args) {
+        // Reserved for future logging
+    }
+
+    /**
+     * Log a serious unexpected internal exception.
+     *
+     * @param ex the exception
+     * @param where a description of the context of the exception
+     */
+    private static void debug(Throwable ex, String where) {
+        // Reserved for future logging
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiEventHandler.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,140 @@
+/*
+ * 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 jdk.jshell.execution;
+
+import java.util.function.Consumer;
+import com.sun.jdi.*;
+import com.sun.jdi.event.*;
+
+/**
+ * Handler of Java Debug Interface events.
+ * Adapted from jdb EventHandler.
+ * Only exit and disconnect events processed.
+ */
+class JdiEventHandler implements Runnable {
+
+    private final Thread thread;
+    private volatile boolean connected = true;
+    private boolean completed = false;
+    private final VirtualMachine vm;
+    private final Consumer<String> reportVMExit;
+
+    /**
+     * Creates an event handler. Start with {@code start()}.
+     *
+     * @param vm the virtual machine for which to handle events
+     * @param reportVMExit callback to report exit/disconnect
+     * (passed true if the VM has died)
+     */
+    JdiEventHandler(VirtualMachine vm, Consumer<String> reportVMExit) {
+        this.vm = vm;
+        this.reportVMExit = reportVMExit;
+        this.thread = new Thread(this, "event-handler");
+        this.thread.setDaemon(true);
+    }
+
+    /**
+     * Starts the event handler.
+     */
+    void start() {
+        thread.start();
+    }
+
+    synchronized void shutdown() {
+        connected = false;  // force run() loop termination
+        thread.interrupt();
+        while (!completed) {
+            try {wait();} catch (InterruptedException exc) {}
+        }
+    }
+
+    @Override
+    public void run() {
+        EventQueue queue = vm.eventQueue();
+        while (connected) {
+            try {
+                EventSet eventSet = queue.remove();
+                boolean resumeStoppedApp = false;
+                EventIterator it = eventSet.eventIterator();
+                while (it.hasNext()) {
+                    resumeStoppedApp |= handleEvent(it.nextEvent());
+                }
+
+                if (resumeStoppedApp) {
+                    eventSet.resume();
+                }
+            } catch (InterruptedException exc) {
+                // Do nothing. Any changes will be seen at top of loop.
+            } catch (VMDisconnectedException discExc) {
+                handleDisconnectedException();
+                break;
+            }
+        }
+        synchronized (this) {
+            completed = true;
+            notifyAll();
+        }
+    }
+
+    private boolean handleEvent(Event event) {
+        handleExitEvent(event);
+        return true;
+    }
+
+    private void handleExitEvent(Event event) {
+        if (event instanceof VMDeathEvent) {
+            reportVMExit.accept("VM Died");
+        } else if (event instanceof VMDisconnectEvent) {
+            connected = false;
+            reportVMExit.accept("VM Disconnected");
+        } else {
+            // ignore everything else
+        }
+    }
+
+    private synchronized void handleDisconnectedException() {
+        /*
+         * A VMDisconnectedException has happened while dealing with
+         * another event. We need to flush the event queue, dealing only
+         * with exit events (VMDeath, VMDisconnect) so that we terminate
+         * correctly.
+         */
+        EventQueue queue = vm.eventQueue();
+        while (connected) {
+            try {
+                EventSet eventSet = queue.remove();
+                EventIterator iter = eventSet.eventIterator();
+                while (iter.hasNext()) {
+                    handleExitEvent(iter.next());
+                }
+            } catch (InterruptedException exc) {
+                // ignore
+            } catch (InternalError exc) {
+                // ignore
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiExecutionControl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,117 @@
+/*
+ * 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.jshell.execution;
+
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+import com.sun.jdi.ReferenceType;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.spi.ExecutionControl;
+import static java.util.stream.Collectors.toMap;
+
+/**
+ * Abstract JDI implementation of {@link jdk.jshell.spi.ExecutionControl}
+ */
+public abstract class JdiExecutionControl extends StreamingExecutionControl implements ExecutionControl {
+
+    /**
+     * Mapping from class names to JDI {@link ReferenceType}.
+     */
+    private final Map<String, ReferenceType> toReferenceType = new HashMap<>();
+
+    /**
+     * Create an instance.
+     * @param out the output from the remote agent
+     * @param in the input to the remote agent
+     */
+    protected JdiExecutionControl(ObjectOutput out, ObjectInput in) {
+        super(out, in);
+    }
+
+    /**
+     * Returns the JDI {@link VirtualMachine} instance.
+     *
+     * @return the virtual machine
+     * @throws EngineTerminationException if the VM is dead/disconnected
+     */
+    protected abstract VirtualMachine vm() throws EngineTerminationException;
+
+    /**
+     * Redefine the specified classes. Where 'redefine' is, as in JDI and JVMTI,
+     * an in-place replacement of the classes (preserving class identity) --
+     * that is, existing references to the class do not need to be recompiled.
+     * This implementation uses JDI
+     * {@link com.sun.jdi.VirtualMachine#redefineClasses(java.util.Map) }.
+     * It will be unsuccessful if
+     * the signature of the class has changed (see the JDI spec). The
+     * JShell-core is designed to adapt to unsuccessful redefine.
+     */
+    @Override
+    public void redefine(ClassBytecodes[] cbcs)
+            throws ClassInstallException, EngineTerminationException {
+        try {
+            // Convert to the JDI ReferenceType to class bytes map form needed
+            // by JDI.
+            VirtualMachine vm = vm();
+            Map<ReferenceType, byte[]> rmp = Stream.of(cbcs)
+                    .collect(toMap(
+                            cbc -> referenceType(vm, cbc.name()),
+                            cbc -> cbc.bytecodes()));
+            // Attempt redefine.  Throws exceptions on failure.
+            vm().redefineClasses(rmp);
+        } catch (EngineTerminationException ex) {
+            throw ex;
+        } catch (Exception ex) {
+            throw new ClassInstallException("redefine: " + ex.getMessage(), new boolean[cbcs.length]);
+        }
+    }
+
+    /**
+     * Returns the JDI {@link ReferenceType} corresponding to the specified
+     * class name.
+     *
+     * @param vm the current JDI {@link VirtualMachine} as returned by
+     * {@code vm()}
+     * @param name the class name to look-up
+     * @return the corresponding {@link ReferenceType}
+     */
+    protected ReferenceType referenceType(VirtualMachine vm, String name) {
+        return toReferenceType.computeIfAbsent(name, n -> nameToRef(vm, n));
+    }
+
+    private static ReferenceType nameToRef(VirtualMachine vm, String name) {
+        List<ReferenceType> rtl = vm.classesByName(name);
+        if (rtl.size() != 1) {
+            return null;
+        }
+        return rtl.get(0);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiInitiator.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jshell.execution;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import com.sun.jdi.Bootstrap;
+import com.sun.jdi.VirtualMachine;
+import com.sun.jdi.connect.Connector;
+import com.sun.jdi.connect.LaunchingConnector;
+import com.sun.jdi.connect.ListeningConnector;
+
+/**
+ * Sets up a JDI connection, providing the resulting JDI {@link VirtualMachine}
+ * and the {@link Process} the remote agent is running in.
+ */
+public class JdiInitiator {
+
+    private VirtualMachine vm;
+    private Process process = null;
+    private final Connector connector;
+    private final String remoteAgent;
+    private final Map<String, com.sun.jdi.connect.Connector.Argument> connectorArgs;
+
+    /**
+     * Start the remote agent and establish a JDI connection to it.
+     *
+     * @param port the socket port for (non-JDI) commands
+     * @param remoteVMOptions any user requested VM options
+     * @param remoteAgent full class name of remote agent to launch
+     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
+     * otherwise we start explicitly and use ListeningConnector
+     * @param host explicit hostname to use, if null use discovered
+     * hostname, applies to listening only (!isLaunch)
+     */
+    public JdiInitiator(int port, List<String> remoteVMOptions, String remoteAgent,
+            boolean isLaunch, String host) {
+        this.remoteAgent = remoteAgent;
+        String connectorName
+                = isLaunch
+                        ? "com.sun.jdi.CommandLineLaunch"
+                        : "com.sun.jdi.SocketListen";
+        this.connector = findConnector(connectorName);
+        if (connector == null) {
+            throw new IllegalArgumentException("No connector named: " + connectorName);
+        }
+        Map<String, String> argumentName2Value
+                = isLaunch
+                        ? launchArgs(port, String.join(" ", remoteVMOptions))
+                        : new HashMap<>();
+        if (host != null && !isLaunch) {
+            argumentName2Value.put("localAddress", host);
+        }
+        this.connectorArgs = mergeConnectorArgs(connector, argumentName2Value);
+        this.vm = isLaunch
+                ? launchTarget()
+                : listenTarget(port, remoteVMOptions);
+
+    }
+
+    /**
+     * Returns the resulting {@code VirtualMachine} instance.
+     *
+     * @return the virtual machine
+     */
+    public VirtualMachine vm() {
+        return vm;
+    }
+
+    /**
+     * Returns the launched process.
+     *
+     * @return the remote agent process
+     */
+    public Process process() {
+        return process;
+    }
+
+    /* launch child target vm */
+    private VirtualMachine launchTarget() {
+        LaunchingConnector launcher = (LaunchingConnector) connector;
+        try {
+            VirtualMachine new_vm = launcher.launch(connectorArgs);
+            process = new_vm.process();
+            return new_vm;
+        } catch (Exception ex) {
+            reportLaunchFail(ex, "launch");
+        }
+        return null;
+    }
+
+    /**
+     * Directly launch the remote agent and connect JDI to it with a
+     * ListeningConnector.
+     */
+    private VirtualMachine listenTarget(int port, List<String> remoteVMOptions) {
+        ListeningConnector listener = (ListeningConnector) connector;
+        try {
+            // Start listening, get the JDI connection address
+            String addr = listener.startListening(connectorArgs);
+            debug("Listening at address: " + addr);
+
+            // Launch the RemoteAgent requesting a connection on that address
+            String javaHome = System.getProperty("java.home");
+            List<String> args = new ArrayList<>();
+            args.add(javaHome == null
+                    ? "java"
+                    : javaHome + File.separator + "bin" + File.separator + "java");
+            args.add("-agentlib:jdwp=transport=" + connector.transport().name() +
+                    ",address=" + addr);
+            args.addAll(remoteVMOptions);
+            args.add(remoteAgent);
+            args.add("" + port);
+            ProcessBuilder pb = new ProcessBuilder(args);
+            process = pb.start();
+
+            // Forward out, err, and in
+            // Accept the connection from the remote agent
+            vm = listener.accept(connectorArgs);
+            listener.stopListening(connectorArgs);
+            return vm;
+        } catch (Exception ex) {
+            reportLaunchFail(ex, "listen");
+        }
+        return null;
+    }
+
+    private Connector findConnector(String name) {
+        for (Connector cntor
+                : Bootstrap.virtualMachineManager().allConnectors()) {
+            if (cntor.name().equals(name)) {
+                return cntor;
+            }
+        }
+        return null;
+    }
+
+    private Map<String, Connector.Argument> mergeConnectorArgs(Connector connector, Map<String, String> argumentName2Value) {
+        Map<String, Connector.Argument> arguments = connector.defaultArguments();
+
+        for (Entry<String, String> argumentEntry : argumentName2Value.entrySet()) {
+            String name = argumentEntry.getKey();
+            String value = argumentEntry.getValue();
+            Connector.Argument argument = arguments.get(name);
+
+            if (argument == null) {
+                throw new IllegalArgumentException("Argument is not defined for connector:" +
+                        name + " -- " + connector.name());
+            }
+
+            argument.setValue(value);
+        }
+
+        return arguments;
+    }
+
+    /**
+     * The JShell specific Connector args for the LaunchingConnector.
+     *
+     * @param portthe socket port for (non-JDI) commands
+     * @param remoteVMOptions any user requested VM options
+     * @return the argument map
+     */
+    private Map<String, String> launchArgs(int port, String remoteVMOptions) {
+        Map<String, String> argumentName2Value = new HashMap<>();
+        argumentName2Value.put("main", remoteAgent + " " + port);
+        argumentName2Value.put("options", remoteVMOptions);
+        return argumentName2Value;
+    }
+
+    private void reportLaunchFail(Exception ex, String context) {
+        throw new InternalError("Failed remote " + context + ": " + connector +
+                " -- " + connectorArgs, ex);
+    }
+
+    /**
+     * Log debugging information. Arguments as for {@code printf}.
+     *
+     * @param format a format string as described in Format string syntax
+     * @param args arguments referenced by the format specifiers in the format
+     * string.
+     */
+    private void debug(String format, Object... args) {
+        // Reserved for future logging
+    }
+
+    /**
+     * Log a serious unexpected internal exception.
+     *
+     * @param ex the exception
+     * @param where a description of the context of the exception
+     */
+    private void debug(Throwable ex, String where) {
+        // Reserved for future logging
+    }
+
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/RemoteExecutionControl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -41,7 +41,7 @@
  * process). This agent loads code over a socket from the main JShell process,
  * executes the code, and other misc, Specialization of
  * {@link DirectExecutionControl} which adds stop support controlled by
- * an external process. Designed to work with {@link JDIDefaultExecutionControl}.
+ * an external process. Designed to work with {@link JdiDefaultExecutionControl}.
  *
  * @author Jan Lahoda
  * @author Robert Field
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/Util.java	Fri Nov 11 16:44:36 2016 +0100
@@ -239,9 +239,9 @@
      * @param unbiddenExitHandler the handler, which will accept the exit
      * information
      */
-    public static void detectJDIExitEvent(VirtualMachine vm, Consumer<String> unbiddenExitHandler) {
+    public static void detectJdiExitEvent(VirtualMachine vm, Consumer<String> unbiddenExitHandler) {
         if (vm.canBeModified()) {
-            new JDIEventHandler(vm, unbiddenExitHandler).start();
+            new JdiEventHandler(vm, unbiddenExitHandler).start();
         }
     }
 
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java	Fri Nov 11 16:44:36 2016 +0100
@@ -44,12 +44,13 @@
  * To install an {@code ExecutionControl}, its {@code Generator} is passed to
  * {@link jdk.jshell.JShell.Builder#executionEngine(ExecutionControl.Generator)  }.
  */
-public interface ExecutionControl {
+public interface ExecutionControl extends AutoCloseable {
 
     /**
      * Defines a functional interface for creating {@link ExecutionControl}
      * instances.
      */
+    @FunctionalInterface
     public interface Generator {
 
         /**
--- a/langtools/src/jdk.jshell/share/classes/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/src/jdk.jshell/share/classes/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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,14 +30,16 @@
  */
 module jdk.jshell {
     requires public java.compiler;
-    requires java.desktop;
     requires java.prefs;
     requires jdk.compiler;
     requires jdk.internal.le;
+    requires jdk.internal.ed;
     requires jdk.internal.opt;
     requires jdk.jdi;
 
     exports jdk.jshell;
     exports jdk.jshell.spi;
     exports jdk.jshell.execution;
+
+    uses jdk.internal.editor.spi.BuildInEditorProvider;
 }
--- a/langtools/test/Makefile	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/Makefile	Fri Nov 11 16:44:36 2016 +0100
@@ -253,7 +253,7 @@
 
 # Is the test JVM 32-bit?
 DATA_MODEL := \
-	$(shell $(JT_JAVA)/bin/java -XshowSettings:properties -version 2>&1 | \
+	$(shell $(TESTJAVA)/bin/java -XshowSettings:properties -version 2>&1 | \
 		grep 'sun\.arch\.data\.model' | \
 		awk '{print $$3}')
 ifeq ($(DATA_MODEL), 32)
--- a/langtools/test/ProblemList.txt	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/ProblemList.txt	Fri Nov 11 16:44:36 2016 +0100
@@ -55,6 +55,7 @@
 tools/javac/annotations/typeAnnotations/referenceinfos/NestedTypes.java         8057687    generic-all    emit correct byte code an attributes for type annotations
 tools/javac/warnings/suppress/TypeAnnotations.java                              8057683    generic-all    improve ordering of errors with type annotations
 tools/javac/modules/T8159439/NPEForModuleInfoWithNonZeroSuperClassTest.java     8160396    generic-all    current version of jtreg needs a new promotion to include lastes version of ASM
+tools/javac/T8132562/ClassPathWithDoubleQuotesTest.java                         8169005    windows-all
 
 ###########################################################################
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/internal/shellsupport/doc/JavadocFormatterTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,393 @@
+/*
+ * 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 8131019
+ * @summary Test JavadocFormatter
+ * @library /tools/lib
+ * @modules jdk.compiler/jdk.internal.shellsupport.doc
+ * @run testng JavadocFormatterTest
+ */
+
+import java.util.Objects;
+
+import jdk.internal.shellsupport.doc.JavadocFormatter;
+import org.testng.annotations.Test;
+
+@Test
+public class JavadocFormatterTest {
+
+    private static final String CODE_RESET = "\033[0m";
+    private static final String CODE_HIGHLIGHT = "\033[1m";
+    private static final String CODE_UNDERLINE = "\033[4m";
+
+    public void testReflow() {
+        String actual;
+        String expected;
+
+        actual = new JavadocFormatter(25, true).formatJavadoc(
+                "test",
+                "1234 1234\n1234\n1234 12345 123456789012345678901234567890 1234 1234\n1234 {@code 1234} 1234 1234\n1234 1234 123456 123456\n<b>123456</b>\n123456 123456 {@link String string} 1");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "1234 1234 1234 1234 12345\n" +
+                   "123456789012345678901234567890\n" +
+                   "1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 123456\n" +
+                   "123456 123456 123456\n" +
+                   "123456 string 1\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "@param <T> 51234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                "@param <E> 61234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                "@param shortName 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n" +
+                "@param aVeryLongName1234567890123456789012345678901234567890 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "\n" +
+                   CODE_UNDERLINE + "Type Parameters:" + CODE_RESET + "\n" +
+                   "T - 51234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "E - 61234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "\n" +
+                   CODE_UNDERLINE + "Parameters:" + CODE_RESET + "\n" +
+                   "shortName - 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234\n" +
+                   "aVeryLongName1234567890123456789012345678901234567890 - \n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "@throws ShortExcp 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n" +
+                "@throws aVeryLongException1234567890123456789012345678901234567890 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "\n" +
+                   CODE_UNDERLINE + "Thrown Exceptions:" + CODE_RESET + "\n" +
+                   "ShortExcp - 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234\n" +
+                   "aVeryLongException1234567890123456789012345678901234567890 - \n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "@return 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "\n" +
+                   CODE_UNDERLINE + "Returns:" + CODE_RESET + "\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //handling of <p>, <pre>:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 <p>1234 1234 <p>1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 <p>1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n" +
+                "<blockquote><pre>\n" +
+                "for (String data : content) {\n" +
+                "    System.err.println(data);\n" +
+                "}\n" +
+                "</pre></blockquote>\n");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234\n" +
+                   "1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234\n" +
+                   "    for (String data : content) {\n" +
+                   "        System.err.println(data);\n" +
+                   "    }\n" +
+                   "    \n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //list handling:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "<ul>" +
+                "    <li>A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</li>" +
+                "    <li>B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "    <li>C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234<ol>" +
+                "        <li>D 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</li>" +
+                "        <li>E 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234<ul>" +
+                "            <li>F 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234<ol>" +
+                "                <li>G 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "            </ol>" +
+                "        </ul>" +
+                "    </OL>" +
+                "    <LI><p>H 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 <p>1234 1234 1234 1234 1234 1234 1234<ul>" +
+                "        <li>I 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "    </ul>" +
+                "</ul> followup" +
+                "<dl>" +
+                "<dt>Term1</dt>" +
+                "<dd>A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</dd>" +
+                "<dt>Term2" +
+                "<dd>B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "<dt>Term3" +
+                "<dd>C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "</dl>" +
+                "<dl>" +
+                "<dt>TermUnfinished" +
+                "</dl> followup");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "  * A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234\n" +
+                   "  * B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234\n" +
+                   "  * C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234\n" +
+                   "     1. D 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "        1234 1234 1234 1234 1234 1234\n" +
+                   "     2. E 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "        1234 1234 1234 1234 1234 1234\n" +
+                   "          * F 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234\n" +
+                   "             1. G 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "                1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "  * H 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234\n" +
+                   "      * I 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "        1234 1234 1234 1234 1234 1234\n" +
+                   "followup\n" +
+                   CODE_HIGHLIGHT + "Term1" + CODE_RESET + "\n" +
+                   "    A 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   CODE_HIGHLIGHT + "Term2" + CODE_RESET + "\n" +
+                   "    B 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   CODE_HIGHLIGHT + "Term3" + CODE_RESET + "\n" +
+                   "    C 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   CODE_HIGHLIGHT + "TermUnfinished" + CODE_RESET + "\n" +
+                   "followup\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //sections:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "text 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "<h3>1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</h3>" +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "text 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "\n" +
+                   CODE_UNDERLINE + "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234" + CODE_RESET + "\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "1234 1234 1234 1234 1234 1234 1234 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //table:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "<table>" +
+                "<tr>" +
+                "<th>A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</th>" +
+                "<th>B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</th>" +
+                "<th>C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</th>" +
+                "</tr>" +
+                "<tr>" +
+                "<td>A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>  \n" +
+                "<td>B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "<td>C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "<tr>" +
+                "<td>A 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>" +
+                "<td>B 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>" +
+                "<td>C 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>" +
+                "</tr>" +
+                "<tr>" +
+                "<td>1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>" +
+                "<td>1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234</td>" +
+                "</table>");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "----------------------------------------------------------------\n" +
+                   "| " + CODE_HIGHLIGHT + "A 1234 1234 1234" + CODE_RESET + "   | " + CODE_HIGHLIGHT + "B 1234 1234 1234" + CODE_RESET + "   | " + CODE_HIGHLIGHT + "C 1234 1234 1234" + CODE_RESET + "   |\n" +
+                   "| " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     |\n" +
+                   "| " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     |\n" +
+                   "| " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     |\n" +
+                   "| " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     | " + CODE_HIGHLIGHT + "1234 1234 1234" + CODE_RESET + "     |\n" +
+                   "| " + CODE_HIGHLIGHT + "1234 1234" + CODE_RESET + "          | " + CODE_HIGHLIGHT + "1234 1234" + CODE_RESET + "          | " + CODE_HIGHLIGHT + "1234 1234" + CODE_RESET + "          |\n" +
+                   "----------------------------------------------------------------\n" +
+                   "| A 1234 1234 1234   | B 1234 1234 1234   | C 1234 1234 1234   |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234          | 1234 1234          | 1234 1234          |\n" +
+                   "----------------------------------------------------------------\n" +
+                   "| A 1234 1234 1234   | B 1234 1234 1234   | C 1234 1234 1234   |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234          | 1234 1234          | 1234 1234          |\n" +
+                   "----------------------------------------------------------------\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234 1234     | 1234 1234 1234     |\n" +
+                   "| 1234 1234          | 1234 1234          |\n" +
+                   "-------------------------------------------\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //no escape sequences:
+        actual = new JavadocFormatter(66, false).formatJavadoc("test",
+                "@param shortName 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n" +
+                "@param aVeryLongName1234567890123456789012345678901234567890 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 " +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234" +
+                "                 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 \n");
+
+        expected = "test\n" +
+                   "\n" +
+                   "Parameters:\n" +
+                   "shortName - 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "            1234 1234 1234 1234\n" +
+                   "aVeryLongName1234567890123456789012345678901234567890 - \n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n" +
+                   "    1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //null javadoc:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test", null);
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //stray tags:
+        for (String tag : new String[] {"li", "ol", "h3", "table", "tr", "td", "dl", "dt", "dd"}) {
+            for (boolean closing : new boolean[] {false, true}) {
+                actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                        "<" + (closing ? "/" : "") + tag + ">text");
+
+                if (!actual.contains("text")) {
+                    throw new AssertionError("Incorrect output: " + actual);
+                }
+            }
+        }
+
+        //entities:
+        actual = new JavadocFormatter(66, false).formatJavadoc("test",
+                "&alpha; &lt; &#65; &#X42; &gt; &broken; &#xFFFFFFFF; &#xFFFFFFF;\n");
+
+        expected = "test\n" +
+                   "\u03b1 < A B > &broken; &#xFFFFFFFF; &#xFFFFFFF;\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+
+        //img:
+        actual = new JavadocFormatter(66, true).formatJavadoc("test",
+                "1234 <img src='any.png' alt='text'/> 1234");
+
+        expected = CODE_HIGHLIGHT + "test" + CODE_RESET + "\n" +
+                   "1234 text 1234\n";
+
+        if (!Objects.equals(actual, expected)) {
+            throw new AssertionError("Incorrect output: " + actual);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/internal/shellsupport/doc/JavadocHelperTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,296 @@
+/*
+ * 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 8131019
+ * @summary Test JavadocHelper
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/jdk.internal.shellsupport.doc
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
+ * @run testng JavadocHelperTest
+ */
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.function.Function;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.util.ElementFilter;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+import com.sun.source.util.JavacTask;
+import jdk.internal.shellsupport.doc.JavadocHelper;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test
+public class JavadocHelperTest {
+
+    public void testJavadoc() throws Exception {
+        doTestJavadoc("",
+                      t -> t.getElements().getTypeElement("test.Super"),
+                      "Top level. ");
+        doTestJavadoc("",
+                      t -> getFirstMethod(t, "test.Super"),
+                      " javadoc1A\n" +
+                      "\n" +
+                      " @param p1 param1A\n" +
+                      " @param p2 param2A\n" +
+                      " @param p3 param3A\n" +
+                      " @throws IllegalStateException exc1A\n" +
+                      " @throws IllegalArgumentException exc2A\n" +
+                      " @throws IllegalAccessException exc3A\n" +
+                      " @return valueA\n");
+    }
+
+    private Element getFirstMethod(JavacTask task, String typeName) {
+        return ElementFilter.methodsIn(task.getElements().getTypeElement(typeName).getEnclosedElements()).get(0);
+    }
+
+    private Function<JavacTask, Element> getSubTest = t -> getFirstMethod(t, "test.Sub");
+
+    public void testInheritNoJavadoc() throws Exception {
+        doTestJavadoc("",
+                      getSubTest,
+                      " javadoc1A\n" +
+                      "\n" +
+                      " @param p1 param1A\n" +
+                      " @param p2 param2A\n" +
+                      " @param p3 param3A\n" +
+                      " @throws IllegalStateException exc1A\n" +
+                      " @throws IllegalArgumentException exc2A\n" +
+                      " @throws IllegalAccessException exc3A\n" +
+                      " @return valueA\n");
+    }
+
+    public void testInheritFull() throws Exception {
+        doTestJavadoc("    /**\n" +
+                      "     * Prefix {@inheritDoc} suffix.\n" +
+                      "     *\n" +
+                      "     * @param p1 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p2 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p3 prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalStateException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalArgumentException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalAccessException prefix {@inheritDoc} suffix\n" +
+                      "     * @return prefix {@inheritDoc} suffix\n" +
+                      "     */\n",
+                      getSubTest,
+                      " Prefix javadoc1 suffix.\n" +
+                      "\n" +
+                      " @param p1 prefix param1 suffix\n" +
+                      " @param p2 prefix param2 suffix\n" +
+                      " @param p3 prefix param3 suffix\n" +
+                      " @throws IllegalStateException prefix exc1 suffix\n" +
+                      " @throws IllegalArgumentException prefix exc2 suffix\n" +
+                      " @throws IllegalAccessException prefix exc3 suffix\n" +
+                      " @return prefix value suffix\n");
+    }
+
+    public void testInheritMissingParam() throws Exception {
+        doTestJavadoc("    /**\n" +
+                      "     * Prefix {@inheritDoc} suffix.\n" +
+                      "     *\n" +
+                      "     * @param p1 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p3 prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalStateException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalArgumentException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalAccessException prefix {@inheritDoc} suffix\n" +
+                      "     * @return prefix {@inheritDoc} suffix\n" +
+                      "     */\n",
+                      getSubTest,
+                      " Prefix javadoc1 suffix.\n" +
+                      "\n" +
+                      " @param p1 prefix param1 suffix\n" +
+                      "@param p2  param2\n" +
+                      " @param p3 prefix param3 suffix\n" +
+                      " @throws IllegalStateException prefix exc1 suffix\n" +
+                      " @throws IllegalArgumentException prefix exc2 suffix\n" +
+                      " @throws IllegalAccessException prefix exc3 suffix\n" +
+                      " @return prefix value suffix\n");
+    }
+
+    public void testInheritMissingFirstParam() throws Exception {
+        doTestJavadoc("    /**\n" +
+                      "     * Prefix {@inheritDoc} suffix.\n" +
+                      "     *\n" +
+                      "     * @param p2 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p3 prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalStateException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalArgumentException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalAccessException prefix {@inheritDoc} suffix\n" +
+                      "     * @return prefix {@inheritDoc} suffix\n" +
+                      "     */\n",
+                      getSubTest,
+                      " Prefix javadoc1 suffix.\n" +
+                      "@param p1  param1\n" +
+                      "\n" +
+                      " @param p2 prefix param2 suffix\n" +
+                      " @param p3 prefix param3 suffix\n" +
+                      " @throws IllegalStateException prefix exc1 suffix\n" +
+                      " @throws IllegalArgumentException prefix exc2 suffix\n" +
+                      " @throws IllegalAccessException prefix exc3 suffix\n" +
+                      " @return prefix value suffix\n");
+    }
+
+    public void testInheritMissingThrows() throws Exception {
+        doTestJavadoc("    /**\n" +
+                      "     * Prefix {@inheritDoc} suffix.\n" +
+                      "     *\n" +
+                      "     * @param p1 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p2 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p3 prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalStateException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalAccessException prefix {@inheritDoc} suffix\n" +
+                      "     * @return prefix {@inheritDoc} suffix\n" +
+                      "     */\n",
+                      getSubTest,
+                      " Prefix javadoc1 suffix.\n" +
+                      "\n" +
+                      " @param p1 prefix param1 suffix\n" +
+                      " @param p2 prefix param2 suffix\n" +
+                      " @param p3 prefix param3 suffix\n" +
+                      " @throws IllegalStateException prefix exc1 suffix\n" +
+                      "@throws java.lang.IllegalArgumentException  exc2\n" +
+                      " @throws IllegalAccessException prefix exc3 suffix\n" +
+                      " @return prefix value suffix\n");
+    }
+
+    public void testInheritMissingReturn() throws Exception {
+        doTestJavadoc("    /**\n" +
+                      "     * Prefix {@inheritDoc} suffix.\n" +
+                      "     *\n" +
+                      "     * @param p1 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p2 prefix {@inheritDoc} suffix\n" +
+                      "     * @param p3 prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalStateException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalArgumentException prefix {@inheritDoc} suffix\n" +
+                      "     * @throws IllegalAccessException prefix {@inheritDoc} suffix\n" +
+                      "     */\n",
+                      getSubTest,
+                      " Prefix javadoc1 suffix.\n" +
+                      "\n" +
+                      " @param p1 prefix param1 suffix\n" +
+                      " @param p2 prefix param2 suffix\n" +
+                      " @param p3 prefix param3 suffix\n" +
+                      " @throws IllegalStateException prefix exc1 suffix\n" +
+                      " @throws IllegalArgumentException prefix exc2 suffix\n" +
+                      " @throws IllegalAccessException prefix exc3 suffix\n" +
+                      "@return  value\n");
+    }
+
+
+    private void doTestJavadoc(String origJavadoc, Function<JavacTask, Element> getElement, String expectedJavadoc) throws Exception {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        String subClass =
+                "package test;\n" +
+                "public class Sub extends Super {\n" +
+                origJavadoc +
+                "    public String test(int p1, int p2, int p3) throws IllegalStateException, IllegalArgumentException, IllegalAccessException { return null;} \n" +
+                "}\n";
+        String superClass =
+                "package test;\n" +
+                "/**Top level." +
+                " */\n" +
+                "public class Super {\n" +
+                "    /**\n" +
+                "     * javadoc1A\n" +
+                "     *\n" +
+                "     * @param p1 param1A\n" +
+                "     * @param p2 param2A\n" +
+                "     * @param p3 param3A\n" +
+                "     * @throws IllegalStateException exc1A\n" +
+                "     * @throws IllegalArgumentException exc2A\n" +
+                "     * @throws IllegalAccessException exc3A\n" +
+                "     * @return valueA\n" +
+                "     */\n" +
+                "    public String test(int p1, int p2, int p3) throws IllegalStateException, IllegalArgumentException, IllegalAccessException { return null;} \n" +
+                "}\n";
+
+        Path srcZip = Paths.get("src.zip");
+
+        try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) {
+            out.putNextEntry(new JarEntry("test/Sub.java"));
+            out.write(subClass.getBytes());
+            out.putNextEntry(new JarEntry("test/Super.java"));
+            out.write(superClass.getBytes());
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        DiagnosticListener<? super JavaFileObject> noErrors = d -> {
+            if (d.getKind() == Kind.ERROR) {
+                throw new AssertionError(d.getMessage(null));
+            }
+        };
+
+        assertTrue(compiler.getTask(null, null, noErrors, Arrays.asList("-d", "."), null, Arrays.asList(new JFOImpl("Super", superClass), new JFOImpl("Sub", subClass))).call());
+
+        try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
+            fm.setLocationFromPaths(StandardLocation.CLASS_PATH, Arrays.asList(Paths.get(".").toAbsolutePath()));
+            JavacTask task = (JavacTask) compiler.getTask(null, fm, noErrors, null, null, null);
+
+            Element el = getElement.apply(task);
+
+            try (JavadocHelper helper = JavadocHelper.create(task, Arrays.asList(srcZip))) {
+                String javadoc = helper.getResolvedDocComment(el);
+
+                assertEquals(javadoc, expectedJavadoc);
+            }
+        }
+    }
+
+    private static final class JFOImpl extends SimpleJavaFileObject {
+
+        private final String code;
+
+        public JFOImpl(String name, String code) throws URISyntaxException {
+            super(new URI("mem:///" + name + ".java"), Kind.SOURCE);
+            this.code = code;
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            return code;
+        }
+
+    }
+}
--- a/langtools/test/jdk/jshell/ClassMembersTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ClassMembersTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -38,6 +38,9 @@
 import jdk.jshell.SourceCodeAnalysis;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
+import jdk.jshell.TypeDeclSnippet;
+import static jdk.jshell.Snippet.Status.OVERWRITTEN;
+import static jdk.jshell.Snippet.Status.VALID;
 
 public class ClassMembersTest extends KullaTesting {
 
@@ -141,29 +144,36 @@
                 new ExpectedDiagnostic("compiler.err.non-static.cant.be.ref", 0, 8, 1, -1, -1, Diagnostic.Kind.ERROR));
     }
 
-    @Test(enabled = false) // TODO 8080354
-    public void annotationTest() {
+    @Test(dataProvider = "retentionPolicyTestCase")
+    public void annotationTest(RetentionPolicy policy) {
         assertEval("import java.lang.annotation.*;");
+        String annotationSource =
+                "@Retention(RetentionPolicy." + policy.toString() + ")\n" +
+                "@interface A {}";
+        assertEval(annotationSource);
+        String classSource =
+                "@A class C {\n" +
+                "   @A C() {}\n" +
+                "   @A void f() {}\n" +
+                "   @A int f;\n" +
+                "   @A class Inner {}\n" +
+                "}";
+        assertEval(classSource);
+        String isRuntimeVisible = policy == RetentionPolicy.RUNTIME ? "true" : "false";
+        assertEval("C.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+        assertEval("C.class.getDeclaredConstructor().getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+        assertEval("C.class.getDeclaredMethod(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+        assertEval("C.class.getDeclaredField(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+        assertEval("C.Inner.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+    }
+
+    @DataProvider(name = "retentionPolicyTestCase")
+    public Object[][] retentionPolicyTestCaseGenerator() {
+        List<Object[]> list = new ArrayList<>();
         for (RetentionPolicy policy : RetentionPolicy.values()) {
-            String annotationSource =
-                    "@Retention(RetentionPolicy." + policy.toString() + ")\n" +
-                    "@interface A {}";
-            assertEval(annotationSource);
-            String classSource =
-                    "@A class C {\n" +
-                    "   @A C() {}\n" +
-                    "   @A void f() {}\n" +
-                    "   @A int f;\n" +
-                    "   @A class Inner {}\n" +
-                    "}";
-            assertEval(classSource);
-            String isRuntimeVisible = policy == RetentionPolicy.RUNTIME ? "true" : "false";
-            assertEval("C.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
-            assertEval("C.class.getDeclaredConstructor().getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
-            assertEval("C.class.getDeclaredMethod(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
-            assertEval("C.class.getDeclaredField(\"f\").getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
-            assertEval("C.Inner.class.getAnnotationsByType(A.class).length > 0;", isRuntimeVisible);
+            list.add(new Object[]{policy});
         }
+        return list.toArray(new Object[list.size()][]);
     }
 
     @DataProvider(name = "memberTestCase")
--- a/langtools/test/jdk/jshell/ClassesTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ClassesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8145239
+ * @bug 8145239 8129559 8080354
  * @summary Tests for EvaluationState.classes
  * @build KullaTesting TestingInputStream ExpectedDiagnostic
  * @run testng ClassesTest
@@ -247,14 +247,30 @@
     }
 
     public void classesIgnoredModifiers() {
-        assertDeclareWarn1("public interface A { }",
-                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
+        assertEval("public interface A { }");
         assertDeclareWarn1("static class B implements A { }",
                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
         assertDeclareWarn1("final interface C extends A { }",
                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING));
-        assertDeclareWarn1("protected enum D implements C { }",
+        assertActiveKeys();
+    }
+
+    public void classesIgnoredModifiersAnnotation() {
+        assertEval("public @interface X { }");
+        assertEval("@X public interface A { }");
+        assertDeclareWarn1("@X static class B implements A { }",
                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
+        assertDeclareWarn1("@X final interface C extends A { }",
+                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 8, 0, -1, -1, Diagnostic.Kind.WARNING));
+        assertActiveKeys();
+    }
+
+    public void classesIgnoredModifiersOtherModifiers() {
+        assertEval("strictfp public interface A { }");
+        assertDeclareWarn1("strictfp static class B implements A { }",
+                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING));
+        assertDeclareWarn1("strictfp final interface C extends A { }",
+                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 14, 0, -1, -1, Diagnostic.Kind.WARNING));
         assertActiveKeys();
     }
 
--- a/langtools/test/jdk/jshell/CompletenessTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/CompletenessTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8149524 8131024 8165211 8080071 8130454 8167343
+ * @bug 8149524 8131024 8165211 8080071 8130454 8167343 8129559
  * @summary Test SourceCodeAnalysis
  * @build KullaTesting TestingInputStream
  * @run testng CompletenessTest
@@ -176,6 +176,7 @@
         "@interface Anno",
         "void f()",
         "void f() throws E",
+        "@A(",
     };
 
     static final String[] unknown = new String[] {
--- a/langtools/test/jdk/jshell/CompletionSuggestionTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/CompletionSuggestionTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,12 +23,12 @@
 
 /*
  * @test
- * @bug 8131025 8141092 8153761 8145263
+ * @bug 8131025 8141092 8153761 8145263 8131019
  * @summary Test Completion and Documentation
+ * @library /tools/lib
  * @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 toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
  * @build KullaTesting TestingInputStream Compiler
  * @run testng CompletionSuggestionTest
@@ -305,26 +305,26 @@
 
     public void testDocumentation() throws Exception {
         dontReadParameterNamesFromClassFile();
-        assertDocumentation("System.getProperty(|",
+        assertSignature("System.getProperty(|",
                 "String System.getProperty(String key)",
                 "String System.getProperty(String key, String def)");
         assertEval("char[] chars = null;");
-        assertDocumentation("new String(chars, |",
+        assertSignature("new String(chars, |",
                 "String(char[], int, int)");
-        assertDocumentation("String.format(|",
+        assertSignature("String.format(|",
                 "String String.format(String, Object...)",
                 "String String.format(java.util.Locale, String, Object...)");
-        assertDocumentation("\"\".getBytes(\"\"|", "void String.getBytes(int, int, byte[], int)",
+        assertSignature("\"\".getBytes(\"\"|", "void String.getBytes(int, int, byte[], int)",
                                                     "byte[] String.getBytes(String) throws java.io.UnsupportedEncodingException",
                                                     "byte[] String.getBytes(java.nio.charset.Charset)");
-        assertDocumentation("\"\".getBytes(\"\" |", "void String.getBytes(int, int, byte[], int)",
+        assertSignature("\"\".getBytes(\"\" |", "void String.getBytes(int, int, byte[], int)",
                                                      "byte[] String.getBytes(String) throws java.io.UnsupportedEncodingException",
                                                      "byte[] String.getBytes(java.nio.charset.Charset)");
     }
 
     public void testMethodsWithNoArguments() throws Exception {
         dontReadParameterNamesFromClassFile();
-        assertDocumentation("System.out.println(|",
+        assertSignature("System.out.println(|",
                 "void java.io.PrintStream.println()",
                 "void java.io.PrintStream.println(boolean)",
                 "void java.io.PrintStream.println(char)",
@@ -339,6 +339,7 @@
 
     public void testErroneous() {
         assertCompletion("Undefined.|");
+        assertSignature("does.not.exist|");
     }
 
     public void testClinit() {
@@ -474,59 +475,63 @@
 
     public void testDocumentationOfUserDefinedMethods() {
         assertEval("void f() {}");
-        assertDocumentation("f(|", "void f()");
+        assertSignature("f(|", "void f()");
         assertEval("void f(int i) {}");
-        assertDocumentation("f(|", "void f()", "void f(int i)");
+        assertSignature("f(|", "void f()", "void f(int i)");
         assertEval("<T> void f(T... ts) {}", DiagCheck.DIAG_WARNING, DiagCheck.DIAG_OK);
-        assertDocumentation("f(|", "void f()", "void f(int i)", "void <T>f(T... ts)");
+        assertSignature("f(|", "void f()", "void f(int i)", "void <T>f(T... ts)");
         assertEval("class A {}");
         assertEval("void f(A a) {}");
-        assertDocumentation("f(|", "void f()", "void f(int i)", "void <T>f(T... ts)", "void f(A a)");
+        assertSignature("f(|", "void f()", "void f(int i)", "void <T>f(T... ts)", "void f(A a)");
+    }
+
+    public void testClass() {
+        assertSignature("String|", "java.lang.String");
     }
 
     public void testDocumentationOfUserDefinedConstructors() {
         Snippet a = classKey(assertEval("class A {}"));
-        assertDocumentation("new A(|", "A()");
+        assertSignature("new A(|", "A()");
         Snippet a2 = classKey(assertEval("class A { A() {} A(int i) {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
-        assertDocumentation("new A(|", "A()", "A(int i)");
+        assertSignature("new A(|", "A()", "A(int i)");
         assertEval("class A<T> { A(T a) {} A(int i) {} <U> A(T t, U u) {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(a2, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertDocumentation("new A(|", "A<T>(T a)", "A<T>(int i)", "<U> A<T>(T t, U u)");
+        assertSignature("new A(|", "A<T>(T a)", "A<T>(int i)", "<U> A<T>(T t, U u)");
     }
 
     public void testDocumentationOfOverriddenMethods() throws Exception {
         dontReadParameterNamesFromClassFile();
-        assertDocumentation("\"\".wait(|",
+        assertSignature("\"\".wait(|",
             "void Object.wait(long) throws InterruptedException",
             "void Object.wait(long, int) throws InterruptedException",
             "void Object.wait() throws InterruptedException");
         assertEval("class Base {void method() {}}");
         Snippet e = classKey(assertEval("class Extend extends Base {}"));
-        assertDocumentation("new Extend().method(|", "void Base.method()");
+        assertSignature("new Extend().method(|", "void Base.method()");
         assertEval("class Extend extends Base {void method() {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(e, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertDocumentation("new Extend().method(|", "void Extend.method()");
+        assertSignature("new Extend().method(|", "void Extend.method()");
     }
 
     public void testDocumentationOfInvisibleMethods() {
-        assertDocumentation("Object.wait(|", "");
-        assertDocumentation("\"\".indexOfSupplementary(|", "");
+        assertSignature("Object.wait(|");
+        assertSignature("\"\".indexOfSupplementary(|");
         Snippet a = classKey(assertEval("class A {void method() {}}"));
-        assertDocumentation("A.method(|", "");
+        assertSignature("A.method(|");
         assertEval("class A {private void method() {}}",
                 ste(MAIN_SNIPPET, VALID, VALID, true, null),
                 ste(a, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertDocumentation("new A().method(|", "");
+        assertSignature("new A().method(|");
     }
 
     public void testDocumentationOfInvisibleConstructors() {
-        assertDocumentation("new Compiler(|", "");
+        assertSignature("new Compiler(|");
         assertEval("class A { private A() {} }");
-        assertDocumentation("new A(|", "");
+        assertSignature("new A(|");
     }
 
     public void testDocumentationWithBoxing() {
@@ -535,13 +540,13 @@
         assertEval("Object object = null;");
         assertEval("void method(int n, Object o) { }");
         assertEval("void method(Object n, int o) { }");
-        assertDocumentation("method(primitive,|",
+        assertSignature("method(primitive,|",
                 "void method(int n, Object o)",
                 "void method(Object n, int o)");
-        assertDocumentation("method(boxed,|",
+        assertSignature("method(boxed,|",
                 "void method(int n, Object o)",
                 "void method(Object n, int o)");
-        assertDocumentation("method(object,|",
+        assertSignature("method(object,|",
                 "void method(Object n, int o)");
     }
 
@@ -567,7 +572,7 @@
 
             void assertDoc(String generics, String expectedGenerics) {
                 assertEval(evalFormatter.apply(generics, count));
-                assertDocumentation(codeFacotry.apply(count), docFormatter.apply(expectedGenerics, count));
+                assertSignature(codeFacotry.apply(count), docFormatter.apply(expectedGenerics, count));
                 count++;
             }
         }
--- a/langtools/test/jdk/jshell/EditorPadTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8139872
- * @summary Testing built-in editor.
- * @modules java.desktop/java.awt
- *          jdk.jshell/jdk.internal.jshell.tool
- * @build ReplToolTesting EditorTestBase
- * @run testng EditorPadTest
- */
-
-import java.awt.AWTException;
-import java.awt.Component;
-import java.awt.Container;
-import java.awt.Dimension;
-import java.awt.Frame;
-import java.awt.GraphicsEnvironment;
-import java.awt.Point;
-import java.awt.Robot;
-import java.awt.event.InputEvent;
-import java.awt.event.WindowEvent;
-import java.lang.reflect.InvocationTargetException;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.function.Consumer;
-
-import javax.swing.JButton;
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JViewport;
-import javax.swing.SwingUtilities;
-
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-public class EditorPadTest extends EditorTestBase {
-
-    private static final int DELAY = 500;
-
-    private static Robot robot;
-    private static JFrame frame = null;
-    private static JTextArea area = null;
-    private static JButton cancel = null;
-    private static JButton accept = null;
-    private static JButton exit = null;
-
-    // Do not actually run if we are headless
-    @Override
-    public void testEditor(boolean defaultStartup, String[] args, ReplTest... tests) {
-        if (!GraphicsEnvironment.isHeadless()) {
-            test(defaultStartup, args, tests);
-        }
-    }
-
-    @BeforeClass
-    public static void setUpEditorPadTest() {
-        if (!GraphicsEnvironment.isHeadless()) {
-            try {
-                robot = new Robot();
-                robot.setAutoWaitForIdle(true);
-                robot.setAutoDelay(DELAY);
-            } catch (AWTException e) {
-                throw new ExceptionInInitializerError(e);
-            }
-        }
-    }
-
-    @AfterClass
-    public static void shutdown() {
-        executorShutdown();
-    }
-
-    @Override
-    public void writeSource(String s) {
-        SwingUtilities.invokeLater(() -> area.setText(s));
-    }
-
-    @Override
-    public String getSource() {
-        try {
-            String[] s = new String[1];
-            SwingUtilities.invokeAndWait(() -> s[0] = area.getText());
-            return s[0];
-        } catch (InvocationTargetException | InterruptedException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    @Override
-    public void accept() {
-        clickOn(accept);
-    }
-
-    @Override
-    public void exit() {
-        clickOn(exit);
-    }
-
-    @Override
-    public void cancel() {
-        clickOn(cancel);
-    }
-
-    @Override
-    public void shutdownEditor() {
-        SwingUtilities.invokeLater(this::clearElements);
-        waitForIdle();
-    }
-
-    @Test
-    public void testShuttingDown() {
-        testEditor(
-                (a) -> assertEditOutput(a, "/ed", "", this::shutdownEditor)
-        );
-    }
-
-    private void waitForIdle() {
-        robot.waitForIdle();
-        robot.delay(DELAY);
-    }
-
-    private Future<?> task;
-    @Override
-    public void assertEdit(boolean after, String cmd,
-                           Consumer<String> checkInput, Consumer<String> checkOutput, Action action) {
-        if (!after) {
-            setCommandInput(cmd + "\n");
-            task = getExecutor().submit(() -> {
-                try {
-                    waitForIdle();
-                    SwingUtilities.invokeLater(this::seekElements);
-                    waitForIdle();
-                    checkInput.accept(getSource());
-                    action.accept();
-                } catch (Throwable e) {
-                    shutdownEditor();
-                    if (e instanceof AssertionError) {
-                        throw (AssertionError) e;
-                    }
-                    throw new RuntimeException(e);
-                }
-            });
-        } else {
-            try {
-                task.get();
-                waitForIdle();
-                checkOutput.accept(getCommandOutput());
-            } catch (ExecutionException e) {
-                if (e.getCause() instanceof AssertionError) {
-                    throw (AssertionError) e.getCause();
-                }
-                throw new RuntimeException(e);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            } finally {
-                shutdownEditor();
-            }
-        }
-    }
-
-    private void seekElements() {
-        for (Frame f : Frame.getFrames()) {
-            if (f.getTitle().contains("Edit Pad")) {
-                frame = (JFrame) f;
-                // workaround
-                frame.setLocation(0, 0);
-                Container root = frame.getContentPane();
-                for (Component c : root.getComponents()) {
-                    if (c instanceof JScrollPane) {
-                        JScrollPane scrollPane = (JScrollPane) c;
-                        for (Component comp : scrollPane.getComponents()) {
-                            if (comp instanceof JViewport) {
-                                JViewport view = (JViewport) comp;
-                                area = (JTextArea) view.getComponent(0);
-                            }
-                        }
-                    }
-                    if (c instanceof JPanel) {
-                        JPanel p = (JPanel) c;
-                        for (Component comp : p.getComponents()) {
-                            if (comp instanceof JButton) {
-                                JButton b = (JButton) comp;
-                                switch (b.getText()) {
-                                    case "Cancel":
-                                        cancel = b;
-                                        break;
-                                    case "Exit":
-                                        exit = b;
-                                        break;
-                                    case "Accept":
-                                        accept = b;
-                                        break;
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    private void clearElements() {
-        if (frame != null) {
-            frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
-            frame = null;
-        }
-        area = null;
-        accept = null;
-        cancel = null;
-        exit = null;
-    }
-
-    private void clickOn(JButton button) {
-        waitForIdle();
-        Point p = button.getLocationOnScreen();
-        Dimension d = button.getSize();
-        robot.mouseMove(p.x + d.width / 2, p.y + d.height / 2);
-        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
-        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
-    }
-}
--- a/langtools/test/jdk/jshell/ErrorTranslationTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ErrorTranslationTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -63,11 +63,8 @@
         List<ReplTest> list = new ArrayList<>();
         ExpectedDiagnostic[] diagnostics = new ExpectedDiagnostic[]{
                 newExpectedDiagnostic(0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
-                newExpectedDiagnostic(0, 9, 0, -1, -1, Diagnostic.Kind.WARNING),
-                newExpectedDiagnostic(0, 7, 0, -1, -1, Diagnostic.Kind.WARNING),
-                newExpectedDiagnostic(0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
                 newExpectedDiagnostic(0, 5, 0, -1, -1, Diagnostic.Kind.WARNING)};
-        String[] mods = {"public", "protected", "private", "static", "final"};
+        String[] mods = {"static", "final"};
         for (int i = 0; i < mods.length; ++i) {
             for (String code : new String[] {"class A {}", "void f() {}", "int a;"}) {
                 final int finalI = i;
--- a/langtools/test/jdk/jshell/FailOverExecutionControlTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/FailOverExecutionControlTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,7 +33,7 @@
 
 import org.testng.annotations.Test;
 import org.testng.annotations.BeforeMethod;
-import jdk.jshell.execution.JDIDefaultExecutionControl;
+import jdk.jshell.execution.JdiDefaultExecutionControl;
 import jdk.jshell.spi.ExecutionControl;
 import jdk.jshell.spi.ExecutionEnv;
 import static jdk.jshell.execution.Util.failOverExecutionControlGenerator;
@@ -47,7 +47,7 @@
         setUp(builder -> builder.executionEngine(failOverExecutionControlGenerator(
                 new AlwaysFailingGenerator(),
                 new AlwaysFailingGenerator(),
-                JDIDefaultExecutionControl.launch())));
+                JdiDefaultExecutionControl.launch())));
     }
 
     class AlwaysFailingGenerator implements ExecutionControl.Generator {
--- a/langtools/test/jdk/jshell/IgnoreTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/IgnoreTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -22,7 +22,7 @@
  */
 
 /*
- * @test
+ * @test 8129559
  * @summary Test the ignoring of comments and certain modifiers
  * @build KullaTesting TestingInputStream
  * @run testng IgnoreTest
@@ -58,38 +58,67 @@
     }
 
     public void testVarModifier() {
-        VarSnippet x1 = (VarSnippet) assertDeclareWarn1("public int x1;", "jdk.eval.warn.illegal.modifiers");
-        assertVariableDeclSnippet(x1, "x1", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
-        VarSnippet x2 = (VarSnippet) assertDeclareWarn1("protected int x2;", "jdk.eval.warn.illegal.modifiers");
-        assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
-        VarSnippet x3 = (VarSnippet) assertDeclareWarn1("private int x3;", "jdk.eval.warn.illegal.modifiers");
-        assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
+        VarSnippet x1 = varKey(assertEval("public int x1;"));
+        assertVariableDeclSnippet(x1, "x1", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x2 = varKey(assertEval("protected int x2;"));
+        assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x3 = varKey(assertEval("private int x3;"));
+        assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
         VarSnippet x4 = (VarSnippet) assertDeclareWarn1("static int x4;", "jdk.eval.warn.illegal.modifiers");
         assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
         VarSnippet x5 = (VarSnippet) assertDeclareWarn1("final int x5;", "jdk.eval.warn.illegal.modifiers");
         assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
     }
 
+    public void testVarModifierAnnotation() {
+        assertEval("@interface A { int value() default 0; }");
+        VarSnippet x1 = varKey(assertEval("@A public int x1;"));
+        assertVariableDeclSnippet(x1, "x1", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x2 = varKey(assertEval("@A(14) protected int x2;"));
+        assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x3 = varKey(assertEval("@A(value=111)private int x3;"));
+        assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x4 = (VarSnippet) assertDeclareWarn1("@A static int x4;", "jdk.eval.warn.illegal.modifiers");
+        assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
+        VarSnippet x5 = (VarSnippet) assertDeclareWarn1("@A(1111) final int x5;", "jdk.eval.warn.illegal.modifiers");
+        assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
+    }
+
+    public void testVarModifierOtherModifier() {
+        VarSnippet x1 = varKey(assertEval("volatile public int x1;"));
+        assertVariableDeclSnippet(x1, "x1", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x2 = varKey(assertEval("transient protected int x2;"));
+        assertVariableDeclSnippet(x2, "x2", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x3 = varKey(assertEval("transient private int x3;"));
+        assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
+        VarSnippet x4 = (VarSnippet) assertDeclareWarn1("volatile static int x4;", "jdk.eval.warn.illegal.modifiers");
+        assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
+        VarSnippet x5 = (VarSnippet) assertDeclareWarn1("transient final int x5;", "jdk.eval.warn.illegal.modifiers");
+        assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
+    }
+
+    public void testMisplacedIgnoredModifier() {
+        assertEvalFail("int public y;");
+        assertEvalFail("String private x;");
+        assertEvalFail("(protected 34);");
+    }
+
     public void testMethodModifier() {
-        MethodSnippet m1 = (MethodSnippet) assertDeclareWarn1("public void m1() {}", "jdk.eval.warn.illegal.modifiers");
-        assertMethodDeclSnippet(m1, "m1", "()void", VALID, 0, 1);
-        MethodSnippet m2 = (MethodSnippet) assertDeclareWarn1("protected void m2() {}", "jdk.eval.warn.illegal.modifiers");
-        assertMethodDeclSnippet(m2, "m2", "()void", VALID, 0, 1);
-        MethodSnippet m3 = (MethodSnippet) assertDeclareWarn1("private void m3() {}", "jdk.eval.warn.illegal.modifiers");
-        assertMethodDeclSnippet(m3, "m3", "()void", VALID, 0, 1);
         MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("static void m4() {}", "jdk.eval.warn.illegal.modifiers");
         assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
         MethodSnippet m5 = (MethodSnippet) assertDeclareWarn1("final void m5() {}", "jdk.eval.warn.illegal.modifiers");
         assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 1);
     }
 
+    public void testMethodModifierAnnotation() {
+        assertEval("@interface A { int value() default 0; }");
+        MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("@A static void m4() {}", "jdk.eval.warn.illegal.modifiers");
+        assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
+        MethodSnippet m5 = (MethodSnippet) assertDeclareWarn1("@A(value=66)final void m5() {}", "jdk.eval.warn.illegal.modifiers");
+        assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 1);
+    }
+
     public void testClassModifier() {
-        TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareWarn1("public class C1 {}", "jdk.eval.warn.illegal.modifiers");
-        assertTypeDeclSnippet(c1, "C1", VALID, CLASS_SUBKIND, 0, 1);
-        TypeDeclSnippet c2 = (TypeDeclSnippet) assertDeclareWarn1("protected class C2 {}", "jdk.eval.warn.illegal.modifiers");
-        assertTypeDeclSnippet(c2, "C2", VALID, CLASS_SUBKIND, 0, 1);
-        TypeDeclSnippet c3 = (TypeDeclSnippet) assertDeclareWarn1("private class C3 {}", "jdk.eval.warn.illegal.modifiers");
-        assertTypeDeclSnippet(c3, "C3", VALID, CLASS_SUBKIND, 0, 1);
         TypeDeclSnippet c4 = (TypeDeclSnippet) assertDeclareWarn1("static class C4 {}", "jdk.eval.warn.illegal.modifiers");
         assertTypeDeclSnippet(c4, "C4", VALID, CLASS_SUBKIND, 0, 1);
         TypeDeclSnippet c5 = (TypeDeclSnippet) assertDeclareWarn1("final class C5 {}", "jdk.eval.warn.illegal.modifiers");
--- a/langtools/test/jdk/jshell/JDILaunchingExecutionControlTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8164518
- * @summary Tests for standard JDI connector (without failover) -- launching
- * @modules jdk.jshell/jdk.jshell.execution
- * @build KullaTesting ExecutionControlTestBase
- * @run testng JDILaunchingExecutionControlTest
- */
-
-
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import jdk.jshell.execution.JDIDefaultExecutionControl;
-
-@Test
-public class JDILaunchingExecutionControlTest extends ExecutionControlTestBase {
-
-    @BeforeMethod
-    @Override
-    public void setUp() {
-        setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.launch()));
-    }
-}
--- a/langtools/test/jdk/jshell/JDIListeningExecutionControlTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8131029 8159935 8160127 8164518
- * @summary Tests for alternate JDI connector -- listening
- * @modules jdk.jshell/jdk.jshell.execution
- * @build KullaTesting ExecutionControlTestBase
- * @run testng JDIListeningExecutionControlTest
- */
-
-
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import jdk.jshell.execution.JDIDefaultExecutionControl;
-
-@Test
-public class JDIListeningExecutionControlTest extends ExecutionControlTestBase {
-
-    @BeforeMethod
-    @Override
-    public void setUp() {
-        setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen(null)));
-    }
-}
--- a/langtools/test/jdk/jshell/JDIListeningLocalhostExecutionControlTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * @test
- * @bug 8164518
- * @summary Tests for alternate JDI connector -- listening to "localhost"
- * @modules jdk.jshell/jdk.jshell.execution
- * @build KullaTesting ExecutionControlTestBase
- * @run testng JDIListeningLocalhostExecutionControlTest
- */
-
-
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import jdk.jshell.execution.JDIDefaultExecutionControl;
-
-@Test
-public class JDIListeningLocalhostExecutionControlTest extends ExecutionControlTestBase {
-
-    @BeforeMethod
-    @Override
-    public void setUp() {
-        setUp(builder -> builder.executionEngine(JDIDefaultExecutionControl.listen("localhost")));
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/JavadocTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,105 @@
+/*
+ * 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 8131019
+ * @summary Test Javadoc
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.jshell
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask
+ * @build KullaTesting TestingInputStream Compiler
+ * @run testng JavadocTest
+ */
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import org.testng.annotations.Test;
+
+@Test
+public class JavadocTest extends KullaTesting {
+
+    private final Compiler compiler = new Compiler();
+
+    public void testJavadoc() {
+        prepareZip();
+        assertJavadoc("test.Clazz|", "test.Clazz\n" +
+                                     "Top level. ");
+        assertEval("test.Clazz clz = null;");
+        assertJavadoc("clz.test(|", "String test.Clazz.test(int p) throws IllegalStateException\n" +
+                                    " javadoc1A\n" +
+                                    "\n" +
+                                    " @param p param\n" +
+                                    " @throws IllegalStateException exc\n" +
+                                    " @return value\n");
+        //undefined handling:
+        assertJavadoc("clz.undef|");
+    }
+
+    private void prepareZip() {
+        String clazz =
+                "package test;\n" +
+                "/**Top level." +
+                " */\n" +
+                "public class Clazz {\n" +
+                "    /**\n" +
+                "     * javadoc1A\n" +
+                "     *\n" +
+                "     * @param p param\n" +
+                "     * @throws IllegalStateException exc\n" +
+                "     * @return value\n" +
+                "     */\n" +
+                "    public String test(int p) throws IllegalStateException { return null;}\n" +
+                "}\n";
+
+        Path srcZip = Paths.get("src.zip");
+
+        try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(srcZip))) {
+            out.putNextEntry(new JarEntry("test/Clazz.java"));
+            out.write(clazz.getBytes());
+        } catch (IOException ex) {
+            throw new IllegalStateException(ex);
+        }
+
+        compiler.compile(clazz);
+
+        try {
+            Field availableSources = getAnalysis().getClass().getDeclaredField("availableSources");
+            availableSources.setAccessible(true);
+            availableSources.set(getAnalysis(), Arrays.asList(srcZip));
+        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException ex) {
+            throw new IllegalStateException(ex);
+        }
+        addToClasspath(compiler.getClassDir());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/JdiLaunchingExecutionControlTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8164518
+ * @summary Tests for standard JDI connector (without failover) -- launching
+ * @modules jdk.jshell/jdk.jshell.execution
+ * @build KullaTesting ExecutionControlTestBase
+ * @run testng JdiLaunchingExecutionControlTest
+ */
+
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.execution.JdiDefaultExecutionControl;
+
+@Test
+public class JdiLaunchingExecutionControlTest extends ExecutionControlTestBase {
+
+    @BeforeMethod
+    @Override
+    public void setUp() {
+        setUp(builder -> builder.executionEngine(JdiDefaultExecutionControl.launch()));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/JdiListeningExecutionControlTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8131029 8159935 8160127 8164518
+ * @summary Tests for alternate JDI connector -- listening
+ * @modules jdk.jshell/jdk.jshell.execution
+ * @build KullaTesting ExecutionControlTestBase
+ * @run testng JdiListeningExecutionControlTest
+ */
+
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.execution.JdiDefaultExecutionControl;
+
+@Test
+public class JdiListeningExecutionControlTest extends ExecutionControlTestBase {
+
+    @BeforeMethod
+    @Override
+    public void setUp() {
+        setUp(builder -> builder.executionEngine(JdiDefaultExecutionControl.listen(null)));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/JdiListeningLocalhostExecutionControlTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/*
+ * @test
+ * @bug 8164518
+ * @summary Tests for alternate JDI connector -- listening to "localhost"
+ * @modules jdk.jshell/jdk.jshell.execution
+ * @build KullaTesting ExecutionControlTestBase
+ * @run testng JdiListeningLocalhostExecutionControlTest
+ */
+
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.execution.JdiDefaultExecutionControl;
+
+@Test
+public class JdiListeningLocalhostExecutionControlTest extends ExecutionControlTestBase {
+
+    @BeforeMethod
+    @Override
+    public void setUp() {
+        setUp(builder -> builder.executionEngine(JdiDefaultExecutionControl.listen("localhost")));
+    }
+}
--- a/langtools/test/jdk/jshell/KullaTesting.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/KullaTesting.java	Fri Nov 11 16:44:36 2016 +0100
@@ -72,11 +72,14 @@
 import org.testng.annotations.BeforeMethod;
 
 import jdk.jshell.Diag;
+
 import static java.util.stream.Collectors.toList;
 import static java.util.stream.Collectors.toSet;
+
 import static jdk.jshell.Snippet.Status.*;
 import static org.testng.Assert.*;
 import static jdk.jshell.Snippet.SubKind.METHOD_SUBKIND;
+import jdk.jshell.SourceCodeAnalysis.Documentation;
 
 public class KullaTesting {
 
@@ -946,54 +949,56 @@
         }
     }
 
-    public void assertDocumentation(String code, String... expected) {
+    public void assertSignature(String code, String... expected) {
         int cursor =  code.indexOf('|');
         code = code.replace("|", "");
         assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
-        String documentation = getAnalysis().documentation(code, cursor);
-        Set<String> docSet = Stream.of(documentation.split("\r?\n")).collect(Collectors.toSet());
+        List<Documentation> documentation = getAnalysis().documentation(code, cursor, false);
+        Set<String> docSet = documentation.stream().map(doc -> doc.signature()).collect(Collectors.toSet());
+        Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet());
+        assertEquals(docSet, expectedSet, "Input: " + code);
+    }
+
+    public void assertJavadoc(String code, String... expected) {
+        int cursor =  code.indexOf('|');
+        code = code.replace("|", "");
+        assertTrue(cursor > -1, "'|' expected, but not found in: " + code);
+        List<Documentation> documentation = getAnalysis().documentation(code, cursor, true);
+        Set<String> docSet = documentation.stream()
+                                          .map(doc -> doc.signature() + "\n" + doc.javadoc())
+                                          .collect(Collectors.toSet());
         Set<String> expectedSet = Stream.of(expected).collect(Collectors.toSet());
         assertEquals(docSet, expectedSet, "Input: " + code);
     }
 
     public enum ClassType {
-        CLASS("CLASS_SUBKIND") {
-            @Override
-            public String toString() {
-                return "class";
-            }
-        },
-        ENUM("ENUM_SUBKIND") {
-            @Override
-            public String toString() {
-                return "enum";
-            }
-        },
-        INTERFACE("INTERFACE_SUBKIND") {
-            @Override
-            public String toString() {
-                return "interface";
-            }
-        },
-        ANNOTATION("ANNOTATION_TYPE_SUBKIND") {
-            @Override
-            public String toString() {
-                return "@interface";
-            }
-        };
+        CLASS("CLASS_SUBKIND", "class", "class"),
+        ENUM("ENUM_SUBKIND", "enum", "enum"),
+        INTERFACE("INTERFACE_SUBKIND", "interface", "interface"),
+        ANNOTATION("ANNOTATION_TYPE_SUBKIND", "@interface", "annotation interface");
 
         private final String classType;
+        private final String name;
+        private final String displayed;
 
-        ClassType(String classType) {
+        ClassType(String classType, String name, String displayed) {
             this.classType = classType;
+            this.name = name;
+            this.displayed = displayed;
         }
 
         public String getClassType() {
             return classType;
         }
 
+        public String getDisplayed() {
+            return displayed;
+        }
+
         @Override
-        public abstract String toString();
+        public String toString() {
+            return name;
+        }
     }
 
     public static MemberInfo variable(String type, String name) {
--- a/langtools/test/jdk/jshell/MethodsTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/MethodsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8080357
+ * @bug 8080357 8167643
  * @summary Tests for EvaluationState.methods
  * @build KullaTesting TestingInputStream ExpectedDiagnostic
  * @run testng MethodsTest
@@ -230,31 +230,30 @@
         assertActiveKeys();
     }
 
-    public void methodsWarn() {
-        Snippet f = assertDeclareWarn1("public String f() {return null;}",
-                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
-                added(VALID));
+
+    public void methodsAccessModifierIgnored() {
+        Snippet f = methodKey(assertEval("public String f() {return null;}",
+                added(VALID)));
         assertNumberOfActiveMethods(1);
         assertActiveKeys();
 
-        f = assertDeclareWarn1("protected String f() {return null;}",
-                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING),
+        f = methodKey(assertEval("protected String f() {return null;}",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET)));
+        assertNumberOfActiveMethods(1);
+        assertActiveKeys();
+
+        assertEval("private String f() {return null;}",
                 ste(MAIN_SNIPPET, VALID, VALID, false, null),
                 ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
         assertNumberOfActiveMethods(1);
         assertActiveKeys();
+    }
 
-        f = assertDeclareWarn1("private String f() {return null;}",
-                new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 7, 0, -1, -1, Diagnostic.Kind.WARNING),
-                ste(MAIN_SNIPPET, VALID, VALID, false, null),
-                ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertNumberOfActiveMethods(1);
-        assertActiveKeys();
-
-        f = assertDeclareWarn1("static String f() {return null;}",
+    public void methodsWarn() {
+        Snippet f = assertDeclareWarn1("static String f() {return null;}",
                 new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
-                ste(MAIN_SNIPPET, VALID, VALID, false, null),
-                ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+                added(VALID));
         assertNumberOfActiveMethods(1);
         assertActiveKeys();
 
--- a/langtools/test/jdk/jshell/ModifiersTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ModifiersTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -22,7 +22,7 @@
  */
 
 /*
- * @test
+ * @test 8167643 8129559
  * @summary Tests for modifiers
  * @build KullaTesting TestingInputStream ExpectedDiagnostic
  * @run testng ModifiersTest
@@ -31,6 +31,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import java.util.function.Consumer;
 import javax.tools.Diagnostic;
 
 import org.testng.annotations.DataProvider;
@@ -43,22 +44,55 @@
     public Object[][] getTestCases() {
         List<Object[]> testCases = new ArrayList<>();
         String[] ignoredModifiers = new String[] {
-            "public", "protected", "private", "static", "final"
+            "static", "final"
+        };
+        String[] silentlyIgnoredModifiers = new String[] {
+            "public", "protected", "private"
         };
+        String[] before = new String[] {
+            "strictfp", "abstract", "@X", "@X(value=9)"
+        };
+        String context = "@interface X { int value() default 0; }";
+        Consumer<String> eval = this::assertEval;
+        Consumer<String> evalWarn = s -> assertDeclareWarn1(s, "jdk.eval.warn.illegal.modifiers");
         for (String ignoredModifier : ignoredModifiers) {
             for (ClassType classType : ClassType.values()) {
-                testCases.add(new Object[] { ignoredModifier, classType });
+                testCases.add(new Object[] { ignoredModifier, classType, evalWarn, "", null });
+            }
+        }
+        for (String ignoredModifier : ignoredModifiers) {
+            for (String preface : before) {
+                testCases.add(new Object[] { ignoredModifier, ClassType.CLASS, evalWarn, preface, context});
+            }
+        }
+        for (String ignoredModifier : silentlyIgnoredModifiers) {
+            for (ClassType classType : ClassType.values()) {
+                testCases.add(new Object[] { ignoredModifier, classType, eval, "", null });
+            }
+        }
+        for (String ignoredModifier : silentlyIgnoredModifiers) {
+            for (String preface : before) {
+                testCases.add(new Object[] { ignoredModifier, ClassType.CLASS, eval, preface, context});
             }
         }
         return testCases.toArray(new Object[testCases.size()][]);
     }
 
     @Test(dataProvider = "ignoredModifiers")
-    public void ignoredModifiers(String modifier, ClassType classType) {
-        assertDeclareWarn1(
-                String.format("%s %s A {}", modifier, classType), "jdk.eval.warn.illegal.modifiers");
-        assertNumberOfActiveClasses(1);
-        assertClasses(clazz(classType, "A"));
+    public void ignoredModifiers(String modifier, ClassType classType,
+            Consumer<String> eval, String preface, String context) {
+        if (context != null) {
+            assertEval(context);
+        }
+        String decl = String.format("%s %s %s A {}", preface, modifier, classType);
+        eval.accept(decl);
+        if (context != null) {
+            assertNumberOfActiveClasses(2);
+            assertClasses(clazz(ClassType.ANNOTATION, "X"), clazz(classType, "A"));
+        } else {
+            assertNumberOfActiveClasses(1);
+            assertClasses(clazz(classType, "A"));
+        }
         assertActiveKeys();
     }
 
--- a/langtools/test/jdk/jshell/ToolBasicTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ToolBasicTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714
+ * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 8143955 8157953 8080347 8154714 8166649 8167643
  * @summary Tests for Basic tests for REPL tool
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -289,6 +289,21 @@
         );
     }
 
+    public void testModulePath() {
+        Compiler compiler = new Compiler();
+        Path modsDir = Paths.get("mods");
+        Path outDir = Paths.get("mods", "org.astro");
+        compiler.compile(outDir, "package org.astro; public class World { public static String name() { return \"world\"; } }");
+        compiler.compile(outDir, "module org.astro { exports org.astro; }");
+        Path modsPath = compiler.getPath(modsDir);
+        test(new String[] { "--module-path", modsPath.toString(), "--add-modules", "org.astro" },
+                (a) -> assertCommand(a, "import org.astro.World;", ""),
+                (a) -> evaluateExpression(a, "String",
+                        "String.format(\"Greetings %s!\", World.name());",
+                        "\"Greetings world!\"")
+        );
+    }
+
     public void testStartupFileOption() {
         try {
             Compiler compiler = new Compiler();
@@ -505,7 +520,7 @@
                     a -> assertCommand(a, "int a", ""),
                     a -> assertCommand(a, "void f() {}", ""),
                     a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("|  Error:")),
-                    a -> assertCommandCheckOutput(a, "public void f() {}", assertStartsWith("|  Warning:"))
+                    a -> assertCommandCheckOutput(a, "static void f() {}", assertStartsWith("|  Warning:"))
             );
         }
     }
--- a/langtools/test/jdk/jshell/ToolFormatTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ToolFormatTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840
+ * @bug 8148316 8148317 8151755 8152246 8153551 8154812 8157261 8163840 8166637 8161969
  * @summary Tests for output customization
  * @library /tools/lib
  * @modules jdk.compiler/com.sun.tools.javac.api
@@ -220,8 +220,8 @@
             test(
                     (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", ""),
                     (a) -> assertCommand(a, "String s = java.util.stream.IntStream.range(65, 74)"+
-                            ".mapToObj(i -> \"\"+(char)i).reduce((a,b) -> a + b + a).get()",
-                            "s ==> \"ABACABADABACABAEABACABADABACABAFABACABADABACABAEABACABADABACABAGABACABADABA ..."),
+                            ".mapToObj(i -> \"\"+(char)i).reduce((a,b) -> a + b + a).get() + \"XYZ\"",
+                            "s ==> \"ABACABADABACABAEABACABADABACABAFABACABADABACABAE ... BACABAEABACABADABACABAXYZ\""),
                     (a) -> assertCommandOutputStartsWith(a, "/set mode test -quiet", ""),
                     (a) -> assertCommandOutputStartsWith(a, "/set feedback test", ""),
                     (a) -> assertCommand(a, "/set format test display '{type}:{value}' primary", ""),
@@ -234,8 +234,9 @@
                             "/set truncation test 10 varvalue"),
                     (a) -> assertCommandOutputContains(a, "/set truncation test",
                             "/set truncation test 10 varvalue"),
-                    (a) -> assertCommand(a, "String r = s", "String:\"ABACABADABACABA ..."),
-                    (a) -> assertCommand(a, "r", "String:\"ABACA ..."),
+                    (a) -> assertCommand(a, "/var", "|    String s = \"ABACABADA"),
+                    (a) -> assertCommand(a, "String r = s", "String:\"ABACABAD ... BAXYZ\""),
+                    (a) -> assertCommand(a, "r", "String:\"ABACABADA"),
                     (a) -> assertCommand(a, "r=s", "String:\"AB")
             );
         } finally {
--- a/langtools/test/jdk/jshell/ToolRetainTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ToolRetainTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,13 +23,14 @@
 
 /*
  * @test
- * @bug 8157200 8163840
+ * @bug 8157200 8163840 8154513
  * @summary Tests of what information is retained across jshell tool runs
  * @modules jdk.jshell/jdk.internal.jshell.tool
  * @build ToolRetainTest ReplToolTesting
  * @run testng ToolRetainTest
  */
 
+import java.util.Locale;
 import org.testng.annotations.Test;
 
 @Test
@@ -62,14 +63,14 @@
                 (a) -> assertCommand(a, "/set mode -retain trm1", ""),
                 (a) -> assertCommand(a, "/exit", "")
         );
-        test(
+        test(Locale.ROOT, true, new String[0], "",
                 (a) -> assertCommand(a, "/set mode trm2 -quiet", ""),
                 (a) -> assertCommand(a, "/set format trm2 display '{name}={value}'", ""),
                 (a) -> assertCommand(a, "int x = 45", "x:45"),
                 (a) -> assertCommand(a, "/set mode -retain trm2", ""),
                 (a) -> assertCommand(a, "/exit", "")
         );
-        test(
+        test(Locale.ROOT, true, new String[0], "",
                 (a) -> assertCommandOutputContains(a, "/set mode trm1",
                         "/set format trm1 display \"{name}:{value}\""),
                 (a) -> assertCommand(a, "/set format trm2 display",
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128
+ * @bug 8153716 8143955 8151754 8150382 8153920 8156910 8131024 8160089 8153897 8167128 8154513
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -35,6 +35,7 @@
 import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Locale;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -465,14 +466,14 @@
     }
 
     public void testOptionQ() {
-        test(new String[]{"-q", "--no-startup"},
+        test(Locale.ROOT, false, new String[]{"-q", "--no-startup"}, "",
                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
                 (a) -> assertCommand(a, "int x = 5", "")
         );
     }
 
     public void testOptionS() {
-        test(new String[]{"-s", "--no-startup"},
+        test(Locale.ROOT, false, new String[]{"-s", "--no-startup"}, "",
                 (a) -> assertCommand(a, "1+1", "")
         );
     }
@@ -486,7 +487,7 @@
     }
 
     public void testOptionFeedback() {
-        test(new String[]{"--feedback", "concise", "--no-startup"},
+        test(Locale.ROOT, false, new String[]{"--feedback", "concise", "--no-startup"}, "",
                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
                 (a) -> assertCommand(a, "int x = 5", "")
         );
@@ -498,17 +499,17 @@
                             .filter(l -> !l.isEmpty())
                             .count(), "Expected no lines: " + s);
                 };
-        test(new String[]{"-nq"},
+        test(Locale.ROOT, false, new String[]{"-nq"}, "",
                 (a) -> assertCommandCheckOutput(a, "/list -all", confirmNoStartup),
                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
                 (a) -> assertCommand(a, "int x = 5", "")
         );
-        test(new String[]{"-qn"},
+        test(Locale.ROOT, false, new String[]{"-qn"}, "",
                 (a) -> assertCommandCheckOutput(a, "/list -all", confirmNoStartup),
                 (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
                 (a) -> assertCommand(a, "int x = 5", "")
         );
-        test(new String[]{"-ns"},
+        test(Locale.ROOT, false, new String[]{"-ns"}, "",
                 (a) -> assertCommandCheckOutput(a, "/list -all", confirmNoStartup),
                 (a) -> assertCommand(a, "1+1", "")
         );
--- a/langtools/test/jdk/jshell/UserJDIUserRemoteTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,286 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
- /*
- * @test
- * @bug 8160128 8159935
- * @summary Tests for Aux channel, custom remote agents, custom JDI implementations.
- * @build KullaTesting ExecutionControlTestBase
- * @run testng UserJDIUserRemoteTest
- */
-import java.io.ByteArrayOutputStream;
-import org.testng.annotations.Test;
-import org.testng.annotations.BeforeMethod;
-import jdk.jshell.Snippet;
-import static jdk.jshell.Snippet.Status.OVERWRITTEN;
-import static jdk.jshell.Snippet.Status.VALID;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.net.ServerSocket;
-import java.util.ArrayList;
-import java.util.List;
-import com.sun.jdi.VMDisconnectedException;
-import com.sun.jdi.VirtualMachine;
-import jdk.jshell.VarSnippet;
-import jdk.jshell.execution.DirectExecutionControl;
-import jdk.jshell.execution.JDIExecutionControl;
-import jdk.jshell.execution.JDIInitiator;
-import jdk.jshell.execution.Util;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.Socket;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.function.Consumer;
-import jdk.jshell.spi.ExecutionControl;
-import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
-import jdk.jshell.spi.ExecutionEnv;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
-import static jdk.jshell.execution.Util.remoteInputOutput;
-
-@Test
-public class UserJDIUserRemoteTest extends ExecutionControlTestBase {
-
-    ExecutionControl currentEC;
-    ByteArrayOutputStream auxStream;
-
-    @BeforeMethod
-    @Override
-    public void setUp() {
-        auxStream = new ByteArrayOutputStream();
-        setUp(builder -> builder.executionEngine(MyExecutionControl.create(this)));
-    }
-
-    public void testVarValue() {
-        VarSnippet dv = varKey(assertEval("double aDouble = 1.5;"));
-        String vd = getState().varValue(dv);
-        assertEquals(vd, "1.5");
-        assertEquals(auxStream.toString(), "aDouble");
-    }
-
-    public void testExtension() throws ExecutionControlException {
-        assertEval("42;");
-        Object res = currentEC.extensionCommand("FROG", "test");
-        assertEquals(res, "ribbit");
-    }
-
-    public void testRedefine() {
-        Snippet vx = varKey(assertEval("int x;"));
-        Snippet mu = methodKey(assertEval("int mu() { return x * 4; }"));
-        Snippet c = classKey(assertEval("class C { String v() { return \"#\" + mu(); } }"));
-        assertEval("C c0  = new C();");
-        assertEval("c0.v();", "\"#0\"");
-        assertEval("int x = 10;", "10",
-                ste(MAIN_SNIPPET, VALID, VALID, false, null),
-                ste(vx, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertEval("c0.v();", "\"#40\"");
-        assertEval("C c = new C();");
-        assertEval("c.v();", "\"#40\"");
-        assertEval("int mu() { return x * 3; }",
-                ste(MAIN_SNIPPET, VALID, VALID, false, null),
-                ste(mu, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertEval("c.v();", "\"#30\"");
-        assertEval("class C { String v() { return \"@\" + mu(); } }",
-                ste(MAIN_SNIPPET, VALID, VALID, false, null),
-                ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
-        assertEval("c0.v();", "\"@30\"");
-        assertEval("c = new C();");
-        assertEval("c.v();", "\"@30\"");
-        assertActiveKeys();
-    }
-}
-
-class MyExecutionControl extends JDIExecutionControl {
-
-    private static final String REMOTE_AGENT = MyRemoteExecutionControl.class.getName();
-
-    private VirtualMachine vm;
-    private Process process;
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI
-     * {@code LaunchingConnector}.
-     *
-     * @return the generator
-     */
-    public static ExecutionControl.Generator create(UserJDIUserRemoteTest test) {
-        return env -> make(env, test);
-    }
-
-    /**
-     * Creates an ExecutionControl instance based on a JDI
-     * {@code ListeningConnector} or {@code LaunchingConnector}.
-     *
-     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
-     * commands and results. This socket also transports the user
-     * input/output/error.
-     *
-     * @param env the context passed by
-         * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
-     * @return the channel
-     * @throws IOException if there are errors in set-up
-     */
-    static ExecutionControl make(ExecutionEnv env, UserJDIUserRemoteTest test) throws IOException {
-        try (final ServerSocket listener = new ServerSocket(0)) {
-            // timeout after 60 seconds
-            listener.setSoTimeout(60000);
-            int port = listener.getLocalPort();
-
-            // Set-up the JDI connection
-            List<String> opts = new ArrayList<>(env.extraRemoteVMOptions());
-            opts.add("-classpath");
-            opts.add(System.getProperty("java.class.path")
-                    + System.getProperty("path.separator")
-                    + System.getProperty("user.dir"));
-            JDIInitiator jdii = new JDIInitiator(port,
-                    opts, REMOTE_AGENT, true, null);
-            VirtualMachine vm = jdii.vm();
-            Process process = jdii.process();
-
-            List<Consumer<String>> deathListeners = new ArrayList<>();
-            deathListeners.add(s -> env.closeDown());
-            Util.detectJDIExitEvent(vm, s -> {
-                for (Consumer<String> h : deathListeners) {
-                    h.accept(s);
-                }
-            });
-
-            // Set-up the commands/reslts on the socket.  Piggy-back snippet
-            // output.
-            Socket socket = listener.accept();
-            // out before in -- match remote creation so we don't hang
-            OutputStream out = socket.getOutputStream();
-            Map<String, OutputStream> outputs = new HashMap<>();
-            outputs.put("out", env.userOut());
-            outputs.put("err", env.userErr());
-            outputs.put("aux", test.auxStream);
-            Map<String, InputStream> input = new HashMap<>();
-            input.put("in", env.userIn());
-            ExecutionControl myec = remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new MyExecutionControl(objOut, objIn, vm, process, deathListeners));
-            test.currentEC = myec;
-            return myec;
-        }
-    }
-
-    /**
-     * Create an instance.
-     *
-     * @param out the output for commands
-     * @param in the input for responses
-     */
-    private MyExecutionControl(ObjectOutput out, ObjectInput in,
-            VirtualMachine vm, Process process,
-            List<Consumer<String>> deathListeners) {
-        super(out, in);
-        this.vm = vm;
-        this.process = process;
-        deathListeners.add(s -> disposeVM());
-    }
-
-    @Override
-    public void close() {
-        super.close();
-        disposeVM();
-    }
-
-    private synchronized void disposeVM() {
-        try {
-            if (vm != null) {
-                vm.dispose(); // This could NPE, so it is caught below
-                vm = null;
-            }
-        } catch (VMDisconnectedException ex) {
-            // Ignore if already closed
-        } catch (Throwable e) {
-            fail("disposeVM threw: " + e);
-        } finally {
-            if (process != null) {
-                process.destroy();
-                process = null;
-            }
-        }
-    }
-
-    @Override
-    protected synchronized VirtualMachine vm() throws EngineTerminationException {
-        if (vm == null) {
-            throw new EngineTerminationException("VM closed");
-        } else {
-            return vm;
-        }
-    }
-
-}
-
-class MyRemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
-
-    static PrintStream auxPrint;
-
-    /**
-     * Launch the agent, connecting to the JShell-core over the socket specified
-     * in the command-line argument.
-     *
-     * @param args standard command-line arguments, expectation is the socket
-     * number is the only argument
-     * @throws Exception any unexpected exception
-     */
-    public static void main(String[] args) throws Exception {
-        try {
-            String loopBack = null;
-            Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
-            InputStream inStream = socket.getInputStream();
-            OutputStream outStream = socket.getOutputStream();
-            Map<String, Consumer<OutputStream>> outputs = new HashMap<>();
-            outputs.put("out", st -> System.setOut(new PrintStream(st, true)));
-            outputs.put("err", st -> System.setErr(new PrintStream(st, true)));
-            outputs.put("aux", st -> { auxPrint = new PrintStream(st, true); });
-            Map<String, Consumer<InputStream>> input = new HashMap<>();
-            input.put("in", st -> System.setIn(st));
-            forwardExecutionControlAndIO(new MyRemoteExecutionControl(), inStream, outStream, outputs, input);
-        } catch (Throwable ex) {
-            throw ex;
-        }
-    }
-
-    @Override
-    public String varValue(String className, String varName)
-            throws RunException, EngineTerminationException, InternalException {
-        auxPrint.print(varName);
-        return super.varValue(className, varName);
-    }
-
-    @Override
-    public Object extensionCommand(String className, Object arg)
-            throws RunException, EngineTerminationException, InternalException {
-        if (!arg.equals("test")) {
-            throw new InternalException("expected extensionCommand arg to be 'test' got: " + arg);
-        }
-        return "ribbit";
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/jshell/UserJdiUserRemoteTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8160128 8159935
+ * @summary Tests for Aux channel, custom remote agents, custom JDI implementations.
+ * @build KullaTesting ExecutionControlTestBase
+ * @run testng UserJdiUserRemoteTest
+ */
+import java.io.ByteArrayOutputStream;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import jdk.jshell.Snippet;
+import static jdk.jshell.Snippet.Status.OVERWRITTEN;
+import static jdk.jshell.Snippet.Status.VALID;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.List;
+import com.sun.jdi.VMDisconnectedException;
+import com.sun.jdi.VirtualMachine;
+import jdk.jshell.VarSnippet;
+import jdk.jshell.execution.DirectExecutionControl;
+import jdk.jshell.execution.JdiExecutionControl;
+import jdk.jshell.execution.JdiInitiator;
+import jdk.jshell.execution.Util;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.Socket;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import jdk.jshell.spi.ExecutionControl;
+import jdk.jshell.spi.ExecutionControl.ExecutionControlException;
+import jdk.jshell.spi.ExecutionEnv;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+import static jdk.jshell.execution.Util.forwardExecutionControlAndIO;
+import static jdk.jshell.execution.Util.remoteInputOutput;
+
+@Test
+public class UserJdiUserRemoteTest extends ExecutionControlTestBase {
+
+    ExecutionControl currentEC;
+    ByteArrayOutputStream auxStream;
+
+    @BeforeMethod
+    @Override
+    public void setUp() {
+        auxStream = new ByteArrayOutputStream();
+        setUp(builder -> builder.executionEngine(MyExecutionControl.create(this)));
+    }
+
+    public void testVarValue() {
+        VarSnippet dv = varKey(assertEval("double aDouble = 1.5;"));
+        String vd = getState().varValue(dv);
+        assertEquals(vd, "1.5");
+        assertEquals(auxStream.toString(), "aDouble");
+    }
+
+    public void testExtension() throws ExecutionControlException {
+        assertEval("42;");
+        Object res = currentEC.extensionCommand("FROG", "test");
+        assertEquals(res, "ribbit");
+    }
+
+    public void testRedefine() {
+        Snippet vx = varKey(assertEval("int x;"));
+        Snippet mu = methodKey(assertEval("int mu() { return x * 4; }"));
+        Snippet c = classKey(assertEval("class C { String v() { return \"#\" + mu(); } }"));
+        assertEval("C c0  = new C();");
+        assertEval("c0.v();", "\"#0\"");
+        assertEval("int x = 10;", "10",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(vx, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c0.v();", "\"#40\"");
+        assertEval("C c = new C();");
+        assertEval("c.v();", "\"#40\"");
+        assertEval("int mu() { return x * 3; }",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(mu, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c.v();", "\"#30\"");
+        assertEval("class C { String v() { return \"@\" + mu(); } }",
+                ste(MAIN_SNIPPET, VALID, VALID, false, null),
+                ste(c, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
+        assertEval("c0.v();", "\"@30\"");
+        assertEval("c = new C();");
+        assertEval("c.v();", "\"@30\"");
+        assertActiveKeys();
+    }
+}
+
+class MyExecutionControl extends JdiExecutionControl {
+
+    private static final String REMOTE_AGENT = MyRemoteExecutionControl.class.getName();
+
+    private VirtualMachine vm;
+    private Process process;
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code LaunchingConnector}.
+     *
+     * @return the generator
+     */
+    public static ExecutionControl.Generator create(UserJdiUserRemoteTest test) {
+        return env -> make(env, test);
+    }
+
+    /**
+     * Creates an ExecutionControl instance based on a JDI
+     * {@code ListeningConnector} or {@code LaunchingConnector}.
+     *
+     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
+     * commands and results. This socket also transports the user
+     * input/output/error.
+     *
+     * @param env the context passed by
+         * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+     * @return the channel
+     * @throws IOException if there are errors in set-up
+     */
+    static ExecutionControl make(ExecutionEnv env, UserJdiUserRemoteTest test) throws IOException {
+        try (final ServerSocket listener = new ServerSocket(0)) {
+            // timeout after 60 seconds
+            listener.setSoTimeout(60000);
+            int port = listener.getLocalPort();
+
+            // Set-up the JDI connection
+            List<String> opts = new ArrayList<>(env.extraRemoteVMOptions());
+            opts.add("-classpath");
+            opts.add(System.getProperty("java.class.path")
+                    + System.getProperty("path.separator")
+                    + System.getProperty("user.dir"));
+            JdiInitiator jdii = new JdiInitiator(port,
+                    opts, REMOTE_AGENT, true, null);
+            VirtualMachine vm = jdii.vm();
+            Process process = jdii.process();
+
+            List<Consumer<String>> deathListeners = new ArrayList<>();
+            deathListeners.add(s -> env.closeDown());
+            Util.detectJdiExitEvent(vm, s -> {
+                for (Consumer<String> h : deathListeners) {
+                    h.accept(s);
+                }
+            });
+
+            // Set-up the commands/reslts on the socket.  Piggy-back snippet
+            // output.
+            Socket socket = listener.accept();
+            // out before in -- match remote creation so we don't hang
+            OutputStream out = socket.getOutputStream();
+            Map<String, OutputStream> outputs = new HashMap<>();
+            outputs.put("out", env.userOut());
+            outputs.put("err", env.userErr());
+            outputs.put("aux", test.auxStream);
+            Map<String, InputStream> input = new HashMap<>();
+            input.put("in", env.userIn());
+            ExecutionControl myec = remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> new MyExecutionControl(objOut, objIn, vm, process, deathListeners));
+            test.currentEC = myec;
+            return myec;
+        }
+    }
+
+    /**
+     * Create an instance.
+     *
+     * @param out the output for commands
+     * @param in the input for responses
+     */
+    private MyExecutionControl(ObjectOutput out, ObjectInput in,
+            VirtualMachine vm, Process process,
+            List<Consumer<String>> deathListeners) {
+        super(out, in);
+        this.vm = vm;
+        this.process = process;
+        deathListeners.add(s -> disposeVM());
+    }
+
+    @Override
+    public void close() {
+        super.close();
+        disposeVM();
+    }
+
+    private synchronized void disposeVM() {
+        try {
+            if (vm != null) {
+                vm.dispose(); // This could NPE, so it is caught below
+                vm = null;
+            }
+        } catch (VMDisconnectedException ex) {
+            // Ignore if already closed
+        } catch (Throwable e) {
+            fail("disposeVM threw: " + e);
+        } finally {
+            if (process != null) {
+                process.destroy();
+                process = null;
+            }
+        }
+    }
+
+    @Override
+    protected synchronized VirtualMachine vm() throws EngineTerminationException {
+        if (vm == null) {
+            throw new EngineTerminationException("VM closed");
+        } else {
+            return vm;
+        }
+    }
+
+}
+
+class MyRemoteExecutionControl extends DirectExecutionControl implements ExecutionControl {
+
+    static PrintStream auxPrint;
+
+    /**
+     * Launch the agent, connecting to the JShell-core over the socket specified
+     * in the command-line argument.
+     *
+     * @param args standard command-line arguments, expectation is the socket
+     * number is the only argument
+     * @throws Exception any unexpected exception
+     */
+    public static void main(String[] args) throws Exception {
+        try {
+            String loopBack = null;
+            Socket socket = new Socket(loopBack, Integer.parseInt(args[0]));
+            InputStream inStream = socket.getInputStream();
+            OutputStream outStream = socket.getOutputStream();
+            Map<String, Consumer<OutputStream>> outputs = new HashMap<>();
+            outputs.put("out", st -> System.setOut(new PrintStream(st, true)));
+            outputs.put("err", st -> System.setErr(new PrintStream(st, true)));
+            outputs.put("aux", st -> { auxPrint = new PrintStream(st, true); });
+            Map<String, Consumer<InputStream>> input = new HashMap<>();
+            input.put("in", st -> System.setIn(st));
+            forwardExecutionControlAndIO(new MyRemoteExecutionControl(), inStream, outStream, outputs, input);
+        } catch (Throwable ex) {
+            throw ex;
+        }
+    }
+
+    @Override
+    public String varValue(String className, String varName)
+            throws RunException, EngineTerminationException, InternalException {
+        auxPrint.print(varName);
+        return super.varValue(className, varName);
+    }
+
+    @Override
+    public Object extensionCommand(String className, Object arg)
+            throws RunException, EngineTerminationException, InternalException {
+        if (!arg.equals("test")) {
+            throw new InternalException("expected extensionCommand arg to be 'test' got: " + arg);
+        }
+        return "ribbit";
+    }
+
+}
--- a/langtools/test/tools/doclint/moduleTests/bad/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/doclint/moduleTests/bad/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -6,7 +6,7 @@
  * @modules jdk.compiler/com.sun.tools.doclint
  * @build DocLintTester
  * @run main DocLintTester -ref module-info.out module-info.java
- * @compile/fail/ref=module-info.javac.out -XDrawDiagnostics -Werror -Xdoclint:all module-info.java
+ * @compile/fail/ref=module-info.javac.out -XDrawDiagnostics -Werror -Xlint:-options -Xdoclint:all module-info.java
  */
 
 // missing doc comment
--- a/langtools/test/tools/doclint/moduleTests/good/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/doclint/moduleTests/good/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,7 +29,7 @@
  * @modules jdk.compiler/com.sun.tools.doclint
  * @build DocLintTester
  * @run main DocLintTester module-info.java
- * @compile -Xdoclint:all -Werror module-info.java
+ * @compile -Xdoclint:all -Werror -Xlint:-options module-info.java
  */
 
 /** good module */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/AnonymousClass/AnonymousCtorExceptionTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8166367
+ * @summary Missing ExceptionTable attribute in anonymous class constructors
+ * @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.ToolBox toolbox.JavapTask
+ * @run compile -g AnonymousCtorExceptionTest.java
+ * @run main AnonymousCtorExceptionTest
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.JavapTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class AnonymousCtorExceptionTest {
+
+    AnonymousCtorExceptionTest() throws IOException {
+    }
+
+    public static void main(String args[]) throws Exception {
+
+        new AnonymousCtorExceptionTest() {
+        };
+
+        ToolBox tb = new ToolBox();
+        Path classPath = Paths.get(ToolBox.testClasses, "AnonymousCtorExceptionTest$1.class");
+        String javapOut = new JavapTask(tb)
+                .options("-v", "-p")
+                .classes(classPath.toString())
+                .run()
+                .getOutput(Task.OutputKind.DIRECT);
+        if (!javapOut.contains("AnonymousCtorExceptionTest$1() throws java.io.IOException;"))
+            throw new AssertionError("Unexpected output " + javapOut);
+        if (!javapOut.contains("Exceptions:"))
+            throw new AssertionError("Unexpected output " + javapOut);
+    }
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/T6403466.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/T6403466.java	Fri Nov 11 16:44:36 2016 +0100
@@ -58,9 +58,7 @@
                 fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java")));
 
             Iterable<String> options = Arrays.asList(
-                "--add-exports",
-                    "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED,"
-                    + "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED",
+                "--add-exports", "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED",
                 "--processor-path", testClassDir,
                 "-processor", self,
                 "-s", ".",
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/T8132562/ClassPathWithDoubleQuotesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8132562
+ * @summary javac fails with CLASSPATH with double-quotes as an environment variable
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @run main ClassPathWithDoubleQuotesTest
+*/
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import toolbox.TestRunner;
+import toolbox.JarTask;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class ClassPathWithDoubleQuotesTest extends TestRunner {
+
+    ToolBox tb;
+
+    private static final String ASrc = "public class A {}";
+    private static final String JarSrc = "public class J {}";
+    private static final String[] jarArgs = {"cf", "test/J.jar", "-C", "test", "J.java"};
+
+    public static void main(String... args) throws Exception {
+        new ClassPathWithDoubleQuotesTest().runTests();
+    }
+
+    ClassPathWithDoubleQuotesTest() {
+        super(System.err);
+        tb = new ToolBox();
+    }
+
+    public void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    @Test
+    public void test(Path base) throws Exception {
+        Path current = base.resolve(".");
+        tb.writeJavaFiles(current, ASrc, JarSrc);
+        new JarTask(tb).run(jarArgs).writeAll();
+
+        executeTask(new JavacTask(tb, Task.Mode.EXEC)
+                    .envVar("CLASSPATH", "\"test/J.jar" + File.pathSeparator + "test\"")
+                    .files("test/A.java"));
+
+        executeTask(new JavacTask(tb)
+                    .classpath("\"test/J.jar" + File.pathSeparator + "test\"")
+                    .files("test/A.java"));
+    }
+
+    void executeTask(JavacTask task) {
+        boolean isWindows = System.getProperty("os.name").startsWith("Windows");
+        Task.Expect whatToExpect = isWindows ? Task.Expect.FAIL : Task.Expect.SUCCESS;
+        try {
+            task.run(whatToExpect);
+            if (isWindows) {
+                throw new AssertionError("exception must be thrown");
+            }
+        } catch (IllegalArgumentException iae) {
+            if (!isWindows) {
+                throw new AssertionError("exception unexpectedly thrown");
+            }
+        } catch (Throwable t) {
+            throw new AssertionError("unexpected exception thrown");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/BadNameForOption.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+// key: compiler.warn.bad.name.for.option
+// options: --add-exports Bad!Name/p=java.base
+
+class BadNameForOption { }
+
--- a/langtools/test/tools/javac/diags/examples/CantFindModule/CantFindModule.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.cant.find.module
-// key: compiler.err.doesnt.exist
-
-// options: --add-exports undef/undef=ALL-UNNAMED
-
-import undef.Any;
-
-class Test {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/ModuleForOptionNotFound.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+// key: compiler.warn.module.for.option.not.found
+// key: compiler.err.doesnt.exist
+
+// options: --add-exports undefModule/undefPackage=ALL-UNNAMED
+
+import undefPackage.Any;
+
+class Test {}
+
--- a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/ServiceDefinitionInner.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.service.definition.is.inner
-// key: compiler.err.encl.class.required
--- a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/module-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-module m {
-    provides p1.C1.InnerDefinition with p2.C2;
-    exports p1;
-}
--- a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p1/C1.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package p1;
-
-public class C1 {
-    public class InnerDefinition {}
-}
--- a/langtools/test/tools/javac/diags/examples/ServiceDefinitionInner/modulesourcepath/m/p2/C2.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package p2;
-
-public class C2 extends p1.C1.InnerDefinition {}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/WrongNumberTypeArgsFragment.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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: compiler.err.cant.apply.symbol
+// key: compiler.misc.wrong.number.type.args
+
+import java.util.*;
+
+class WrongNumberTypeArgsFragment {
+    void test() {
+        Arrays.<String, Integer>asList("");
+    }
+}
--- a/langtools/test/tools/javac/diags/examples/XaddexportsMalformedEntry.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.xaddexports.malformed.entry
-// options: --add-exports jdk.compiler/com.sun.tools.javac.util
-
-public class XaddexportsMalformedEntry {
-}
--- a/langtools/test/tools/javac/diags/examples/XaddexportsTooMany.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.xaddexports.too.many
-// options: --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED  --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
-
-public class XaddexportsTooMany {
-}
--- a/langtools/test/tools/javac/diags/examples/XaddreadsMalformedEntry.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.xaddreads.malformed.entry
-// options: --add-reads jdk.compiler
-
-public class XaddreadsMalformedEntry {
-}
--- a/langtools/test/tools/javac/diags/examples/XaddreadsTooMany.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.err.xaddreads.too.many
-// options: --add-reads jdk.compiler=ALL-UNNAMED  --add-reads jdk.compiler=ALL-UNNAMED
-
-public class XaddreadsTooMany {
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/generics/inference/8168134/T8168134.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8168134
+ * @summary Inference: javac incorrectly propagating inner constraint with primitive target
+ * @compile T8168134.java
+ */
+
+abstract class T8168134 {
+    interface W<A> {}
+    abstract <B> B f(W<B> e);
+    abstract <C> C g(C b, long i);
+
+    void h(W<Long> i) {
+        g("", f(i));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/meth/BadPolySig.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,12 @@
+/*
+ * @test
+ * @bug 8168774
+ * @summary Polymorhic signature method check crashes javac
+ * @compile -Xmodule:java.base BadPolySig.java
+ */
+
+package java.lang.invoke;
+
+class MethodHandle {
+    native Object m();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/AddExportsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,346 @@
+/*
+ * 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 --add-exports option
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main AddExportsTest
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Set;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class AddExportsTest extends ModuleTestBase {
+
+    public static void main(String... args) throws Exception {
+        new AddExportsTest().runTests();
+    }
+
+    @Test
+    public void testEmpty(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+        testEmpty(src, classes, "--add-exports", "");
+        testEmpty(src, classes, "--add-exports=");
+    }
+
+    private void testEmpty(Path src, Path classes, String... options) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options(options)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: no value for --add-exports option");
+    }
+
+    @Test
+    public void testEmptyItem(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmptyItem(src, classes, "m1/p1=,m2,m3");
+        testEmptyItem(src, classes, "m1/p1=m2,,m3");
+        testEmptyItem(src, classes, "m1/p1=m2,m3,");
+    }
+
+    void testEmptyItem(Path src, Path classes, String option) throws Exception {
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testEmptyList(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmptyList(src, classes, "m1/p1=");
+        testEmptyList(src, classes, "m1/p1=,");
+    }
+
+    void testEmptyList(Path src, Path classes, String option) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: bad value for --add-exports option: '" + option + "'");
+    }
+
+    @Test
+    public void testMissingSourceParts(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testMissingSourcePart(src, classes, "=m2");
+        testMissingSourcePart(src, classes, "/=m2");
+        testMissingSourcePart(src, classes, "m1/=m2");
+        testMissingSourcePart(src, classes, "/p1=m2");
+        testMissingSourcePart(src, classes, "m1p1=m2");
+    }
+
+    private void testMissingSourcePart(Path src, Path classes, String option) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: bad value for --add-exports option: '" + option + "'");
+    }
+
+    @Test
+    public void testBadSourceParts(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testBadSourcePart(src, classes, "m!/p1=m2", "m!");
+        testBadSourcePart(src, classes, "m1/p!=m2", "p!");
+    }
+
+    private void testBadSourcePart(Path src, Path classes, String option, String badName)
+                throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString(),
+                         "--add-exports", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.bad.name.for.option: --add-exports, " + badName);
+    }
+
+    @Test
+    public void testBadTarget(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString(),
+                         "--add-exports", "m1/p1=m!")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.bad.name.for.option: --add-exports, m!");
+    }
+
+    @Test
+    public void testSourceNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString(),
+                         "--add-exports", "DoesNotExist/p=m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist");
+    }
+
+    @Test
+    public void testTargetNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                         "--module-source-path", src.toString(),
+                         "--add-exports", "m1/p1=DoesNotExist")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.module.for.option.not.found: --add-exports, DoesNotExist");
+    }
+
+    @Test
+    public void testDuplicate(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", "m1/p1=m2,m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testRepeated_SameTarget(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", "m1/p1=m2",
+                         "--add-exports", "m1/p1=m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testRepeated_DifferentTarget(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-exports", "m1/p1=m2",
+                         "--add-exports", "m1/p1=m3")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/AddModulesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,232 @@
+/*
+ * 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 --add-modules option
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main AddModulesTest
+ */
+
+
+import java.nio.file.Path;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class AddModulesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new AddModulesTest().runTests();
+    }
+
+    @Test
+    public void testEmpty(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmpty(src, classes, "--add-modules", "");
+        testEmpty(src, classes, "--add-modules=");
+    }
+
+    private void testEmpty(Path src, Path classes, String... options) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options(options)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: no value for --add-modules option");
+    }
+
+    @Test
+    public void testEmptyItem(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 m2 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmptyItem(src, classes, ",m1");
+        testEmptyItem(src, classes, "m1,,m2");
+        testEmptyItem(src, classes, "m1,");
+    }
+
+    private void testEmptyItem(Path src, Path classes, String option) throws Exception {
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-modules", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testEmptyList(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--add-modules", ",")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: bad value for --add-modules option");
+    }
+
+    @Test
+    public void testInvalidName(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-modules", "BadModule!")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.bad.name.for.option: --add-modules, BadModule!");
+    }
+
+    @Test
+    public void testUnknownName(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-modules", "DoesNotExist")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.err.module.not.found: DoesNotExist");
+    }
+
+    @Test
+    public void testDuplicate(Path base) throws Exception {
+        Path src = base.resolve("src");
+
+        // setup a utility module
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        // now test access to the module
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2,
+                          "class Dummy { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-path", modules.toString(),
+                         "--add-modules", "m1,m1")
+                .outdir(classes)
+                .files(findJavaFiles(src2))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testRepeatable(Path base) throws Exception {
+        Path src = base.resolve("src");
+
+        // setup some utility modules
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { exports p2; }",
+                          "package p2; public class C2 { }");
+        Path modules = base.resolve("modules");
+        tb.createDirectories(modules);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString())
+                .outdir(modules)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        // now test access to the modules
+        Path src2 = base.resolve("src2");
+        tb.writeJavaFiles(src2,
+                          "class Dummy { p1.C1 c1; p2.C2 c2; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-path", modules.toString(),
+                         "--add-modules", "m1",
+                         "--add-modules", "m2")
+                .outdir(classes)
+                .files(findJavaFiles(src2))
+                .run()
+                .writeAll();
+    }
+}
+
--- a/langtools/test/tools/javac/modules/AddReadsTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/AddReadsTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -28,6 +28,7 @@
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
  *          jdk.jdeps/com.sun.tools.javap
+ *          java.desktop
  * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask ModuleTestBase
  * @run main AddReadsTest
  */
@@ -49,7 +50,6 @@
 import toolbox.JavacTask;
 import toolbox.JavapTask;
 import toolbox.Task;
-import toolbox.ToolBox;
 
 public class AddReadsTest extends ModuleTestBase {
 
@@ -80,8 +80,8 @@
                 .writeAll()
                 .getOutput(Task.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");
+        checkOutputContains(log,
+            "Test.java:1:44: compiler.err.not.def.access.package.cant.access: api.Api, api");
 
         //test add dependencies:
         new JavacTask(tb)
@@ -104,7 +104,8 @@
 
         //cyclic dependencies OK when created through addReads:
         new JavacTask(tb)
-                .options("--add-reads", "m2=m1,m1=m2",
+                .options("--add-reads", "m2=m1",
+                         "--add-reads", "m1=m2",
                          "--module-source-path", src.toString())
                 .outdir(classes)
                 .files(findJavaFiles(src))
@@ -233,7 +234,8 @@
                           "package impl; public class Impl { javax.swing.JButton b; }");
 
         new JavacTask(tb)
-          .options("--add-reads", "java.base=java.desktop",
+          .options("--add-modules", "java.desktop",
+                   "--add-reads", "java.base=java.desktop",
                    "-Xmodule:java.base")
           .outdir(classes)
           .files(findJavaFiles(src))
@@ -308,4 +310,356 @@
           .run()
           .writeAll();
     }
+
+    @Test
+    public void testAddSelf(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m1=m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testEmpty(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmpty(src, classes, "--add-reads", "");
+        testEmpty(src, classes, "--add-reads=");
+    }
+
+    private void testEmpty(Path src, Path classes, String... options) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options(options)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: no value for --add-reads option");
+    }
+
+    @Test
+    public void testEmptyItem(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmptyItem(src, classes, "m3=,m1");
+        testEmptyItem(src, classes, "m3=m1,,m2");
+        testEmptyItem(src, classes, "m3=m1,");
+    }
+
+    private void testEmptyItem(Path src, Path classes, String option) throws Exception {
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testEmptyList(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        testEmptyList(src, classes, "m3=");
+        testEmptyList(src, classes, "m3=,");
+    }
+
+    private void testEmptyList(Path src, Path classes, String option) throws Exception {
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", option)
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: bad value for --add-reads option: '" + option + "'");
+    }
+
+    @Test
+    public void testMultipleAddReads_DifferentModules(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m2=m1",
+                         "--add-reads", "m3=m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testMultipleAddReads_SameModule(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { exports p2; }",
+                          "package p2; public class C2 { }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; p2.C2 c2; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m3=m1",
+                         "--add-reads", "m3=m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testDuplicateAddReads_SameOption(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { exports p2; }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m2=m1,m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testDuplicateAddReads_MultipleOptions(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { }",
+                          "package p2; class C2 { p1.C1 c1; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m2=m1",
+                         "--add-reads", "m2=m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testRepeatedAddReads(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { exports p2; }",
+                          "package p2; public class C2 { }");
+        Path src_m3 = src.resolve("m3");
+        tb.writeJavaFiles(src_m3,
+                          "module m3 { }",
+                          "package p3; class C3 { p1.C1 c1; p2.C2 c2; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--add-reads", "m3=m1",
+                         "--add-reads", "m3=m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testNoEquals(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "m1:m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "javac: bad value for --add-reads option: 'm1:m2'");
+    }
+
+    @Test
+    public void testBadSourceName(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "bad*Source=m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.bad.name.for.option: --add-reads, bad*Source");
+    }
+
+    @Test
+    public void testBadTargetName(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { }",
+                          "package p1; class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "m1=badTarget!")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.bad.name.for.option: --add-reads, badTarget!");
+    }
+
+    @Test
+    public void testSourceNameNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "missingSource=m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.module.for.option.not.found: --add-reads, missingSource");
+    }
+
+    @Test
+    public void testTargetNameNotFound(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports p1; }",
+                          "package p1; public class C1 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "m1=missingTarget")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        checkOutputContains(log,
+            "- compiler.warn.module.for.option.not.found: --add-reads, missingTarget");
+    }
 }
--- a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -230,8 +230,7 @@
                 .run(Task.Expect.FAIL)
                 .writeAll()
                 .getOutputLines(Task.OutputKind.DIRECT);
-        if (!log.equals(Arrays.asList("- compiler.err.processorpath.no.processormodulepath",
-                                      "1 error"))) {
+        if (!log.equals(Arrays.asList("- compiler.err.processorpath.no.processormodulepath"))) {
             throw new AssertionError("Unexpected output: " + log);
         }
     }
--- a/langtools/test/tools/javac/modules/EdgeCases.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/EdgeCases.java	Fri Nov 11 16:44:36 2016 +0100
@@ -71,21 +71,22 @@
     @Test
     public void testAddExportUndefinedModule(Path base) throws Exception {
         Path src = base.resolve("src");
-        tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}");
+        tb.writeJavaFiles(src, "package test; import undefPackage.Any; public class Test {}");
         Path classes = base.resolve("classes");
         tb.createDirectories(classes);
 
         List<String> log = new JavacTask(tb)
-                .options("--add-exports", "undef/undef=ALL-UNNAMED", "-XDrawDiagnostics")
+                .options("--add-exports", "undefModule/undefPackage=ALL-UNNAMED",
+                         "-XDrawDiagnostics")
                 .outdir(classes)
                 .files(findJavaFiles(src))
                 .run(Task.Expect.FAIL)
                 .writeAll()
                 .getOutputLines(Task.OutputKind.DIRECT);
 
-        List<String> expected = Arrays.asList("- compiler.err.cant.find.module: undef",
-                                              "Test.java:1:27: compiler.err.doesnt.exist: undef",
-                                              "2 errors");
+        List<String> expected = Arrays.asList("- compiler.warn.module.for.option.not.found: --add-exports, undefModule",
+                                              "Test.java:1:34: compiler.err.doesnt.exist: undefPackage",
+                                              "1 error", "1 warning");
 
         if (!expected.equals(log))
             throw new Exception("expected output not found: " + log);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/LimitModulesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,188 @@
+/*
+ * 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 --limit-modules option
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @run main LimitModulesTest
+ */
+
+
+import java.nio.file.Path;
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.ToolBox;
+
+public class LimitModulesTest extends ModuleTestBase {
+    public static void main(String... args) throws Exception {
+        new LimitModulesTest().runTests();
+    }
+
+    @Test
+    public void testEmpty(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules", "")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("javac: no value for --limit-modules option"))
+            throw new Exception("expected output not found");
+
+        log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules=")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("javac: no value for --limit-modules option"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    public void testEmptyItem(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 m2 { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules", ",m1")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules", "m1,,m2")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        new JavacTask(tb)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules", "m1,")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+    }
+
+    @Test
+    public void testEmptyList(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb, Task.Mode.CMDLINE)
+                .options("--module-source-path", src.toString(),
+                         "--limit-modules", ",")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("javac: bad value for --limit-modules option"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    public void testInvalidName(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src, "class Dummy { }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--limit-modules", "BadModule!")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("- compiler.warn.bad.name.for.option: --limit-modules, BadModule!"))
+            throw new Exception("expected output not found");
+    }
+
+    @Test
+    public void testLastOneWins(Path base) throws Exception {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "package p; class C { com.sun.tools.javac.Main main; }");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        System.err.println("case 1:");
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--limit-modules", "java.base",
+                         "--limit-modules", "jdk.compiler")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run()
+                .writeAll();
+
+        System.err.println("case 2:");
+        String log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--limit-modules", "jdk.compiler",
+                         "--limit-modules", "java.base")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutput(Task.OutputKind.DIRECT);
+
+        if (!log.contains("C.java:1:41: compiler.err.doesnt.exist: com.sun.tools.javac"))
+            throw new Exception("expected output not found");
+    }
+}
+
--- a/langtools/test/tools/javac/modules/ModuleTestBase.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/ModuleTestBase.java	Fri Nov 11 16:44:36 2016 +0100
@@ -53,4 +53,12 @@
     Path[] findJavaFiles(Path... paths) throws IOException {
         return tb.findJavaFiles(paths);
     }
+
+    void checkOutputContains(String log, String... expect) throws Exception {
+        for (String e : expect) {
+            if (!log.contains(e)) {
+                throw new Exception("expected output not found: " + e);
+            }
+        }
+    }
 }
--- a/langtools/test/tools/javac/modules/ProvidesTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,6 +24,7 @@
 /**
  * @test
  * @summary simple tests of module provides
+ * @bug 8168854
  * @library /tools/lib
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
@@ -39,6 +40,7 @@
 
 import toolbox.JavacTask;
 import toolbox.Task;
+import toolbox.Task.Expect;
 import toolbox.ToolBox;
 
 public class ProvidesTest extends ModuleTestBase {
@@ -415,24 +417,13 @@
         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 { }");
+                "package p2; public class C2 extends p1.C1.InnerDefinition { public C2() { new p1.C1().super(); } }");
 
-        List<String> output = new JavacTask(tb)
+        new JavacTask(tb)
                 .options("-XDrawDiagnostics")
                 .outdir(Files.createDirectories(base.resolve("classes")))
                 .files(findJavaFiles(src))
-                .run(Task.Expect.FAIL)
-                .writeAll()
-                .getOutputLines(Task.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");
-        }
+                .run(Expect.SUCCESS)
+                .writeAll();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/T8168854/module-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,10 @@
+/*
+ * @test
+ * @bug 8168854
+ * @summary javac erroneously reject a a service interface inner class in a provides clause
+ * @compile module-info.java
+ */
+module mod {
+    exports pack1;
+    provides pack1.Outer.Inter with pack1.Outer1.Implem;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/T8168854/pack1/Outer.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+package pack1;
+
+public class Outer {
+    public class Inter {
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/modules/T8168854/pack1/Outer1.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package pack1;
+
+public class Outer1 {
+    public static class Implem extends Outer.Inter {
+        public Implem () {
+            new Outer().super();
+        }
+    }
+}
\ No newline at end of file
--- a/langtools/test/tools/javac/modules/XModuleTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/javac/modules/XModuleTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -223,8 +223,7 @@
                 .writeAll()
                 .getOutputLines(Task.OutputKind.DIRECT);
 
-        List<String> expected = Arrays.asList("- compiler.err.xmodule.no.module.sourcepath",
-                                              "1 error");
+        List<String> expected = Arrays.asList("- compiler.err.xmodule.no.module.sourcepath");
 
         if (!expected.equals(log))
             throw new Exception("expected output not found: " + log);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/nestedTypeVars/NestedTypeVars.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 jdk.compiler
+ * @build NestedTypeVars
+ * @compile/process/ref=NestedTypeVars.out -processor NestedTypeVars Test$1L1$L2$1L3$L4$L5 Test$1L1$CCheck Test$1L1 Test$1CCheck Test$CCheck Test
+ */
+
+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.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVariable;
+import javax.lang.model.util.ElementFilter;
+
+@SupportedAnnotationTypes("*")
+public class NestedTypeVars extends AbstractProcessor{
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        for (TypeElement te : ElementFilter.typesIn(roundEnv.getRootElements())) {
+            System.out.print(processingEnv.getElementUtils().getBinaryName(te));
+            System.out.print("<");
+            String separator = "";
+            for (TypeParameterElement tp : te.getTypeParameters()) {
+                System.out.print(separator);
+                separator = ", ";
+                System.out.print(tp.getSimpleName());
+                System.out.print(" extends ");
+                System.out.print(tp.getBounds().stream().map(b -> toString(b)).collect(Collectors.joining("&")));
+            }
+            System.out.println(">");
+            for (ExecutableElement m : ElementFilter.methodsIn(te.getEnclosedElements())) {
+                System.out.print("  <");
+                separator = "";
+                for (TypeParameterElement tp : m.getTypeParameters()) {
+                    System.out.print(separator);
+                    separator = ", ";
+                    System.out.print(tp.getSimpleName());
+                    System.out.print(" extends ");
+                    System.out.print(tp.getBounds().
+                            stream().
+                            map(b -> toString(b)).
+                            collect(Collectors.joining("&")));
+                }
+                System.out.print(">");
+                System.out.println(m.getSimpleName());
+            }
+        }
+
+        return false;
+    }
+
+    String toString(TypeMirror bound) {
+        if (bound.getKind() == TypeKind.TYPEVAR) {
+            TypeVariable var = (TypeVariable) bound;
+            return toString(var.asElement());
+        }
+        return bound.toString();
+    }
+
+    String toString(Element el) {
+        switch (el.getKind()) {
+            case METHOD:
+                return toString(el.getEnclosingElement()) + "." + el.getSimpleName();
+            case CLASS:
+                return processingEnv.getElementUtils().getBinaryName((TypeElement) el).toString();
+            case TYPE_PARAMETER:
+                return toString(((TypeParameterElement) el).getGenericElement()) + "." + el.getSimpleName();
+            default:
+                throw new IllegalStateException("Unexpected element: " + el + "(" + el.getKind() + ")");
+        }
+    }
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latestSupported();
+    }
+
+
+}
+
+class Test<T1, C> {
+    <T2, C> void m() {
+        class L1<T3, C> {
+            class L2<T4, C> {
+                <T5, C> void m() {
+                    class L3<T6, C> {
+                        class L4<T7, C> {
+                            class L5<T1a extends T1,
+                                     T2a extends T2,
+                                     T3a extends T3,
+                                     T4a extends T4,
+                                     T5a extends T5,
+                                     T6a extends T6,
+                                     T7a extends T7> {}
+                        }
+                    }
+                }
+            }
+            class CCheck<T extends C> {}
+            <T extends C> void test() {}
+        }
+        class CCheck<T extends C> {}
+    }
+    class CCheck<T extends C> {}
+    <T extends C> void test() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/processing/model/nestedTypeVars/NestedTypeVars.out	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,9 @@
+Test$1L1$L2$1L3$L4$L5<T1a extends Test.T1, T2a extends Test.m.T2, T3a extends Test$1L1.T3, T4a extends Test$1L1$L2.T4, T5a extends Test$1L1$L2.m.T5, T6a extends Test$1L1$L2$1L3.T6, T7a extends Test$1L1$L2$1L3$L4.T7>
+Test$1L1$CCheck<T extends Test$1L1.C>
+Test$1L1<T3 extends java.lang.Object, C extends java.lang.Object>
+  <T extends Test$1L1.C>test
+Test$1CCheck<T extends Test.m.C>
+Test$CCheck<T extends Test.C>
+Test<T1 extends java.lang.Object, C extends java.lang.Object>
+  <T2 extends java.lang.Object, C extends java.lang.Object>m
+  <T extends Test.C>test
--- a/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestLoad.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestLoad.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8145464 8164837
  * @summary Test of jdeprscan tool loading and printing to aCSV file.
  * @modules jdk.jdeps/com.sun.tools.jdeprscan
  * @library ../../../cases
--- a/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestScan.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/jdeprscan/tests/jdk/jdeprscan/TestScan.java	Fri Nov 11 16:44:36 2016 +0100
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8145464 8164837 8165646
  * @summary Basic test of jdeprscan's scanning phase.
  * @modules jdk.jdeps/com.sun.tools.jdeprscan
  * @library ../../../cases
@@ -89,6 +90,7 @@
                 new InputStreamReader(
                     new ByteArrayInputStream(bytes), StandardCharsets.UTF_8))
                         .lines()
+                        .filter(line -> !line.endsWith(":"))
                         .map(line -> line.split(" +"))
                         .map(array -> array[1])
                         .collect(Collectors.toSet());
--- a/langtools/test/tools/jdeps/lib/JdepsRunner.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/langtools/test/tools/jdeps/lib/JdepsRunner.java	Fri Nov 11 16:44:36 2016 +0100
@@ -27,16 +27,19 @@
 import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.List;
+import java.util.spi.ToolProvider;
 import java.util.stream.Collectors;
 
 /**
  * JdepsRunner class to invoke jdeps with the given command line argument
  */
 public class JdepsRunner {
+    private static final ToolProvider JDEPS_TOOL = ToolProvider.findFirst("jdeps")
+        .orElseThrow(() -> new RuntimeException("jdeps tool not found"));
+
     public static JdepsRunner run(String... args) {
         JdepsRunner jdeps = new JdepsRunner(args);
-        int rc = jdeps.run();
-        jdeps.printStdout(System.err);
+        int rc = jdeps.run(true);
         if (rc != 0)
            throw new Error("jdeps failed: rc=" + rc);
         return jdeps;
@@ -46,7 +49,7 @@
     final StringWriter stderr = new StringWriter();
     final String[] args;
     public JdepsRunner(String... args) {
-        System.err.println("jdeps " + Arrays.stream(args)
+        System.out.println("jdeps " + Arrays.stream(args)
                                             .collect(Collectors.joining(" ")));
         this.args = args;
     }
@@ -60,10 +63,12 @@
     }
 
     public int run(boolean showOutput) {
-        try (PrintWriter pw = new PrintWriter(stdout)) {
-            int rc = com.sun.tools.jdeps.Main.run(args, pw);
+        try (PrintWriter pwout = new PrintWriter(stdout);
+             PrintWriter pwerr = new PrintWriter(stderr)) {
+            int rc = JDEPS_TOOL.run(pwout, pwerr, args);
             if (showOutput) {
-                System.err.println(stdout.toString());
+                printStdout(System.out);
+                printStderr(System.out);
             }
             return rc;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/listdeps/ListModuleDeps.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8167057
+ * @summary Tests split packages
+ * @modules java.logging
+ *          java.xml
+ *          jdk.compiler
+ *          jdk.jdeps
+ *          jdk.unsupported
+ * @library ../lib
+ * @build CompilerUtils JdepsRunner
+ * @run testng ListModuleDeps
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class ListModuleDeps {
+    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 LIB_DIR = Paths.get("lib");
+
+    private static final Path FOO_CLASS =
+        CLASSES_DIR.resolve("z").resolve("Foo.class");
+    private static final Path BAR_CLASS =
+        CLASSES_DIR.resolve("z").resolve("Bar.class");
+    private static final Path UNSAFE_CLASS =
+        CLASSES_DIR.resolve("z").resolve("UseUnsafe.class");
+
+    /**
+     * Compiles classes used by the test
+     */
+    @BeforeTest
+    public void compileAll() throws Exception {
+        // compile library
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "lib"), LIB_DIR));
+
+        // compile classes in unnamed module
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "z"),
+            CLASSES_DIR,
+            "-cp", LIB_DIR.toString(),
+            "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
+            "--add-exports=java.base/sun.security.util=ALL-UNNAMED",
+            "--add-exports=java.xml/jdk.xml.internal=ALL-UNNAMED"
+        ));
+    }
+
+    @Test(dataProvider = "listdeps")
+    public void testListDeps(Path classes, String[] expected) {
+        JdepsRunner jdeps = JdepsRunner.run(
+            "--class-path", LIB_DIR.toString(),
+            "--list-deps", classes.toString()
+        );
+        String[] output = Arrays.stream(jdeps.output())
+                                .map(s -> s.trim())
+                                .toArray(String[]::new);
+        assertEquals(output, expected);
+    }
+
+    @Test(dataProvider = "reduceddeps")
+    public void testListReducedDeps(Path classes, String[]  expected) {
+        JdepsRunner jdeps = JdepsRunner.run(
+            "--class-path", LIB_DIR.toString(),
+            "--list-reduced-deps", classes.toString()
+        );
+        String[] output = Arrays.stream(jdeps.output())
+                                .map(s -> s.trim())
+                                .toArray(String[]::new);
+        assertEquals(output, expected);
+    }
+
+
+    @DataProvider(name = "listdeps")
+    public Object[][] listdeps() {
+        return new Object[][] {
+            { CLASSES_DIR,  new String[] {
+                                "java.base/jdk.internal.misc",
+                                "java.base/sun.security.util",
+                                "java.logging",
+                                "java.sql",
+                                "java.xml/jdk.xml.internal",
+                                "jdk.unsupported",
+                                "unnamed module: lib"
+                            }
+            },
+
+            { FOO_CLASS,    new String[] {
+                                "java.base",
+                                "java.logging",
+                                "java.sql",
+                                "java.xml",
+                                "unnamed module: lib"
+                            }
+            },
+
+            { BAR_CLASS,    new String[] {
+                                "java.base/sun.security.util",
+                                "java.xml/jdk.xml.internal",
+                            }
+            },
+
+            { UNSAFE_CLASS, new String[] {
+                                "java.base/jdk.internal.misc",
+                                "jdk.unsupported",
+                            }
+            },
+        };
+    }
+
+    @DataProvider(name = "reduceddeps")
+    public Object[][] reduceddeps() {
+        Path barClass = CLASSES_DIR.resolve("z").resolve("Bar.class");
+
+        return new Object[][] {
+            { CLASSES_DIR,  new String[] {
+                                "java.base/jdk.internal.misc",
+                                "java.base/sun.security.util",
+                                "java.sql",
+                                "java.xml/jdk.xml.internal",
+                                "jdk.unsupported",
+                                "unnamed module: lib"
+                            }
+            },
+
+
+            { FOO_CLASS,    new String[] {
+                                "java.base",
+                                "java.sql",
+                                "unnamed module: lib"
+                            }
+            },
+
+            { BAR_CLASS,    new String[] {
+                                "java.base/sun.security.util",
+                                "java.xml/jdk.xml.internal",
+                            }
+            },
+
+            { UNSAFE_CLASS, new String[] {
+                                "java.base/jdk.internal.misc",
+                                "jdk.unsupported",
+                            }
+            },
+        };
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/listdeps/src/lib/Lib.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 lib;
+
+import javax.xml.stream.XMLInputFactory;
+
+public class Lib {
+    public static final String isCoalescing = XMLInputFactory.IS_COALESCING;
+    public static boolean check() { return true; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/listdeps/src/z/Bar.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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 z;
+
+import sun.security.util.HostnameChecker;
+import jdk.xml.internal.JdkXmlUtils;
+
+public class Bar {
+    // internal API from java.xml
+    private static final String name = JdkXmlUtils.USE_CATALOG;
+
+    public static void main(String[] argv) throws Exception {
+        HostnameChecker hc = HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/listdeps/src/z/Foo.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package z;
+
+import java.sql.Driver;
+import java.util.logging.Logger;
+import javax.xml.stream.XMLInputFactory;
+/*
+ * Dependences on java.sql and java.logging which can be reduced.
+ */
+public class Foo {
+    // dependence to java.logging
+    static Logger log = Logger.getLogger("foo");
+    static final String isCoalescing = XMLInputFactory.IS_COALESCING;
+
+    // dependence to java.sql
+    public Driver getDriver() { return null; }
+
+    // dependence to same package
+    public Bar getBar() { return new Bar(); }
+
+    // dependence to module m
+    public String isCoalescing() { return lib.Lib.isCoalescing; }
+
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/listdeps/src/z/UseUnsafe.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package z;
+
+import sun.misc.Unsafe;
+import jdk.internal.misc.VM;
+
+public class UseUnsafe {
+    private static Unsafe unsafe = Unsafe.getUnsafe();
+
+    private static boolean booted = VM.isBooted();
+}
--- a/make/Bundles.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/Bundles.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -256,7 +256,7 @@
 
   $(eval $(call SetupBundleFile, BUILD_DEMOS_BUNDLE, \
       BUNDLE_NAME := $(DEMOS_BUNDLE_NAME), \
-      FILES := $(call DoubleDollar, $(DEMOS_BUNDLE_FILES)), \
+      FILES := $(DEMOS_BUNDLE_FILES), \
       BASE_DIR := $(JDK_IMAGE_DIR), \
       SUBDIR := $(JDK_BUNDLE_SUBDIR), \
   ))
@@ -271,7 +271,7 @@
 
   $(eval $(call SetupBundleFile, BUILD_TEST_BUNDLE, \
       BUNDLE_NAME := $(TEST_BUNDLE_NAME), \
-      FILES := $(call DoubleDollar, $(TEST_BUNDLE_FILES)), \
+      FILES := $(TEST_BUNDLE_FILES), \
       BASE_DIR := $(TEST_IMAGE_DIR), \
   ))
 
--- a/make/CompileJavaModules.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/CompileJavaModules.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -95,7 +95,7 @@
 ################################################################################
 
 java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \
-    '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation,-exports
+    '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation,exports
 java.desktop_COPY := .gif .png .wav .txt .xml .css .pf
 java.desktop_CLEAN := iio-plugin.properties cursors.properties
 
@@ -348,7 +348,7 @@
 
 ################################################################################
 
-jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*' \
+jdk.compiler_ADD_JAVAC_FLAGS := -Xdoclint:all/protected '-Xdoclint/package:-com.sun.tools.*,-jdk.internal.*' \
     -XDstringConcat=inline
 jdk.compiler_CLEAN_FILES := $(wildcard \
     $(patsubst %, $(JDK_TOPDIR)/src/jdk.compiler/share/classes/%/*.properties, \
@@ -365,6 +365,10 @@
 
 ################################################################################
 
+jdk.editpad_COPY := .properties
+
+################################################################################
+
 jdk.internal.le_COPY := .properties
 
 ################################################################################
@@ -436,10 +440,6 @@
 
 ################################################################################
 
-jdk.jsobject_ADD_JAVAC_FLAGS := -Xlint:-exports
-
-################################################################################
-
 jdk.dev_CLEAN_FILES := $(wildcard \
     $(patsubst %, $(JDK_TOPDIR)/src/jdk.dev/share/classes/%/*.properties, \
         com/sun/tools/script/shell))
@@ -477,6 +477,13 @@
 jdk.localedata_EXCLUDE_FILES += sun/text/resources/ext/BreakIteratorRules_th.java
 
 ################################################################################
+# If this is an imported module that has prebuilt classes, only compile
+# module-info.java.
+ifneq ($(wildcard $(IMPORT_MODULES_CLASSES)/$(MODULE)), )
+  $(MODULE)_INCLUDE_FILES := module-info.java
+endif
+
+################################################################################
 # Setup the compilation for the module
 #
 MODULE_SRC_DIRS := $(call FindModuleSrcDirs, $(MODULE))
--- a/make/CreateJmods.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/CreateJmods.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -36,6 +36,7 @@
 ################################################################################
 
 JMODS_DIR := $(IMAGES_OUTPUTDIR)/jmods
+JMODS_TEMPDIR := $(SUPPORT_OUTPUTDIR)/jmods
 
 LIBS_DIR := $(firstword $(wildcard $(addsuffix /$(MODULE), \
     $(SUPPORT_OUTPUTDIR)/modules_libs $(IMPORT_MODULES_LIBS))))
@@ -81,16 +82,19 @@
 # Add dependencies on other jmod files. Only java.base needs access to other
 # jmods.
 ifeq ($(MODULE), java.base)
-  ALL_UPGRADEABLE_MODULES = $(call FindAllUpgradeableModules)
   # When creating a BUILDJDK, we don't need to add hashes to java.base
   ifneq ($(CREATING_BUILDJDK), true)
-    DEPS += $(patsubst %, $(JMODS_DIR)/%.jmod, \
-        $(filter-out java.base $(ALL_UPGRADEABLE_MODULES), $(call FindAllModules)))
+    # When creating interim versions of jmods, skip hashes
+    ifneq ($(INTERIM_JMOD), true)
+      ALL_UPGRADEABLE_MODULES := $(call FindAllUpgradeableModules)
+      DEPS += $(patsubst %, $(JMODS_DIR)/%.jmod, \
+          $(filter-out java.base $(ALL_UPGRADEABLE_MODULES), $(call FindAllModules)))
 
-    EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(ALL_UPGRADEABLE_MODULES))))
+      EXCLUDE_PATTERN := $(strip $(subst $(SPACE),|,$(strip $(ALL_UPGRADEABLE_MODULES))))
 
-    JMOD_FLAGS += --module-path $(JMODS_DIR) \
-        --hash-modules '^(?!$(EXCLUDE_PATTERN))'
+      JMOD_FLAGS += --module-path $(JMODS_DIR) \
+          --hash-modules '^(?!$(EXCLUDE_PATTERN))'
+    endif
   endif
 endif
 
@@ -102,13 +106,19 @@
   DEPS += $(call CacheFind, $(JDK_OUTPUTDIR)/modules/jdk.jlink/jdk/tools/jmod)
 endif
 
+# If creating interim versions of jmods, certain files need to be filtered out
+# to avoid false incremental rebuilds.
+ifeq ($(INTERIM_JMOD), true)
+  DEPS := $(filter-out $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist, $(DEPS))
+endif
+
 # 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.
 $(JMODS_DIR)/$(MODULE).jmod: $(DEPS)
 	$(call LogWarn, Creating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
-	$(call MakeDir, $(@D) $(SUPPORT_OUTPUTDIR)/jmods)
-	$(RM) $@ $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
+	$(call MakeDir, $(JMODS_DIR) $(JMODS_TEMPDIR))
+	$(RM) $@ $(JMODS_TEMPDIR)/$(notdir $@)
 	$(JMOD) create \
             --module-version $(VERSION_SHORT) \
             --os-name $(REQUIRED_OS_NAME) \
@@ -116,10 +126,10 @@
             --os-version $(REQUIRED_OS_VERSION) \
             --module-path $(JMODS_DIR) \
 	    --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.dSYM,*.pdb,*.map}' \
-	    $(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
-	$(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@
+	    $(JMOD_FLAGS) $(JMODS_TEMPDIR)/$(notdir $@)
+	$(MV) $(JMODS_TEMPDIR)/$(notdir $@) $@
 
-TARGETS += $(IMAGES_OUTPUTDIR)/jmods/$(MODULE).jmod
+TARGETS += $(JMODS_DIR)/$(MODULE).jmod
 
 ################################################################################
 
--- a/make/ExplodedImageOptimize.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/ExplodedImageOptimize.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -39,6 +39,7 @@
 $(PACKAGES_ATTRIBUTE_TARGET): $(ALL_MODULEINFO_CLASSES) $(BUILD_JIGSAW_CLASSES)
 	$(call LogInfo, Optimizing the exploded image)
 	$(TOOL_ADD_PACKAGES_ATTRIBUTE) $(JDK_OUTPUTDIR)
+	$(TOUCH) $@
 
 TARGETS := $(PACKAGES_ATTRIBUTE_TARGET)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/GenerateLinkOptData.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,88 @@
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+################################################################################
+# Generate classlist
+################################################################################
+
+default: all
+
+include $(SPEC)
+include MakeBase.gmk
+include JarArchive.gmk
+
+################################################################################
+# Create a jar with our generator class. Using a jar is intentional since it
+# will load more classes
+
+$(eval $(call SetupJarArchive, CLASSLIST_JAR, \
+    SRCS := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
+    INCLUDES := build/tools/classlist, \
+    JAR := $(SUPPORT_OUTPUTDIR)/classlist.jar, \
+))
+
+TARGETS += $(CLASSLIST_JAR)
+
+################################################################################
+
+LINK_OPT_DIR := $(SUPPORT_OUTPUTDIR)/link_opt
+CLASSLIST_FILE := $(LINK_OPT_DIR)/classlist
+JLI_TRACE_FILE := $(LINK_OPT_DIR)/jli_trace.out
+
+# If an external buildjdk has been supplied, we don't build a separate interim
+# image, so just use the external build jdk instead.
+ifeq ($(EXTERNAL_BUILDJDK), true)
+  INTERIM_IMAGE_DIR := $(BUILD_JDK)
+endif
+
+$(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
+	$(call MakeDir, $(LINK_OPT_DIR))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $(JLI_TRACE_FILE)))
+	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
+	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
+	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
+	    build.tools.classlist.HelloClasslist \
+	    $(LOG_DEBUG) 2>&1 > $(JLI_TRACE_FILE)
+
+# The jli trace is created by the same recipe as classlist. By declaring these
+# dependencies, make will correctly rebuild both jli trace and classlist
+# incrementally using the single recpie above.
+$(CLASSLIST_FILE): $(JLI_TRACE_FILE)
+$(JLI_TRACE_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
+
+TARGETS += $(CLASSLIST_FILE) $(JLI_TRACE_FILE)
+
+# Copy the classlist file into java.base libs
+$(eval $(call SetupCopyFiles, COPY_CLASSLIST, \
+    FILES := $(CLASSLIST_FILE), \
+    DEST := $(SUPPORT_OUTPUTDIR)/modules_libs/java.base, \
+))
+
+TARGETS += $(COPY_CLASSLIST)
+
+################################################################################
+
+all: $(TARGETS)
--- a/make/Images.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/Images.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -113,8 +113,8 @@
 JLINK_ORDER_RESOURCES := **module-info.class
 JLINK_JLI_CLASSES :=
 ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
-  JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/classlist/classlist
-  JLINK_JLI_CLASSES := --generate-jli-classes=@$(SUPPORT_OUTPUTDIR)/classlist/jli_trace.out
+  JLINK_ORDER_RESOURCES += @$(SUPPORT_OUTPUTDIR)/link_opt/classlist
+  JLINK_JLI_CLASSES := --generate-jli-classes=@$(SUPPORT_OUTPUTDIR)/link_opt/jli_trace.out
 endif
 JLINK_ORDER_RESOURCES += \
     /java.base/java/** \
@@ -142,7 +142,7 @@
 	$(ECHO) Creating jdk jimage
 	$(RM) -r $(JDK_IMAGE_DIR)
 	$(JLINK_TOOL) --add-modules $(JDK_MODULES_LIST) \
- 	    $(JLINK_JDK_EXTRA_OPTS) \
+	    $(JLINK_JDK_EXTRA_OPTS) \
 	    --output $(JDK_IMAGE_DIR)
 	$(TOUCH) $@
 
@@ -152,7 +152,7 @@
 	$(RM) -r $(JRE_IMAGE_DIR)
 	$(JLINK_TOOL) --add-modules $(JRE_MODULES_LIST) \
 	    $(JLINK_JRE_EXTRA_OPTS) \
- 	    --output $(JRE_IMAGE_DIR)
+	    --output $(JRE_IMAGE_DIR)
 	$(TOUCH) $@
 
 JRE_COMPACT1_IMAGE_DIR := $(JRE_IMAGE_DIR)-compact1
@@ -360,34 +360,15 @@
 JDK_TARGETS += $(JDK_IMAGE_DIR)/src.zip
 
 ################################################################################
-# classlist
-
-ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
-  $(eval $(call SetupCopyFiles, JDK_COPY_CLASSLIST, \
-      FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
-      DEST := $(JDK_IMAGE_DIR)/lib, \
-  ))
-
-  JDK_TARGETS += $(JDK_COPY_CLASSLIST)
-
-  $(eval $(call SetupCopyFiles, JRE_COPY_CLASSLIST, \
-      FILES := $(SUPPORT_OUTPUTDIR)/classlist/classlist, \
-      DEST := $(JRE_IMAGE_DIR)/lib, \
-  ))
-
-  JRE_TARGETS += $(JRE_COPY_CLASSLIST)
-endif
-
-################################################################################
 # /demo dir
 # Avoid doing the expensive find unless called with "jdk" as target.
 ifneq ($(filter jdk, $(MAKECMDGOALS)), )
 
   DEMO_FILES := \
       $(if $(wildcard $(SUPPORT_OUTPUTDIR)/demos/image), \
-        $(call DoubleDollar, $(call DoubleDollar, \
+        $(call DoubleDollar, \
         $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/demos/image \
-            -type f -a ! \( -name "_the*" -o -name "javac_state" \) ))) \
+            -type f -a ! \( -name "_the*" -o -name "javac_state" \) )) \
       )
 
   ifeq ($(ZIP_EXTERNAL_DEBUG_SYMBOLS), true)
--- a/make/InterimImage.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/InterimImage.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -36,15 +36,15 @@
 
 INTERIM_MODULES_LIST := $(call CommaList, $(INTERIM_IMAGE_MODULES))
 
-JMODS := $(patsubst %, $(IMAGES_OUTPUTDIR)/jmods/%.jmod, $(INTERIM_IMAGE_MODULES))
+JMODS := $(patsubst %, $(INTERIM_JMODS_DIR)/%.jmod, $(INTERIM_IMAGE_MODULES))
 
 JLINK_TOOL := $(JLINK) \
-    --module-path $(IMAGES_OUTPUTDIR)/jmods \
+    --module-path $(INTERIM_JMODS_DIR) \
     --endian $(OPENJDK_BUILD_CPU_ENDIAN)
 
 $(INTERIM_IMAGE_DIR)/$(JIMAGE_TARGET_FILE): $(JMODS) \
     $(call DependOnVariable, INTERIM_MODULES_LIST)
-	$(ECHO) Creating interim jimage
+	$(call LogWarn, Creating interim jimage)
 	$(RM) -r $(INTERIM_IMAGE_DIR)
 	$(JLINK_TOOL) \
 	    --output $(INTERIM_IMAGE_DIR) \
--- a/make/Javadoc.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/Javadoc.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -22,140 +22,16 @@
 # questions.
 #
 
+default: all
+
 include $(SPEC)
 include MakeBase.gmk
 
-#################################################################
-#
-# CORE_PKGS environment variable has been moved to the following file
-#
-include CORE_PKGS.gmk
-#
-# Load environment variables for API package names that are not part of
-# the Java SE platform
-#
-include NON_CORE_PKGS.gmk
-
-
-.SUFFIXES: # Delete the default suffixes
-.SUFFIXES: .java
-
-#
-# Definitions for directories
-#
-
-DOCSDIR := $(DOCS_IMAGE_DIR)
-DOCSTMPDIR = $(SUPPORT_OUTPUTDIR)/docs
-
-HOTSPOT_DOCS_IMPORT_PATH=$(HOTSPOT_OUTPUTDIR)/docs
-
-JAVADOC_CMD = $(JAVA) \
-    -Djava.awt.headless=true \
-    $(NEW_JAVADOC)
-
-JAVADOC_CMD_SMALL = $(JAVA_SMALL) \
-    -Djava.awt.headless=true \
-    $(NEW_JAVADOC)
-
-# Copyright year for beginning of Java and some of the apis
-# (Needed when creating the javadocs)
-FIRST_COPYRIGHT_YEAR = 1993
-DOMAPI_FIRST_COPYRIGHT_YEAR = 2005
-MIRROR_FIRST_COPYRIGHT_YEAR = 2004
-DOCLETAPI_FIRST_COPYRIGHT_YEAR = 1993
-TAGLETAPI_FIRST_COPYRIGHT_YEAR = 1993
-JDI_FIRST_COPYRIGHT_YEAR = 1999
-JAAS_FIRST_COPYRIGHT_YEAR = 1998
-JGSS_FIRST_COPYRIGHT_YEAR = 2000
-SMARTCARDIO_FIRST_COPYRIGHT_YEAR = 2005
-HTTPSERVER_FIRST_COPYRIGHT_YEAR = 2005
-MGMT_FIRST_COPYRIGHT_YEAR = 2003
-ATTACH_FIRST_COPYRIGHT_YEAR = 2005
-JCONSOLE_FIRST_COPYRIGHT_YEAR = 2006
-SCTPAPI_FIRST_COPYRIGHT_YEAR = 2009
-TRACING_FIRST_COPYRIGHT_YEAR = 2008
-JSHELLAPI_FIRST_COPYRIGHT_YEAR = 2015
-TREEAPI_FIRST_COPYRIGHT_YEAR = 2005
-NASHORNAPI_FIRST_COPYRIGHT_YEAR = 2014
-DYNALINKAPI_FIRST_COPYRIGHT_YEAR = 2015
-JNLP_FIRST_COPYRIGHT_YEAR = 1998
-PLUGIN2_FIRST_COPYRIGHT_YEAR = 2007
-JDKNET_FIRST_COPYRIGHT_YEAR = 2014
-JACCESSAPI_FIRST_COPYRIGHT_YEAR = 2002
-JSOBJECT_FIRST_COPYRIGHT_YEAR = 1993
-
-# Oracle name
-FULL_COMPANY_NAME = Oracle and/or its affiliates
-
-# Copyright address
-COMPANY_ADDRESS = 500 Oracle Parkway<br>Redwood Shores, CA 94065 USA.
-
-# The trademark symbol
-TRADEMARK = &trade;
-
-# Common copyright lines used
-# The word "Copyright" might optionally be a link to the file cpyr.html.
-# The first year of copyright may vary or not be available.
-# The address to the company might be optional.
-COMMA:= ,
-EMPTY:=
-SPACE:=$(EMPTY) $(EMPTY)
-COPYRIGHT_SYMBOL = &\#x00a9;
-# Macro to construct the copyright line
-# (The GNU make 3.78.1 "if" conditional is broken, fixed in GNU make 3.81)
-define CopyrightLine # optionalurl optionalfirstyear optionaladdress
-$(if $(strip $1),<a href="$(strip $1)">Copyright</a>,Copyright) \
-$(COPYRIGHT_SYMBOL) $(if $2,$2${COMMA},) $(COPYRIGHT_YEAR),\
-$(FULL_COMPANY_NAME). $3 All rights reserved.
-endef
-
-# Url to root of documents
-DOCSDIR_URL = {@docroot}/$(GET2DOCSDIR)
-
-# Url to copyright html file
-COPYRIGHT_URL = $(DOCSDIR_URL)/legal/cpyr.html
-
-# Url to bug filing site
-BUG_SUBMIT_URL = http://bugreport.java.com/bugreport/
-
-# Common line for how to submit a bug or rfe
-BUG_SUBMIT_LINE = <a href="$(BUG_SUBMIT_URL)">Submit a bug or feature</a>
-
-# Url to devdocs page
-DOCS_BASE_URL = http://docs.oracle.com/javase/$(VERSION_SPECIFICATION)/docs
-DEV_DOCS_URL = $(DOCS_BASE_URL)/index.html
-
-# Common Java trademark line
-JAVA_TRADEMARK_LINE = Java is a trademark or registered trademark of \
-$(FULL_COMPANY_NAME) in the US and other countries.
-
-#################################################################
-# Macros:
-
+################################################################################
 
 # List of all possible directories for javadoc to look for sources
-# NOTE: Quotes are required around sourcepath argument only on Windows.
-# Otherwise, you get "No packages or classes specified." due
-# to $(PATH_SEP) being interpreted as an end of
-# command (newline or shell ; character)
-ALL_SOURCE_DIRS := $(wildcard \
-      $(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)/rmic/j* \
-      $(JDK_TOPDIR)/src/*/share/doc/stub \
-      ) \
-      #
-
-ALL_MODULE_SOURCE_DIRS := \
+# Allow custom to overwrite.
+JAVADOC_SOURCE_DIRS = \
       $(SUPPORT_OUTPUTDIR)/gensrc/* \
       $(if $(IMPORT_MODULES_SRC), $(IMPORT_MODULES_SRC)/*) \
       $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS)/classes \
@@ -171,181 +47,56 @@
       $(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) $@
-endef
-
-# Prep for javadoc creation, assumes $@ is an index.html file
-define prep-javadoc
-	@if [ -f "$@" -a "$?" != "" ] ; then \
-	  $(ECHO) "# Dependencies have changed: $?"; \
-	fi
-	$(RM) -r $(@D)
-	$(MKDIR) -p $(@D)
-endef
-
-$(eval $(call FillCacheFind, $(ALL_SOURCE_DIRS)))
-define PackageDependencies
-  $(call CacheFind, $(wildcard $(foreach p, $(subst .,/,$1), $(addsuffix /$p, $(ALL_SOURCE_DIRS)))))
-endef
-
-# Given a list of packages, add packages that exist to $@, print summary
-define PackageFilter # packages
-	@if [ "$1" != "" ] ; then \
-	  for p in $1 ; do \
-	    pd=`$(ECHO) $${p} | $(SED) -e 's@[.]@/@g'`; \
-	    found="false"; \
-	    for cp in $(ALL_SOURCE_DIRS) ; do \
-	      if [ -d $${cp}/$${pd} ] ; then \
-	        $(ECHO) "$${p}" >> $@; \
-	        found="true"; \
-	        break; \
-	      fi; \
-	    done; \
-	    if [ "$${found}" = "false" ] ; then \
-	      $(ECHO) "WARNING: Package not found: $${p}"; \
-	    fi; \
-	  done; \
-	fi
-endef
-
-# Print out a summary of the javadoc command about to be run
-define JavadocSummary # optionsfile packagesfile
-	@$(ECHO) "# Running javadoc for $(patsubst $(OUTPUT_ROOT)/%,%,$@)" $(LOG_WARN)
-	@($(ECHO) "# Options (`$(BASENAME) $1`):"; $(SED) -e 's@^@#   @' $1) $(LOG_DEBUG)
-	@($(ECHO) "# Packages (`$(BASENAME) $2`):";$(SED) -e 's@^@#   @' $2) $(LOG_DEBUG)
-endef
-
-#
-# Different api directories created from root directory
-#
-COREAPI_DOCSDIR = $(DOCSDIR)/api
-JDK_API_DOCSDIR = $(DOCSDIR)/jdk/api
-JRE_API_DOCSDIR = $(DOCSDIR)/jre/api
-PLATFORM_DOCSDIR = $(DOCSDIR)/platform
-
-JAVADOC_ARCHIVE_NAME := jdk-$(VERSION_STRING)-docs.zip
-JAVADOC_ARCHIVE_ASSEMBLY_DIR :=  $(DOCSTMPDIR)/zip-docs
-JAVADOC_ARCHIVE_DIR := $(OUTPUT_ROOT)/bundles
-JAVADOC_ARCHIVE := $(JAVADOC_ARCHIVE_DIR)/$(JAVADOC_ARCHIVE_NAME)
+# Should we use -Xdocrootparent? Allow custom to overwrite.
+DOCROOTPARENT_FLAG = TRUE
 
 # The core api index file is the target for the core api javadocs rule
 # and needs to be defined early so that all other javadoc rules may
 # depend on it.
-COREAPI_INDEX_FILE = $(COREAPI_DOCSDIR)/index.html
-
-# The non-core api javadocs need to be able to access the root of the core
-# api directory, so for jdk/api or jre/api to get to the core api/
-# directory we would use this:
-JDKJRE2COREAPI = ../../api
-
-# Common bottom argument
-define CommonBottom # year
-<font size="-1"><br> $(call CopyrightLine,,$1,)</font>
-endef
-
-# Common trademark bottom argument (Not sure why this is used sometimes)
-define CommonTrademarkBottom # year
-<font size="-1">\
-$(BUG_SUBMIT_LINE)<br>$(JAVA_TRADEMARK_LINE)<br>\
-$(call CopyrightLine,,$1,$(COMPANY_ADDRESS))\
-</font>
-endef
+CORE_INDEX_FILE := $(JAVADOC_OUTPUTDIR)/api/index.html
 
-# Common echo of option
-define OptionOnly # opt
-	if [ "$(strip $1)" != "" ] ; then \
-		$(PRINTF) "%s\n" "$(strip $1)"; \
-	fi
-endef
-
-define OptionPair # opt arg
-	$(PRINTF) "%s '%s'\n" "$(strip $1)" '$(strip $2)'
-endef
+# Symbols
+TRADEMARK := &trade;
+COPYRIGHT_SYMBOL := &$(HASH)x00a9;
+COPYRIGHT_TEXT := Copyright
+ALL_RIGHTS_RESERVED := All rights reserved.
 
-define OptionTrip # opt arg arg
-	$(PRINTF) "%s '%s' '%s'\n" "$(strip $1)" '$(strip $2)' '$(strip $3)'
-endef
+# URLs
+JAVADOC_BASE_URL := http://docs.oracle.com/javase/$(VERSION_SPECIFICATION)/docs
+BUG_SUBMIT_URL := http://bugreport.java.com/bugreport/
 
-# Core api bottom argument (with special sauce)
-COREAPI_BOTTOM = <font size="-1"> $(BUG_SUBMIT_LINE)\
-<br>For further API reference and developer documentation, \
-see <a href="$(DEV_DOCS_URL)" target="_blank">Java SE Documentation</a>. \
-That documentation contains more detailed, developer-targeted descriptions, \
-with conceptual overviews, definitions of terms, workarounds, \
-and working code examples.<br>\
-$(call CopyrightLine,$(COPYRIGHT_URL),$(FIRST_COPYRIGHT_YEAR),)\
-</font>
-
-# Common javadoc options used by all bundles
+################################################################################
+# Text snippets
 
-# This flag may be overridden from a custom makefile
-DOCROOTPARENT_FLAG = -Xdocrootparent $(DOCS_BASE_URL)
+FULL_COMPANY_NAME := Oracle and/or its affiliates
+COMPANY_ADDRESS := 500 Oracle Parkway<br>Redwood Shores, CA 94065 USA.
+BUG_SUBMIT_LINE := <a href="$(BUG_SUBMIT_URL)">Submit a bug or feature</a>
+JAVA_TRADEMARK_LINE := Java is a trademark or registered trademark of \
+    $(FULL_COMPANY_NAME) in the US and other countries.
 
-define COMMON_JAVADOCFLAGS
-    $(call OptionOnly,-XDignore.symbol.file=true) ; \
-    $(call OptionOnly,-quiet) ; \
-    $(call OptionOnly,-use) ; \
-    $(call OptionOnly,-keywords) ; \
-    $(call OptionOnly,$(DOCROOTPARENT_FLAG))
-endef
-
-# Common javadoc tags used by all bundles
-
-# Java language specification cite
-TAG_JLS = jls:a:See <cite> \
-The Java&trade; Language Specification</cite>:
-
-# Java virtual machine specification cite
-TAG_JVMS = jvms:a:See <cite> \
-The Java&trade; Virtual Machine Specification</cite>:
+COMMON_BOTTOM_ADDRESS := $(COMPANY_ADDRESS)
+COMMON_BOTTOM_TEXT := $(BUG_SUBMIT_LINE)<br>$(JAVA_TRADEMARK_LINE)
 
-# In order to get a specific ordering it's necessary to specify the total
-# ordering of tags as the tags are otherwise ordered in order of definition.
-define COMMON_JAVADOCTAGS
-  $(call OptionPair,-tag,beaninfo:X) ; \
-  $(call OptionPair,-tag,revised:X) ; \
-  $(call OptionPair,-tag,since.unbundled:X) ; \
-  $(call OptionPair,-tag,spec:X) ; \
-  $(call OptionPair,-tag,specdefault:X) ; \
-  $(call OptionPair,-tag,Note:X) ; \
-  $(call OptionPair,-tag,ToDo:X) ; \
-  $(call OptionPair,-tag,apiNote:a:API Note:) ; \
-  $(call OptionPair,-tag,implSpec:a:Implementation Requirements:) ; \
-  $(call OptionPair,-tag,implNote:a:Implementation Note:) ; \
-  $(call OptionPair,-tag,param) ; \
-  $(call OptionPair,-tag,return) ; \
-  $(call OptionPair,-tag,throws) ; \
-  $(call OptionPair,-tag,since) ; \
-  $(call OptionPair,-tag,version) ; \
-  $(call OptionPair,-tag,serialData) ; \
-  $(call OptionPair,-tag,factory) ; \
-  $(call OptionPair,-tag,see) ; \
-  $(call OptionPair,-tag,$(TAG_JVMS)) ; \
-  $(call OptionPair,-tag,$(TAG_JLS))
-endef
+CORE_BOTTOM_COPYRIGHT_URL := {@docroot}/../legal/cpyr.html
+CORE_BOTTOM_TEXT := $(BUG_SUBMIT_LINE)\
+<br>For further API reference and developer documentation, \
+see <a href="$(JAVADOC_BASE_URL)/index.html" target="_blank">Java SE \
+Documentation</a>. That documentation contains more detailed, \
+developer-targeted descriptions, with conceptual overviews, definitions of \
+terms, workarounds, and working code examples.
 
-
-
-# Assume we need a draft format when the version string is not a GA version.
-ifeq ($(VERSION_IS_GA), false)
+ifeq ($(VERSION_IS_GA), true)
+  DRAFT_HEADER :=
+  DRAFT_BOTTOM :=
+  DRAFT_WINTITLE :=
+  CORE_TOP_EARLYACCESS :=
+else
+  # We need a draft format when not building the GA version.
   DRAFT_HEADER := <br><strong>DRAFT&nbsp;$(VERSION_STRING)</strong>
   DRAFT_BOTTOM := <br><strong>DRAFT&nbsp;$(VERSION_STRING)</strong>
   DRAFT_WINTITLE := $(VERSION_BUILD)
-  # Early access top text (not used in FCS releases)
-  COREAPI_TOP_EARLYACCESS := \
-<div style="background-color: \#EEEEEE"> \
+  CORE_TOP_EARLYACCESS := \
+<div style="background-color: $$(HASH)EEEEEE"> \
 <div style="padding: 6px; margin-top: 2px; margin-bottom: 6px; \
 margin-left: 6px; margin-right: 6px; text-align: justify; \
 font-size: 80%; font-family: Helvetica, Arial, sans-serif; \
@@ -355,1384 +106,932 @@
 The information is being made available to you solely for purpose of \
 evaluation. \
 </div> </div>
-else
-  DRAFT_HEADER :=
-  DRAFT_BOTTOM :=
-  DRAFT_WINTITLE :=
-  COREAPI_TOP_EARLYACCESS :=
 endif
 
-#################################################################
+################################################################################
+# Support functions for SetupJavadocGeneration
 
-#
-# Load custom Javadoc rules
-#
-
-$(eval $(call IncludeCustomExtension, , Javadoc.gmk))
+# Print an option line to the target file
+# Arguments:
+# arg 1: the option name
+# arg 2-3: optional arguments to the option
+define AddOption
+	$(PRINTF) "%s$(if $(strip $2), '%s',)$(if $(strip $3), '%s',)\n" \
+	    "$(strip $1)"$(if $(strip $2), '$(strip $2)',)$(if $(strip $3), \
+	    '$(strip $3)',) >> $@
+endef
 
-#################################################################
+# This function goes to great pains to exactly mimic the old behavior
+# in all details, including whitespace.
+# Note that COPYRIGHT_YEAR is the current year (from spec.gmk)
+# Arguments:
+# arg 1: first copyright year
+# arg 2: copyright url (optional)
+# arg 3: company address (optional)
+# arg 4: free-form text snippet (optional)
+define GenerateBottom
+  <font size="-1">$(if $(strip $4), $(strip $4))<br> $(if \
+      $(strip $2),<a href="$(strip $2)">$(COPYRIGHT_TEXT)</a>,$(COPYRIGHT_TEXT)) \
+      $(COPYRIGHT_SYMBOL) $(strip $1), $(COPYRIGHT_YEAR), \
+      $(FULL_COMPANY_NAME). $(strip $3) \
+      $(ALL_RIGHTS_RESERVED)$(if $(strip $4), )</font>
+endef
 
-#
-# Default target is same as docs target, create core api and all others it can
+# Speed up finding by filling cache
+$(eval $(call FillCacheFind, $(wildcard $(JAVADOC_SOURCE_DIRS))))
+
+# Prevent # from expanding
+EscapeHash = $(subst $(HASH),{hash},$(strip $1))
+
+################################################################################
+# Setup make rules for running javadoc.
 #
-
-all: docs
-docs: coredocs otherdocs
-
+# Parameter 1 is the name of the rule. This name is used as variable prefix,
+# and the targets generated are listed in a variable by that name. Note that
+# the index.html file will work as a "touch file" for all the magnitude of
+# files that are generated by javadoc.
 #
-# Optional target which bundles all generated javadocs into a zip archive.
-# The dependency on docs is handled in Main.gmk.
-#
-
-zip-docs: $(JAVADOC_ARCHIVE)
-
-#############################################################
+# Remaining parameters are named arguments. These include:
+#   MODULES - Modules to include
+#   PACKAGES - Packages to include
+#   PACKAGE_FILTER - Filter for packages
+#   IS_CORE - Set to TRUE for the Core API package which needs special treatment
+#   API_ROOT - Where to base the documentation (jre or jdk)
+#   DEST_DIR - A directory relative to the API root
+#   OVERVIEW - Path to a html overview file
+#   TITLE - Default title to use for the more specific versions below
+#   WINDOW_TITLE - Title to use in -windowtitle. Computed from TITLE if empty.
+#   HEADER_TITLE - Title to use in -header. Computed from TITLE if empty.
+#   DOC_TITLE - Title to use in -doctitle. Computed from TITLE if empty.
+#   FIRST_COPYRIGHT_YEAR - First year this bundle was introduced
+#   DOCLINT - Doclint level. Defaults to "all".
+#   DOCLINT_PACKAGES - Optional -Xdoclint/package value
+#   ENCODING - Change character encoding (defaults to 'ascii')
+#   SPLIT_INDEX - Enable -splitIndex
+#   BREAKITERATOR - Enable -breakiterator
+#   NODEPRECATEDLIST - Enable nodeprecatedlist
+#   NOINDEX - Enable -noindex and -nonavbar
+#   BOTTOM_COPYRIGHT_URL - Copyright URL to use in -bottom
+#   BOTTOM_ADDRESS - Company address to use in -bottom
+#   BOTTOM_TEXT - Extra text to use in -bottom
+#   EXTRA_TOP - Additional -top data
 #
-# coredocs
-#
-COREAPI_DOCTITLE = Java$(TRADEMARK) Platform, Standard Edition \
-$(VERSION_SPECIFICATION)<br>API Specification
-COREAPI_WINDOWTITLE = Java Platform SE $(VERSION_SPECIFICATION)
-COREAPI_HEADER = \
-<strong>Java$(TRADEMARK)&nbsp;Platform<br>Standard&nbsp;Ed.&nbsp;$(VERSION_SPECIFICATION)</strong>
+SetupJavadocGeneration = $(NamedParamsMacroTemplate)
+define SetupJavadocGenerationBody
+  ifeq ($$($1_IS_CORE), TRUE)
+    $1_JAVA := $$(JAVA)
+    $1_OUTPUT_DIRNAME := api
+  else
+    $1_JAVA := $$(JAVA_SMALL)
+    $1_OUTPUT_DIRNAME := $$($1_API_ROOT)/api/$$($1_DEST_DIR)
+
+    ifeq ($$($1_RELATIVE_CORE_DIR),)
+      # Compute a relative path to core root.
+      # The non-core api javadocs need to be able to access the root of the core
+      # api directory, so for jdk/api or jre/api to get to the core api/
+      # directory we would use this
+      # NOTE: Need to be able to override for broken old code in JShell
+      $1_RELATIVE_CORE_DIR := $$(strip $$(subst $$(call DirToDotDot, \
+          $$(JAVADOC_OUTPUTDIR))/,, $$(call DirToDotDot, \
+          $$(JAVADOC_OUTPUTDIR)/$$($1_OUTPUT_DIRNAME))))
+    endif
+
+    $1_DEPS += $(CORE_INDEX_FILE)
+  endif
 
-# Overview file for core apis
-COREAPI_OVERVIEW = $(JDK_TOPDIR)/src/java.base/share/classes/overview-core.html
+  ifneq ($$($1_OVERVIEW), )
+    $1_DEPS +=  $$($1_OVERVIEW)
+  endif
+
+  ifeq ($$($1_ENCODING), )
+    $1_ENCODING := ascii
+  endif
+
+  ifeq ($$($1_DOCLINT), )
+    $1_DOCLINT := all
+  endif
+
+  ifeq ($$($1_DOC_TITLE), )
+    $1_DOC_TITLE := $$($1_TITLE)
+  endif
+
+  ifeq ($$($1_WINDOW_TITLE), )
+    $1_WINDOW_TITLE := $$(strip $$(subst $$(TRADEMARK),, $$($1_TITLE)))
+  endif
+
+  ifeq ($$($1_HEADER_TITLE), )
+    $1_HEADER_TITLE := $$(strip $$(subst $$(TRADEMARK),, $$($1_TITLE)))
+  endif
+  $1_HEADER := <strong>$$($1_HEADER_TITLE)</strong>
 
-# The options and packages files
-COREAPI_OPTIONS_FILE = $(DOCSTMPDIR)/coredocs.options
-COREAPI_PACKAGES_FILE = $(DOCSTMPDIR)/coredocs.packages
+  $1_BOTTOM := $$(call GenerateBottom, $$($1_FIRST_COPYRIGHT_YEAR), \
+      $$($1_BOTTOM_COPYRIGHT_URL), $$($1_BOTTOM_ADDRESS), $$($1_BOTTOM_TEXT))
 
-# The modules required to be documented
-COREAPI_MODULES = java.se.ee
+  # The index.html, options, and packages files
+  $1_INDEX_FILE := $$(JAVADOC_OUTPUTDIR)/$$($1_OUTPUT_DIRNAME)/index.html
+  $1_OPTIONS_FILE := $$(SUPPORT_OUTPUTDIR)/docs/$1.options
+  $1_PACKAGES_FILE := $$(SUPPORT_OUTPUTDIR)/docs/$1.packages
 
-coredocs: $(COREAPI_INDEX_FILE)
+  $1_PACKAGES_VARDEPS := $$($1_PACKAGES) $$($1_PACKAGES_SINGLE_CLASS)
+  $1_PACKAGES_VARDEPS_FILE := $$(call DependOnVariable, $1_PACKAGES_VARDEPS, \
+       $$($1_PACKAGES_FILE).vardeps)
 
-# Set relative location to core api document root
-$(COREAPI_INDEX_FILE): GET2DOCSDIR=..
+  # Rule for creating a file with the package names in it
+  $$($1_PACKAGES_FILE): $$($1_PACKAGES_VARDEPS_FILE)
+	$$(call LogInfo, Creating Javadoc package file for $1)
+	$$(call MakeDir, $$(@D))
+        ifeq ($$($1_PACKAGES_SINGLE_CLASS), )
+	  $$(ECHO) $$($1_PACKAGES) | $$(TR) ' ' '\n' > $$@
+        else
+          # NOTE: This is for backwards compatibility for taglet
+	  $$(ECHO) $$($1_PACKAGES_SINGLE_CLASS) > $$@
+        endif
 
-# Run javadoc if the index file is out of date or missing
-$(COREAPI_INDEX_FILE): $(COREAPI_OPTIONS_FILE) $(COREAPI_PACKAGES_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(COREAPI_OPTIONS_FILE),$(COREAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD) -d $(@D) \
-	    @$(COREAPI_OPTIONS_FILE) @$(COREAPI_PACKAGES_FILE)
+  # NOTE: Not including $$($1_EXTRA_TOP) due to $$(HASH)
+  $1_OPTIONS_VARDEPS := $$(call EscapeHash, \
+      $$($DOCROOTPARENT_FLAG) $$(JAVADOC_BASE_URL) $$($1_NO_COMMON_TAGS) \
+      $$($1_DOCLINT) $$($1_DOCLINT_PACKAGES) $$(JAVADOC_SOURCE_DIRS) \
+      $$($1_MODULES) $$($1_ENCODING) $$($1_NODEPRECATEDLIST) \
+      $$($1_BREAKITERATOR) $$($1_SPLIT_INDEX) $$($1_OVERVIEW) \
+      $$($1_DOC_TITLE) $$($1_WINDOW_TITLE) $$(DRAFT_WINTITLE) \
+      $$($1_HEADER) $$(DRAFT_HEADER) $$($1_NOINDEX) $$($1_EXTRA_TOP_2) \
+      $$($1_BOTTOM) $$(DRAFT_BOTTOM)) $$($1_PACKAGE_FILTER) $$($1_RELATIVE_CORE_DIR) \
+      $$(JAVADOC_OUTPUTDIR) \
+  )
+  $1_OPTIONS_VARDEPS_FILE := $$(call DependOnVariable, $1_OPTIONS_VARDEPS, \
+       $$($1_OPTIONS_FILE).vardeps)
 
-# Create file with javadoc options in it
-$(COREAPI_OPTIONS_FILE): $(COREAPI_OVERVIEW)
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-          $(call OptionOnly,-Xdoclint:reference) ; \
-          $(call OptionOnly,-Xdoclint/package:-org.omg.*$(COMMA)jdk.internal.logging.*) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(COREAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ISO-8859-1) ; \
-	  $(call OptionOnly,-splitIndex) ; \
-	  $(call OptionPair,-overview,$(COREAPI_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(COREAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(COREAPI_WINDOWTITLE) $(DRAFT_WINTITLE)) ; \
-	  $(call OptionPair,-header,$(COREAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(COREAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	) >> $@
-        ifdef COREAPI_TOP_EARLYACCESS
-	  @$(call OptionPair,-top,$(COREAPI_TOP_EARLYACCESS)) >> $@
+  # Rule for creating a file with javadoc options in it
+  $$($1_OPTIONS_FILE): $$($1_OPTIONS_VARDEPS_FILE)
+	$$(call LogInfo, Creating Javadoc options file for $1)
+	$$(call MakeDir, $$(@D))
+	$$(RM) $$@
+	$$(call AddOption, -XDignore.symbol.file=true)
+        ifneq ($$(LOG_LEVEL), trace)
+	  $$(call AddOption, -quiet)
+        endif
+	$$(call AddOption, -use)
+	$$(call AddOption, -keywords)
+        ifneq ($$($DOCROOTPARENT_FLAG), )
+          # NOTE: Argument to -Xdocrootparent is not quoted to keep backwards compatibility.
+	  $$(call AddOption, -Xdocrootparent $(JAVADOC_BASE_URL))
+        endif
+        ifneq ($$($1_NO_COMMON_TAGS), TRUE)
+          # In order to get a specific ordering it's necessary to specify the total
+          # ordering of tags as the tags are otherwise ordered in order of definition.
+	  $$(call AddOption, -tag, beaninfo:X)
+	  $$(call AddOption, -tag, revised:X)
+	  $$(call AddOption, -tag, since.unbundled:X)
+	  $$(call AddOption, -tag, spec:X)
+	  $$(call AddOption, -tag, specdefault:X)
+	  $$(call AddOption, -tag, Note:X)
+	  $$(call AddOption, -tag, ToDo:X)
+	  $$(call AddOption, -tag, apiNote:a:API Note:)
+	  $$(call AddOption, -tag, implSpec:a:Implementation Requirements:)
+	  $$(call AddOption, -tag, implNote:a:Implementation Note:)
+	  $$(call AddOption, -tag, param)
+	  $$(call AddOption, -tag, return)
+	  $$(call AddOption, -tag, throws)
+	  $$(call AddOption, -tag, since)
+	  $$(call AddOption, -tag, version)
+	  $$(call AddOption, -tag, serialData)
+	  $$(call AddOption, -tag, factory)
+	  $$(call AddOption, -tag, see)
+	  $$(call AddOption, -tag, \
+              jvms:a:See <cite> The Java&trade; Virtual Machine Specification</cite>:)
+	  $$(call AddOption, -tag, \
+              jls:a:See <cite> The Java&trade; Language Specification</cite>:)
+        endif
+	$$(call AddOption, -Xdoclint:$$($1_DOCLINT))
+        ifneq ($$($1_DOCLINT_PACKAGES), )
+	  $$(call AddOption, -Xdoclint/package:$$(call CommaList, $$($1_DOCLINT_PACKAGES)))
+        endif
+	$$(call AddOption, --system, none)
+	$$(call AddOption, --module-source-path, $$(subst ",, $$(call PathList, $$(JAVADOC_SOURCE_DIRS))))
+	$$(call AddOption, --add-modules, $$(call CommaList, $$($1_MODULES)))
+	$$(call AddOption, -encoding, $$($1_ENCODING))
+        ifneq ($$($1_NODEPRECATEDLIST), )
+	  $$(call AddOption, -nodeprecatedlist)
+        endif
+        ifneq ($$($1_BREAKITERATOR), )
+	  $$(call AddOption, -breakiterator)
+        endif
+        ifneq ($$($1_SPLIT_INDEX), )
+	  $$(call AddOption, -splitIndex)
+        endif
+        ifneq ($$($1_OVERVIEW), )
+	  $$(call AddOption, -overview, $$($1_OVERVIEW))
+        endif
+	$$(call AddOption, -doctitle, $$($1_DOC_TITLE))
+	$$(call AddOption, -windowtitle, $$($1_WINDOW_TITLE) $$(DRAFT_WINTITLE))
+	$$(call AddOption, -header, $$($1_HEADER)$$(DRAFT_HEADER))
+        ifneq ($$($1_NOINDEX), )
+	  $$(call AddOption, -nonavbar)
+	  $$(call AddOption, -noindex)
+        endif
+        ifneq ($$($1_EXTRA_TOP_2), )
+	  $$(call AddOption, -top,$$($1_EXTRA_TOP_2))
+        endif
+	$$(call AddOption, -bottom, $$($1_BOTTOM)$$(DRAFT_BOTTOM))
+        ifneq ($$($1_PACKAGE_FILTER), )
+	  $$(call AddOption, -group, Packages, $$($1_PACKAGE_FILTER))
+        endif
+        ifneq ($$($1_RELATIVE_CORE_DIR), )
+	  $$(call AddOption, -linkoffline, $$($1_RELATIVE_CORE_DIR)/api, $$(JAVADOC_OUTPUTDIR)/api/)
+        endif
+        ifneq ($$($1_EXTRA_TOP), )
+	  $$(call AddOption, -top, $$($1_EXTRA_TOP))
         endif
 
-# Create a file with the package names in it
-$(COREAPI_PACKAGES_FILE): $(call PackageDependencies,$(CORE_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(CORE_PKGS))
-
-#############################################################
-#
-# docletapidocs
-#
-
-ALL_OTHER_TARGETS += docletapidocs
-
-DOCLETAPI_DOCDIR := $(JDK_API_DOCSDIR)/javadoc/doclet
-DOCLETAPI2COREAPI := ../../$(JDKJRE2COREAPI)
-DOCLETAPI_DOCTITLE := Doclet API
-DOCLETAPI_WINDOWTITLE := Doclet API
-DOCLETAPI_HEADER := <strong>Doclet API</strong>
-DOCLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOCLETAPI_FIRST_COPYRIGHT_YEAR))
-DOCLETAPI_GROUPNAME := Packages
-DOCLETAPI_REGEXP := jdk.javadoc.doclet*
-# DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-# The index.html, options, and packages files
-DOCLETAPI_INDEX_FILE = $(DOCLETAPI_DOCDIR)/index.html
-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
-$(DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(DOCLETAPI2COREAPI)/..
+  $1_PACKAGE_DEPS := $$(call CacheFind, $$(wildcard $$(foreach p, \
+      $$(subst .,/,$$(strip $$($1_PACKAGES))), \
+      $$(addsuffix /$$p, $$(wildcard $$(JAVADOC_SOURCE_DIRS))))))
 
-# Run javadoc if the index file is out of date or missing
-$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(DOCLETAPI_OPTIONS_FILE),$(DOCLETAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(DOCLETAPI_OPTIONS_FILE) @$(DOCLETAPI_PACKAGES_FILE)
+  # Rule for actually running javadoc
+  $$($1_INDEX_FILE): $$($1_OPTIONS_FILE) $$($1_PACKAGES_FILE) \
+    $$($1_PACKAGE_DEPS) $$($1_DEPS)
+	$$(call LogWarn, Generating Javadoc for $$($1_OUTPUT_DIRNAME))
+	$$(call MakeDir, $$(@D))
+        ifneq ($$(findstring $$(LOG_LEVEL), debug trace),)
+	  $$(ECHO) "Contents of $$($1_OPTIONS_FILE):" `$$(CAT) $$($1_OPTIONS_FILE)`
+	  $$(ECHO) "Contents of $$($1_PACKAGES_FILE):" `$$(CAT) $$($1_PACKAGES_FILE)`
+        endif
+	$$(call ExecuteWithLog, $$(SUPPORT_OUTPUTDIR)/docs/$1.javadoc, \
+	    $$($1_JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) -d $$(@D) \
+	    @$$($1_OPTIONS_FILE) @$$($1_PACKAGES_FILE))
+	$$(TOUCH) $$($1_INDEX_FILE)
 
-# Create file with javadoc options in it
-$(DOCLETAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(DOCLETAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-breakiterator) ; \
-	  $(call OptionPair,-doctitle,$(DOCLETAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(DOCLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(DOCLETAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(DOCLETAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-group,$(DOCLETAPI_GROUPNAME),$(DOCLETAPI_REGEXP)); \
-	  $(call OptionTrip,-linkoffline,$(DOCLETAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
+  # The output returned will be the index.html file
+  $1 := $$($1_INDEX_FILE)
+endef
 
-# Create a file with the package names in it
-$(DOCLETAPI_PACKAGES_FILE): $(call PackageDependencies,$(DOCLETAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(DOCLETAPI_PKGS))
-
-#############################################################
-#
-# old docletapidocs
-#
-
-ALL_OTHER_TARGETS += olddocletapidocs
+################################################################################
 
-OLD_DOCLET_DIR := $(JDK_API_DOCSDIR)/javadoc/old
-OLD_DOCLETAPI_DOCDIR := $(OLD_DOCLET_DIR)/doclet
-OLD_DOCLETAPI2COREAPI := ../../../$(JDKJRE2COREAPI)
-OLD_DOCLETAPI_DOCTITLE := Doclet API
-OLD_DOCLETAPI_WINDOWTITLE := Doclet API
-OLD_DOCLETAPI_HEADER := <strong>Doclet API</strong>
-OLD_DOCLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOCLETAPI_FIRST_COPYRIGHT_YEAR))
-OLD_DOCLETAPI_GROUPNAME := Packages
-OLD_DOCLETAPI_REGEXP := com.sun.javadoc
-# OLD_DOCLETAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-# The index.html, options, and packages files
-OLD_DOCLETAPI_INDEX_FILE = $(OLD_DOCLETAPI_DOCDIR)/index.html
-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
-$(OLD_DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(OLD_DOCLETAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(OLD_DOCLETAPI_INDEX_FILE): $(OLD_DOCLETAPI_OPTIONS_FILE) $(OLD_DOCLETAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(OLD_DOCLETAPI_OPTIONS_FILE),$(OLD_DOCLETAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(OLD_DOCLETAPI_OPTIONS_FILE) @$(OLD_DOCLETAPI_PACKAGES_FILE)
+CORE_PACKAGES := \
+    java.applet \
+    java.awt \
+    java.awt.color \
+    java.awt.datatransfer \
+    java.awt.desktop \
+    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.invoke \
+    java.lang.management \
+    java.lang.module \
+    java.lang.ref \
+    java.lang.reflect \
+    java.math \
+    java.net \
+    java.net.http \
+    java.net.spi \
+    java.nio \
+    java.nio.channels \
+    java.nio.channels.spi \
+    java.nio.charset \
+    java.nio.charset.spi \
+    java.nio.file \
+    java.nio.file.attribute \
+    java.nio.file.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.time \
+    java.time.chrono \
+    java.time.format \
+    java.time.temporal \
+    java.time.zone \
+    java.util \
+    java.util.concurrent \
+    java.util.concurrent.atomic \
+    java.util.concurrent.locks \
+    java.util.function \
+    java.util.jar \
+    java.util.logging \
+    java.util.prefs \
+    java.util.regex \
+    java.util.spi \
+    java.util.stream \
+    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.plugins.tiff \
+    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.nimbus \
+    javax.swing.plaf.synth \
+    javax.tools \
+    javax.transaction \
+    javax.transaction.xa \
+    javax.xml.catalog \
+    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.ws.spi.http \
+    javax.xml.ws.wsaddressing \
+    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.w3c.dom.ranges \
+    org.w3c.dom.traversal \
+    org.w3c.dom.views \
+    org.xml.sax \
+    org.xml.sax.ext \
+    org.xml.sax.helpers
 
-# Create file with javadoc options in it
-$(OLD_DOCLETAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(OLD_DOCLETAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-breakiterator) ; \
-	  $(call OptionPair,-doctitle,$(OLD_DOCLETAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(OLD_DOCLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(OLD_DOCLETAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(OLD_DOCLETAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-group,$(OLD_DOCLETAPI_GROUPNAME),$(OLD_DOCLETAPI_REGEXP)); \
-	  $(call OptionTrip,-linkoffline,$(OLD_DOCLETAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
+$(eval $(call SetupJavadocGeneration, coredocs, \
+    MODULES := java.se.ee, \
+    PACKAGES := $(CORE_PACKAGES), \
+    IS_CORE := TRUE, \
+    OVERVIEW := $(JDK_TOPDIR)/src/java.base/share/classes/overview-core.html, \
+    WINDOW_TITLE := Java Platform SE $(VERSION_SPECIFICATION), \
+    HEADER_TITLE := Java$(TRADEMARK)&nbsp;Platform<br>Standard&nbsp;Ed.&nbsp;$(VERSION_SPECIFICATION), \
+    DOC_TITLE := Java$(TRADEMARK) Platform$(COMMA) Standard Edition \
+      $(VERSION_SPECIFICATION)<br>API Specification, \
+    FIRST_COPYRIGHT_YEAR := 1993, \
+    DOCLINT := reference, \
+    DOCLINT_PACKAGES := -org.omg.* jdk.internal.logging.*, \
+    ENCODING := ISO-8859-1, \
+    SPLIT_INDEX := TRUE, \
+    BOTTOM_COPYRIGHT_URL := $(CORE_BOTTOM_COPYRIGHT_URL), \
+    BOTTOM_TEXT := $(CORE_BOTTOM_TEXT), \
+    EXTRA_TOP := $(CORE_TOP_EARLYACCESS), \
+))
 
-# Create a file with the package names in it
-$(OLD_DOCLETAPI_PACKAGES_FILE): $(call PackageDependencies,$(OLD_DOCLETAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(OLD_DOCLETAPI_PKGS))
+TARGETS += $(coredocs)
+
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, docletapi, \
+    MODULES := jdk.javadoc, \
+    PACKAGES := \
+        jdk.javadoc.doclet \
+        jdk.javadoc.doclet.taglet \
+        jdk.javadoc.doclets, \
+    PACKAGE_FILTER := jdk.javadoc.doclet*, \
+    API_ROOT := jdk, \
+    DEST_DIR := javadoc/doclet, \
+    TITLE := Doclet API, \
+    FIRST_COPYRIGHT_YEAR := 1993, \
+    BREAKITERATOR := TRUE, \
+    BOTTOM_ADDRESS := $(COMMON_BOTTOM_ADDRESS), \
+    BOTTOM_TEXT := $(COMMON_BOTTOM_TEXT), \
+))
 
-#############################################################
-#
-# tagletapidocs
-#
+TARGETS += $(docletapi)
+
+################################################################################
 
-ALL_OTHER_TARGETS += tagletapidocs
-TAGLETAPI_DOCDIR := $(OLD_DOCLET_DIR)/taglet
-TAGLETAPI2COREAPI := ../../../$(JDKJRE2COREAPI)
-TAGLETAPI_DOCTITLE := Taglet API
-TAGLETAPI_WINDOWTITLE := Taglet API
-TAGLETAPI_HEADER := <strong>Taglet API</strong>
-TAGLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(TAGLETAPI_FIRST_COPYRIGHT_YEAR))
-# TAGLETAPI_FILE is located in NON_CORE_PKGS.gmk
+$(eval $(call SetupJavadocGeneration, old-docletapi, \
+    MODULES := jdk.javadoc, \
+    PACKAGES := com.sun.javadoc, \
+    PACKAGE_FILTER := com.sun.javadoc, \
+    API_ROOT := jdk, \
+    DEST_DIR := javadoc/old/doclet, \
+    TITLE := Doclet API, \
+    FIRST_COPYRIGHT_YEAR := 1993, \
+    BREAKITERATOR := TRUE, \
+    BOTTOM_ADDRESS := $(COMMON_BOTTOM_ADDRESS), \
+    BOTTOM_TEXT := $(COMMON_BOTTOM_TEXT), \
+))
+
+TARGETS += $(old-docletapi)
 
-# The index.html, options, and packages files
-TAGLETAPI_INDEX_FILE = $(TAGLETAPI_DOCDIR)/index.html
-TAGLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/tagletapi.options
-TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages
+################################################################################
 
-# The modules required to be documented
-TAGLETAPI_MODULES = jdk.javadoc
+# Specify a single class instead of a package
+TAGLET_PACKAGE_SINGLE_CLASS := com/sun/tools/doclets/Taglet.java
+TAGLET_PACKAGE_DIR := $(LANGTOOLS_TOPDIR)/src/jdk.javadoc/share/classes
 
-tagletapidocs: $(TAGLETAPI_INDEX_FILE)
-
-# Run javadoc if the index file is out of date or missing
-$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(TAGLETAPI_OPTIONS_FILE),$(TAGLETAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(TAGLETAPI_OPTIONS_FILE) @$(TAGLETAPI_PACKAGES_FILE)
+$(eval $(call SetupJavadocGeneration, tagletapi, \
+    MODULES := jdk.javadoc, \
+    PACKAGES := com.sun.tools.doclets, \
+    PACKAGES_SINGLE_CLASS := $(TAGLET_PACKAGE_DIR)/$(TAGLET_PACKAGE_SINGLE_CLASS), \
+    API_ROOT := jdk, \
+    DEST_DIR := javadoc/old/taglet, \
+    TITLE := Taglet API, \
+    FIRST_COPYRIGHT_YEAR := 1993, \
+    BREAKITERATOR := TRUE, \
+    NOINDEX := TRUE, \
+    BOTTOM_ADDRESS := $(COMMON_BOTTOM_ADDRESS), \
+    BOTTOM_TEXT := $(COMMON_BOTTOM_TEXT), \
+))
 
-# Create file with javadoc options in it
-$(TAGLETAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(TAGLETAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-breakiterator) ; \
-	  $(call OptionPair,-doctitle,$(TAGLETAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(TAGLETAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(TAGLETAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionOnly,-nonavbar) ; \
-	  $(call OptionOnly,-noindex) ; \
-	  $(call OptionPair,-bottom,$(TAGLETAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(TAGLETAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
+TARGETS += $(tagletapi)
+
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, domapi, \
+    MODULES := \
+        java.xml \
+        jdk.xml.dom, \
+    PACKAGES := \
+        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, \
+    PACKAGE_FILTER := org.w3c.dom*, \
+    API_ROOT := jre, \
+    DEST_DIR := plugin/dom, \
+    TITLE := Common DOM API, \
+    FIRST_COPYRIGHT_YEAR := 2005, \
+    DOCLINT := none, \
+    SPLIT_INDEX := TRUE, \
+    BOTTOM_ADDRESS := $(COMMON_BOTTOM_ADDRESS), \
+    BOTTOM_TEXT := $(COMMON_BOTTOM_TEXT), \
+))
+
+TARGETS += $(domapi)
+
+################################################################################
 
-# Create a file with the package names in it
-$(TAGLETAPI_PACKAGES_FILE): $(call PackageDependencies,$(TAGLETAPI_PKGS))
-	$(prep-target)
-	@($(ECHO) "$(LANGTOOLS_TOPDIR)/src/jdk.javadoc/share/classes/$(TAGLETAPI_FILE)" ) > $@
+$(eval $(call SetupJavadocGeneration, jdi, \
+    MODULES := jdk.jdi, \
+    PACKAGES := \
+        com.sun.jdi \
+        com.sun.jdi.event \
+        com.sun.jdi.request \
+        com.sun.jdi.connect \
+        com.sun.jdi.connect.spi, \
+    API_ROOT := jdk, \
+    DEST_DIR := jpda/jdi, \
+    OVERVIEW := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/jdi-overview.html, \
+    TITLE := Java$(TRADEMARK) Debug Interface, \
+    FIRST_COPYRIGHT_YEAR := 1999, \
+    DOCLINT := none, \
+))
 
-#############################################################
-#
-# domapidocs
-#
+TARGETS += $(jdi)
 
-ALL_OTHER_TARGETS += domapidocs
+################################################################################
 
-DOMAPI_DOCDIR := $(JRE_API_DOCSDIR)/plugin/dom
-DOMAPI2COREAPI := ../../$(JDKJRE2COREAPI)
-DOMAPI_DOCTITLE := Common DOM API
-DOMAPI_WINDOWTITLE := Common DOM API
-DOMAPI_HEADER := <strong>Common DOM API</strong>
-DOMAPI_BOTTOM := $(call CommonTrademarkBottom,$(DOMAPI_FIRST_COPYRIGHT_YEAR))
-DOMAPI_GROUPNAME := Packages
-DOMAPI_REGEXP := org.w3c.dom*
-# DOMAPI_PKGS is located in NON_CORE_PKGS.gmk
+$(eval $(call SetupJavadocGeneration, jaas, \
+    MODULES := jdk.security.auth, \
+    PACKAGES := \
+        com.sun.security.auth \
+        com.sun.security.auth.callback \
+        com.sun.security.auth.login \
+        com.sun.security.auth.module, \
+    API_ROOT := jre, \
+    DEST_DIR := security/jaas/spec, \
+    OVERVIEW := $(JDK_TOPDIR)/src/jdk.security.auth/share/classes/jaas-overview.html, \
+    TITLE := Java$(TRADEMARK) Authentication and Authorization Service, \
+    FIRST_COPYRIGHT_YEAR := 1998, \
+    DOCLINT := none, \
+))
+
+TARGETS += $(jaas)
+
+################################################################################
 
-# The index.html, options, and packages files
-DOMAPI_INDEX_FILE = $(DOMAPI_DOCDIR)/index.html
-DOMAPI_OPTIONS_FILE = $(DOCSTMPDIR)/domapi.options
-DOMAPI_PACKAGES_FILE = $(DOCSTMPDIR)/domapi.packages
+$(eval $(call SetupJavadocGeneration, jgss, \
+    MODULES := jdk.security.jgss, \
+    PACKAGES := com.sun.security.jgss, \
+    API_ROOT := jre, \
+    DEST_DIR := security/jgss/spec, \
+    OVERVIEW := $(JDK_TOPDIR)/src/java.security.jgss/share/classes/jgss-overview.html, \
+    TITLE := Java$(TRADEMARK) GSS-API Utilities, \
+    FIRST_COPYRIGHT_YEAR := 2000, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
 
-# The modules required to be documented
-DOMAPI_MODULES = java.xml,jdk.xml.dom
+TARGETS += $(jgss)
 
-domapidocs: $(DOMAPI_INDEX_FILE)
+################################################################################
 
-# Set relative location to core api document root
-$(DOMAPI_INDEX_FILE): GET2DOCSDIR=$(DOMAPI2COREAPI)/..
+$(eval $(call SetupJavadocGeneration, smartcardio, \
+    MODULES := java.smartcardio, \
+    PACKAGES := javax.smartcardio, \
+    API_ROOT := jre, \
+    DEST_DIR := security/smartcardio/spec, \
+    TITLE := Java$(TRADEMARK) Smart Card I/O, \
+    FIRST_COPYRIGHT_YEAR := 2005, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(smartcardio)
+
+################################################################################
 
-# Run javadoc if the index file is out of date or missing
-$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(DOMAPI_OPTIONS_FILE),$(DOMAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(DOMAPI_OPTIONS_FILE) @$(DOMAPI_PACKAGES_FILE)
+$(eval $(call SetupJavadocGeneration, httpserver, \
+    MODULES := jdk.httpserver, \
+    PACKAGES := \
+        com.sun.net.httpserver \
+        com.sun.net.httpserver.spi, \
+    API_ROOT := jre, \
+    DEST_DIR := net/httpserver/spec, \
+    TITLE := Java$(TRADEMARK) HTTP Server, \
+    FIRST_COPYRIGHT_YEAR := 2005, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(httpserver)
 
-# Create file with javadoc options in it
-$(DOMAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(DOMAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-splitIndex) ; \
-	  $(call OptionPair,-doctitle,$(DOMAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(DOMAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(DOMAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(DOMAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-group,$(DOMAPI_GROUPNAME),$(DOMAPI_REGEXP)); \
-	  $(call OptionTrip,-linkoffline,$(DOMAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, jsobject, \
+    MODULES := jdk.jsobject, \
+    PACKAGES := netscape.javascript, \
+    API_ROOT := jre, \
+    DEST_DIR := plugin/jsobject, \
+    FIRST_COPYRIGHT_YEAR := 1993, \
+    TITLE := Java$(TRADEMARK) JSObject Doc, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(jsobject)
+
+################################################################################
 
-# Create a file with the package names in it
-$(DOMAPI_PACKAGES_FILE): $(call PackageDependencies,$(DOMAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(DOMAPI_PKGS))
+$(eval $(call SetupJavadocGeneration, mgmt, \
+    MODULES := jdk.management, \
+    PACKAGES := com.sun.management, \
+    API_ROOT := jre, \
+    DEST_DIR := management/extension, \
+    OVERVIEW := $(JDK_TOPDIR)/src/java.management/share/classes/mgmt-overview.html, \
+    TITLE := Monitoring and Management Interface for the Java$(TRADEMARK) Platform, \
+    FIRST_COPYRIGHT_YEAR := 2003, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(mgmt)
+
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, attach, \
+    MODULES := jdk.attach, \
+    PACKAGES := \
+        com.sun.tools.attach \
+        com.sun.tools.attach.spi, \
+    API_ROOT := jdk, \
+    DEST_DIR := attach/spec, \
+    TITLE := Attach API, \
+    FIRST_COPYRIGHT_YEAR := 2005, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
 
-#############################################################
-#
-# jpdadocs
-#
+TARGETS += $(attach)
+
+################################################################################
 
-ALL_OTHER_TARGETS += jpdadocs
+$(eval $(call SetupJavadocGeneration, jconsole, \
+    MODULES := jdk.jconsole, \
+    PACKAGES := com.sun.tools.jconsole, \
+    API_ROOT := jdk, \
+    DEST_DIR := jconsole/spec, \
+    TITLE := JConsole API, \
+    FIRST_COPYRIGHT_YEAR := 2006, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(jconsole)
 
-jpdadocs: jdidocs jdwpdocs jvmtidocs
+################################################################################
 
-#############################################################
-#
-# jdidocs
-#
-
-ALL_OTHER_TARGETS += jdidocs
+# NOTE: Need to override RELATIVE_CORE_DIR to be bug compatible with old code.
+$(eval $(call SetupJavadocGeneration, jshellapi, \
+    MODULES := jdk.jshell, \
+    PACKAGES := \
+        jdk.jshell \
+        jdk.jshell.spi \
+        jdk.jshell.execution, \
+    API_ROOT := jdk, \
+    DEST_DIR := jshell, \
+    RELATIVE_CORE_DIR := ../../../.., \
+    OVERVIEW := $(LANGTOOLS_TOPDIR)/src/jdk.jshell/share/classes/jdk/jshell/overview.html, \
+    TITLE := JShell API, \
+    HEADER_TITLE := JSHELL API, \
+    FIRST_COPYRIGHT_YEAR := 2015, \
+))
 
-JDI_DOCDIR := $(JDK_API_DOCSDIR)/jpda/jdi
-JDI2COREAPI := ../../$(JDKJRE2COREAPI)
-JDI_DOCTITLE := Java$(TRADEMARK) Debug Interface
-JDI_WINDOWTITLE := Java Debug Interface
-JDI_HEADER := <strong>Java Debug Interface</strong>
-JDI_BOTTOM := $(call CommonBottom,$(JDI_FIRST_COPYRIGHT_YEAR))
-JDI_OVERVIEW := $(JDK_TOPDIR)/src/jdk.jdi/share/classes/jdi-overview.html
-# JDI_PKGS is located in NON_CORE_PKGS.gmk
+TARGETS += $(jshellapi)
+
+################################################################################
 
-# The index.html, options, and packages files
-JDI_INDEX_FILE = $(JDI_DOCDIR)/index.html
-JDI_OPTIONS_FILE = $(DOCSTMPDIR)/jdi.options
-JDI_PACKAGES_FILE = $(DOCSTMPDIR)/jdi.packages
+$(eval $(call SetupJavadocGeneration, treeapi, \
+    MODULES := jdk.compiler, \
+    PACKAGES := \
+        com.sun.source.doctree \
+        com.sun.source.tree \
+        com.sun.source.util, \
+    PACKAGE_FILTER := com.sun.source.*, \
+    API_ROOT := jdk, \
+    DEST_DIR := javac/tree, \
+    TITLE := Compiler Tree API, \
+    FIRST_COPYRIGHT_YEAR := 2005, \
+))
 
-# The modules required to be documented
-JDI_MODULES = jdk.jdi
+TARGETS += $(treeapi)
 
-jdidocs: $(JDI_INDEX_FILE)
+################################################################################
 
-# Set relative location to core api document root
-$(JDI_INDEX_FILE): GET2DOCSDIR=$(JDI2COREAPI)/..
+$(eval $(call SetupJavadocGeneration, nashornapi, \
+    MODULES := jdk.scripting.nashorn, \
+    PACKAGES := \
+        jdk.nashorn.api.scripting \
+        jdk.nashorn.api.tree, \
+    PACKAGE_FILTER := jdk.nashorn.api.*, \
+    API_ROOT := jdk, \
+    DEST_DIR := nashorn, \
+    TITLE := Nashorn API, \
+    FIRST_COPYRIGHT_YEAR := 2014, \
+))
 
-# Run javadoc if the index file is out of date or missing
-$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JDI_OPTIONS_FILE),$(JDI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JDI_OPTIONS_FILE) @$(JDI_PACKAGES_FILE)
+TARGETS += $(nashornapi)
+
+################################################################################
 
-# Create file with javadoc options in it
-$(JDI_OPTIONS_FILE): $(JDI_OVERVIEW)
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JDI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-overview,$(JDI_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(JDI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JDI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JDI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JDI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JDI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
+$(eval $(call SetupJavadocGeneration, dynalinkapi, \
+    MODULES := jdk.dynalink, \
+    PACKAGES := \
+        jdk.dynalink \
+        jdk.dynalink.beans \
+        jdk.dynalink.linker \
+        jdk.dynalink.linker.support \
+        jdk.dynalink.support, \
+    API_ROOT := jdk, \
+    DEST_DIR := dynalink, \
+    TITLE := Dynalink API, \
+    FIRST_COPYRIGHT_YEAR := 2015, \
+))
+
+TARGETS += $(dynalinkapi)
+
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, sctp, \
+    MODULES := jdk.sctp, \
+    PACKAGES := com.sun.nio.sctp, \
+    API_ROOT := jre, \
+    DEST_DIR := nio/sctp/spec, \
+    TITLE := SCTP API, \
+    FIRST_COPYRIGHT_YEAR := 2009, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(sctp)
+
+################################################################################
+
+$(eval $(call SetupJavadocGeneration, jaccess, \
+    MODULES := jdk.accessibility, \
+    PACKAGES := com.sun.java.accessibility.util, \
+    API_ROOT := jre, \
+    DEST_DIR := accessibility/jaccess/spec, \
+    TITLE := JACCESS API, \
+    FIRST_COPYRIGHT_YEAR := 2002, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(jaccess)
 
-# Create a file with the package names in it
-$(JDI_PACKAGES_FILE): $(call PackageDependencies,$(JDI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JDI_PKGS))
+################################################################################
 
-#############################################################
-#
-# jdwpdocs
-#
+$(eval $(call SetupJavadocGeneration, jdknet, \
+    MODULES := jdk.net, \
+    PACKAGES := jdk.net, \
+    API_ROOT := jre, \
+    DEST_DIR := net/socketoptions/spec, \
+    TITLE := jdk.net API, \
+    FIRST_COPYRIGHT_YEAR := 2014, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
 
-ALL_OTHER_TARGETS += jdwpdocs
+TARGETS += $(jdknet)
+
+################################################################################
 
-JDWP_DOCDIR = $(PLATFORM_DOCSDIR)/jpda/jdwp
+# 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.
+$(eval $(call SetupJavadocGeneration, jlinkplugins, \
+    MODULES := jdk.jlink, \
+    PACKAGES := jdk.tools.jlink.plugin, \
+    API_ROOT := jdk, \
+    DEST_DIR := jlink, \
+    TITLE := JLink Plugin API - EXPERIMENTAL, \
+    FIRST_COPYRIGHT_YEAR := 2015, \
+    DOCLINT := none, \
+    NODEPRECATEDLIST := TRUE, \
+))
+
+TARGETS += $(jlinkplugins)
 
-jdwpdocs: $(JDWP_DOCDIR)/jdwp-protocol.html
-$(JDWP_DOCDIR)/jdwp-protocol.html : $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/jdwp-protocol.html
-	$(MKDIR) -p $(@D)
-	$(RM) $@
-	$(CP) $< $@
+################################################################################
+# Copy JDWP html file
+
+JDWP_HTML := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.jdi/jdwp-protocol.html
 
-#############################################################
-#
-# jvmtidocs
-#
+$(eval $(call SetupCopyFiles, COPY_JDWP_HTML, \
+    FILES := $(JDWP_HTML), \
+    DEST := $(JAVADOC_OUTPUTDIR)/platform/jpda/jdwp, \
+))
 
-JVMTI_DOCDIR := $(PLATFORM_DOCSDIR)/jvmti
+COPY_TARGETS += $(COPY_JDWP_HTML)
+
+################################################################################
+# Copy JVMTI html file
+
 # Pick jvmti.html from any jvm variant, they are all the same.
 JVMTI_HTML := $(firstword \
     $(wildcard $(HOTSPOT_OUTPUTDIR)/variant-*/gensrc/jvmtifiles/jvmti.html))
 
 $(eval $(call SetupCopyFiles, COPY_JVMTI_HTML, \
     FILES := $(JVMTI_HTML), \
-    DEST := $(PLATFORM_DOCSDIR)/jvmti, \
+    DEST := $(JAVADOC_OUTPUTDIR)/platform/jvmti, \
 ))
 
-jvmtidocs: $(COPY_JVMTI_HTML)
-
-#############################################################
-#
-# jaasdocs
-#
-
-ALL_OTHER_TARGETS += jaasdocs
-
-JAAS_DOCDIR := $(JRE_API_DOCSDIR)/security/jaas/spec
-JAAS2COREAPI := ../../../$(JDKJRE2COREAPI)
-JAAS_DOCTITLE := Java$(TRADEMARK) Authentication and Authorization Service
-JAAS_WINDOWTITLE := Java Authentication and Authorization Service
-JAAS_HEADER := <strong>Java Authentication and Authorization Service</strong>
-JAAS_BOTTOM := $(call CommonBottom,$(JAAS_FIRST_COPYRIGHT_YEAR))
-# JAAS_PKGS is located in NON_CORE_PKGS.gmk
-JAAS_OVERVIEW := $(JDK_TOPDIR)/src/jdk.security.auth/share/classes/jaas-overview.html
-
-# The index.html, options, and packages files
-JAAS_INDEX_FILE = $(JAAS_DOCDIR)/index.html
-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
-$(JAAS_INDEX_FILE): GET2DOCSDIR=$(JAAS2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JAAS_OPTIONS_FILE),$(JAAS_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JAAS_OPTIONS_FILE) @$(JAAS_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JAAS_OPTIONS_FILE): $(JAAS_OVERVIEW)
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JAAS_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-overview,$(JAAS_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(JAAS_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JAAS_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JAAS_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JAAS_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JAAS2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JAAS_PACKAGES_FILE): $(call PackageDependencies,$(JAAS_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JAAS_PKGS))
-
-#############################################################
-#
-# jgssdocs
-#
-
-ALL_OTHER_TARGETS += jgssdocs
-
-JGSS_DOCDIR := $(JRE_API_DOCSDIR)/security/jgss/spec
-JGSS2COREAPI := ../../../$(JDKJRE2COREAPI)
-JGSS_DOCTITLE := Java$(TRADEMARK) GSS-API Utilities
-JGSS_WINDOWTITLE := Java GSS-API Utilities
-JGSS_HEADER := <strong>Java GSS-API Utilities</strong>
-JGSS_BOTTOM := $(call CommonBottom,$(JGSS_FIRST_COPYRIGHT_YEAR))
-JGSS_OVERVIEW := $(JDK_TOPDIR)/src/java.security.jgss/share/classes/jgss-overview.html
-# JGSS_PKGS is located in NON_CORE_PKGS.gmk
-
-# The index.html, options, and packages files
-JGSS_INDEX_FILE = $(JGSS_DOCDIR)/index.html
-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
-$(JGSS_INDEX_FILE): GET2DOCSDIR=$(JGSS2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JGSS_OPTIONS_FILE),$(JGSS_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JGSS_OPTIONS_FILE) @$(JGSS_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JGSS_OPTIONS_FILE): $(JGSS_OVERVIEW)
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JGSS_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-overview,$(JGSS_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(JGSS_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JGSS_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JGSS_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JGSS_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JGSS2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JGSS_PACKAGES_FILE): $(call PackageDependencies,$(JGSS_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JGSS_PKGS))
-
-#############################################################
-#
-# smartcardiodocs
-#
-
-ALL_OTHER_TARGETS += smartcardiodocs
-
-SMARTCARDIO_DOCDIR := $(JRE_API_DOCSDIR)/security/smartcardio/spec
-SMARTCARDIO2COREAPI := ../../../$(JDKJRE2COREAPI)
-SMARTCARDIO_DOCTITLE := Java$(TRADEMARK) Smart Card I/O
-SMARTCARDIO_WINDOWTITLE := Java Smart Card I/O
-SMARTCARDIO_HEADER := <strong>Java Smart Card I/O</strong>
-SMARTCARDIO_BOTTOM := $(call CommonBottom,$(SMARTCARDIO_FIRST_COPYRIGHT_YEAR))
-# SMARTCARDIO_PKGS is located in NON_CORE_PKGS.gmk
-
-# The index.html, options, and packages files
-SMARTCARDIO_INDEX_FILE = $(SMARTCARDIO_DOCDIR)/index.html
-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
-$(SMARTCARDIO_INDEX_FILE): GET2DOCSDIR=$(SMARTCARDIO2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(SMARTCARDIO_OPTIONS_FILE),$(SMARTCARDIO_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(SMARTCARDIO_OPTIONS_FILE) @$(SMARTCARDIO_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(SMARTCARDIO_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(SMARTCARDIO_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(SMARTCARDIO_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(SMARTCARDIO_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(SMARTCARDIO_HEADER)$(DRAFT_HEADER)); \
-	  $(call OptionPair,-bottom,$(SMARTCARDIO_BOTTOM)$(DRAFT_BOTTOM)); \
-	  $(call OptionTrip,-linkoffline,$(SMARTCARDIO2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(SMARTCARDIO_PACKAGES_FILE): $(call PackageDependencies,$(SMARTCARDIO_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(SMARTCARDIO_PKGS))
-
-#############################################################
-#
-# httpserverdocs
-#
-
-ALL_OTHER_TARGETS += httpserverdocs
-
-HTTPSERVER_DOCDIR := $(JRE_API_DOCSDIR)/net/httpserver/spec
-HTTPSERVER2COREAPI := ../../../$(JDKJRE2COREAPI)
-HTTPSERVER_DOCTITLE := Java$(TRADEMARK) HTTP Server
-HTTPSERVER_WINDOWTITLE := Java HTTP Server
-HTTPSERVER_HEADER := <strong>Java HTTP Server</strong>
-HTTPSERVER_BOTTOM := $(call CommonBottom,$(HTTPSERVER_FIRST_COPYRIGHT_YEAR))
-# HTTPSERVER_PKGS is located in NON_CORE_PKGS.gmk
-
-HTTPSERVER_INDEX_HTML = $(HTTPSERVER_DOCDIR)/index.html
-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
-$(HTTPSERVER_INDEX_HTML): GET2DOCSDIR=$(HTTPSERVER2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(HTTPSERVER_OPTIONS_FILE),$(HTTPSERVER_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(HTTPSERVER_OPTIONS_FILE) @$(HTTPSERVER_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(HTTPSERVER_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(HTTPSERVER_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(HTTPSERVER_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(HTTPSERVER_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(HTTPSERVER_HEADER)$(DRAFT_HEADER)); \
-	  $(call OptionPair,-bottom,$(HTTPSERVER_BOTTOM)$(DRAFT_BOTTOM)); \
-	  $(call OptionTrip,-linkoffline,$(HTTPSERVER2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(HTTPSERVER_PACKAGES_FILE): $(call PackageDependencies,$(HTTPSERVER_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(HTTPSERVER_PKGS))
-
-#############################################################
-#
-# jsobjectdocs
-#
-
-ALL_OTHER_TARGETS += jsobjectdocs
-
-JSOBJECT_DOCDIR := $(JRE_API_DOCSDIR)/plugin/jsobject
-JSOBJECT2COREAPI := ../../$(JDKJRE2COREAPI)
-JSOBJECT_DOCTITLE := Java$(TRADEMARK) JSObject Doc
-JSOBJECT_WINDOWTITLE := Java JSObject Doc
-JSOBJECT_HEADER := <strong>Java JSObject Doc</strong>
-JSOBJECT_BOTTOM := $(call CommonBottom,$(JSOBJECT_FIRST_COPYRIGHT_YEAR))
-# JSOBJECT_PKGS is located in NON_CORE_PKGS.gmk
-
-JSOBJECT_INDEX_HTML = $(JSOBJECT_DOCDIR)/index.html
-JSOBJECT_OPTIONS_FILE = $(DOCSTMPDIR)/jsobject.options
-JSOBJECT_PACKAGES_FILE = $(DOCSTMPDIR)/jsobject.packages
-
-# The modules required to be documented
-JSOBJECT_MODULES = jdk.jsobject
-
-jsobjectdocs: $(JSOBJECT_INDEX_HTML)
-
-# Set relative location to core api document root
-$(JSOBJECT_INDEX_HTML): GET2DOCSDIR=$(JSOBJECT2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JSOBJECT_INDEX_HTML): $(JSOBJECT_OPTIONS_FILE) $(JSOBJECT_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JSOBJECT_OPTIONS_FILE),$(JSOBJECT_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JSOBJECT_OPTIONS_FILE) @$(JSOBJECT_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JSOBJECT_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JSOBJECT_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(JSOBJECT_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JSOBJECT_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JSOBJECT_HEADER)$(DRAFT_HEADER)); \
-	  $(call OptionPair,-bottom,$(JSOBJECT_BOTTOM)$(DRAFT_BOTTOM)); \
-	  $(call OptionTrip,-linkoffline,$(JSOBJECT2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JSOBJECT_PACKAGES_FILE): $(call PackageDependencies,$(JSOBJECT_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JSOBJECT_PKGS))
-
-
-#############################################################
-#
-# mgmtdocs
-#
-
-ALL_OTHER_TARGETS += mgmtdocs
-
-MGMT_DOCDIR := $(JRE_API_DOCSDIR)/management/extension
-MGMT2COREAPI := ../../$(JDKJRE2COREAPI)
-MGMT_DOCTITLE := Monitoring and Management Interface for the Java$(TRADEMARK) Platform
-MGMT_WINDOWTITLE := Monitoring and Management Interface for the Java Platform
-MGMT_HEADER := <strong>Monitoring and Management Interface for the Java Platform</strong>
-MGMT_BOTTOM := $(call CommonBottom,$(MGMT_FIRST_COPYRIGHT_YEAR))
-MGMT_OVERVIEW := $(JDK_TOPDIR)/src/java.management/share/classes/mgmt-overview.html
-# MGMT_PKGS is located in NON_CORE_PKGS.gmk
-
-# The index.html, options, and packages files
-MGMT_INDEX_FILE = $(MGMT_DOCDIR)/index.html
-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
-$(MGMT_INDEX_FILE): GET2DOCSDIR=$(MGMT2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(MGMT_OPTIONS_FILE),$(MGMT_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(MGMT_OPTIONS_FILE) @$(MGMT_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(MGMT_OPTIONS_FILE): $(MGMT_OVERVIEW)
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(MGMT_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-overview,$(MGMT_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(MGMT_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(MGMT_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(MGMT_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(MGMT_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(MGMT2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(MGMT_PACKAGES_FILE): $(call PackageDependencies,$(MGMT_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(MGMT_PKGS))
-
-#############################################################
-#
-# attachdocs
-#
-
-ALL_OTHER_TARGETS += attachdocs
-
-ATTACH_DOCDIR := $(JDK_API_DOCSDIR)/attach/spec
-ATTACH2COREAPI := ../../$(JDKJRE2COREAPI)
-ATTACH_DOCTITLE := Attach API
-ATTACH_WINDOWTITLE := Attach API
-ATTACH_HEADER := <strong>Attach API</strong>
-ATTACH_BOTTOM := $(call CommonBottom,$(ATTACH_FIRST_COPYRIGHT_YEAR))
-# ATTACH_PKGS is located in NON_CORE_PKGS.gmk
-
-ATTACH_INDEX_HTML = $(ATTACH_DOCDIR)/index.html
-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
-$(ATTACH_INDEX_HTML): GET2DOCSDIR=$(ATTACH2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(ATTACH_OPTIONS_FILE),$(ATTACH_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(ATTACH_OPTIONS_FILE) @$(ATTACH_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(ATTACH_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(ATTACH_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(ATTACH_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(ATTACH_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(ATTACH_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(ATTACH_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(ATTACH2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(ATTACH_PACKAGES_FILE): $(call PackageDependencies,$(ATTACH_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(ATTACH_PKGS))
-
-#############################################################
-#
-# jconsoledocs
-#
-
-ALL_OTHER_TARGETS += jconsoledocs
-
-JCONSOLE_DOCDIR := $(JDK_API_DOCSDIR)/jconsole/spec
-JCONSOLE2COREAPI := ../../$(JDKJRE2COREAPI)
-JCONSOLE_DOCTITLE := JConsole API
-JCONSOLE_WINDOWTITLE := JConsole API
-JCONSOLE_HEADER := <strong>JConsole API</strong>
-JCONSOLE_BOTTOM := $(call CommonBottom,$(JCONSOLE_FIRST_COPYRIGHT_YEAR))
-# JCONSOLE_PKGS is located in NON_CORE_PKGS.gmk
-
-JCONSOLE_INDEX_HTML = $(JCONSOLE_DOCDIR)/index.html
-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
-$(JCONSOLE_INDEX_HTML): GET2DOCSDIR=$(JCONSOLE2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JCONSOLE_OPTIONS_FILE),$(JCONSOLE_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JCONSOLE_OPTIONS_FILE) @$(JCONSOLE_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JCONSOLE_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JCONSOLE_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(JCONSOLE_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JCONSOLE_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JCONSOLE_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JCONSOLE_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JCONSOLE2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JCONSOLE_PACKAGES_FILE): $(call PackageDependencies,$(JCONSOLE_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JCONSOLE_PKGS))
+COPY_TARGETS += $(COPY_JVMTI_HTML)
 
-#############################################################
-#
-# jshellapidocs
-#
-
-ALL_OTHER_TARGETS += jshellapidocs
-
-JSHELLAPI_DOCDIR := $(JDK_API_DOCSDIR)/jshell
-JSHELLAPI2COREAPI := ../../$(JDKJRE2COREAPI)
-JSHELLAPI_DOCTITLE := JShell API
-JSHELLAPI_WINDOWTITLE := JShell API
-JSHELLAPI_HEADER := <strong>JSHELL API</strong>
-JSHELLAPI_BOTTOM := $(call CommonBottom,$(JSHELLAPI_FIRST_COPYRIGHT_YEAR))
-JSHELLAPI_OVERVIEW := $(LANGTOOLS_TOPDIR)/src/jdk.jshell/share/classes/jdk/jshell/overview.html
-# JSHELLAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-JSHELLAPI_INDEX_HTML = $(JSHELLAPI_DOCDIR)/index.html
-JSHELLAPI_OPTIONS_FILE = $(DOCSTMPDIR)/jshellapi.options
-JSHELLAPI_PACKAGES_FILE = $(DOCSTMPDIR)/jshellapi.packages
-
-# The modules required to be documented
-JSHELLAPI_MODULES = jdk.jshell
-
-jshellapidocs: $(JSHELLAPI_INDEX_HTML)
-
-# Set relative location to core api document root
-$(JSHELLAPI_INDEX_HTML): GET2DOCSDIR=$(JSHELLAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JSHELLAPI_INDEX_HTML): $(JSHELLAPI_OPTIONS_FILE) $(JSHELLAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JSHELLAPI_OPTIONS_FILE),$(JSHELLAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JSHELLAPI_OPTIONS_FILE) @$(JSHELLAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JSHELLAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JSHELLAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-overview,$(JSHELLAPI_OVERVIEW)) ; \
-	  $(call OptionPair,-doctitle,$(JSHELLAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JSHELLAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JSHELLAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JSHELLAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JSHELLAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JSHELLAPI_PACKAGES_FILE): $(call PackageDependencies,$(JSHELLAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JSHELLAPI_PKGS))
-
-#############################################################
-#
-# treeapidocs
-#
-
-ALL_OTHER_TARGETS += treeapidocs
-
-TREEAPI_DOCDIR := $(JDK_API_DOCSDIR)/javac/tree
-TREEAPI2COREAPI := ../../$(JDKJRE2COREAPI)
-TREEAPI_DOCTITLE := Compiler Tree API
-TREEAPI_WINDOWTITLE := Compiler Tree API
-TREEAPI_HEADER := <strong>Compiler Tree API</strong>
-TREEAPI_BOTTOM := $(call CommonBottom,$(TREEAPI_FIRST_COPYRIGHT_YEAR))
-TREEAPI_GROUPNAME := Packages
-TREEAPI_REGEXP := com.sun.source.*
-# TREEAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-TREEAPI_INDEX_HTML = $(TREEAPI_DOCDIR)/index.html
-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
-$(TREEAPI_INDEX_HTML): GET2DOCSDIR=$(TREEAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(TREEAPI_OPTIONS_FILE),$(TREEAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(TREEAPI_OPTIONS_FILE) @$(TREEAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(TREEAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(TREEAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-doctitle,$(TREEAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(TREEAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(TREEAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(TREEAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-group,$(TREEAPI_GROUPNAME),$(TREEAPI_REGEXP)); \
-	  $(call OptionTrip,-linkoffline,$(TREEAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(TREEAPI_PACKAGES_FILE): $(call PackageDependencies,$(TREEAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(TREEAPI_PKGS))
-
-#############################################################
-#
-# nashornapidocs
-#
-
-ALL_OTHER_TARGETS += nashornapidocs
-
-NASHORNAPI_DOCDIR := $(JDK_API_DOCSDIR)/nashorn
-NASHORNAPI2COREAPI := ../$(JDKJRE2COREAPI)
-NASHORNAPI_DOCTITLE := Nashorn API
-NASHORNAPI_WINDOWTITLE := Nashorn API
-NASHORNAPI_HEADER := <strong>Nashorn API</strong>
-NASHORNAPI_BOTTOM := $(call CommonBottom,$(NASHORNAPI_FIRST_COPYRIGHT_YEAR))
-NASHORNAPI_GROUPNAME := Packages
-NASHORNAPI_REGEXP := jdk.nashorn.api.*
-# NASHORNAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-NASHORNAPI_INDEX_HTML = $(NASHORNAPI_DOCDIR)/index.html
-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
-$(NASHORNAPI_INDEX_HTML): GET2DOCSDIR=$(NASHORNAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(NASHORNAPI_INDEX_HTML): $(NASHORNAPI_OPTIONS_FILE) $(NASHORNAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(NASHORNAPI_OPTIONS_FILE),$(NASHORNAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(NASHORNAPI_OPTIONS_FILE) @$(NASHORNAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(NASHORNAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(NASHORNAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-doctitle,$(NASHORNAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(NASHORNAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(NASHORNAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(NASHORNAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-group,$(NASHORNAPI_GROUPNAME),$(NASHORNAPI_REGEXP)); \
-	  $(call OptionTrip,-linkoffline,$(NASHORNAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(NASHORNAPI_PACKAGES_FILE): $(call PackageDependencies,$(NASHORNAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(NASHORNAPI_PKGS))
-
-#############################################################
-#
-# dynalinkapidocs
-#
-
-ALL_OTHER_TARGETS += dynalinkapidocs
-
-DYNALINKAPI_DOCDIR := $(JDK_API_DOCSDIR)/dynalink
-DYNALINKAPI2COREAPI := ../$(JDKJRE2COREAPI)
-DYNALINKAPI_DOCTITLE := Dynalink API
-DYNALINKAPI_WINDOWTITLE := Dynalink API
-DYNALINKAPI_HEADER := <strong>Dynalink API</strong>
-DYNALINKAPI_BOTTOM := $(call CommonBottom,$(DYNALINKAPI_FIRST_COPYRIGHT_YEAR))
-DYNALINKAPI_GROUPNAME := Packages
-DYNALINKAPI_REGEXP := jdk.dynalink.*
-# DYNALINKAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-DYNALINKAPI_INDEX_HTML = $(DYNALINKAPI_DOCDIR)/index.html
-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
-$(DYNALINKAPI_INDEX_HTML): GET2DOCSDIR=$(DYNALINKAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(DYNALINKAPI_INDEX_HTML): $(DYNALINKAPI_OPTIONS_FILE) $(DYNALINKAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(DYNALINKAPI_OPTIONS_FILE),$(DYNALINKAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(DYNALINKAPI_OPTIONS_FILE) @$(DYNALINKAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(DYNALINKAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(DYNALINKAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionPair,-doctitle,$(DYNALINKAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(DYNALINKAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(DYNALINKAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(DYNALINKAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(DYNALINKAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(DYNALINKAPI_PACKAGES_FILE): $(call PackageDependencies,$(DYNALINKAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(DYNALINKAPI_PKGS))
+################################################################################
+# Optional target which bundles all generated javadocs into a zip archive.
+# The dependency on docs is handled in Main.gmk.
 
-#############################################################
-#
-# sctpdocs
-#
-
-ALL_OTHER_TARGETS += sctpdocs
-
-SCTPAPI_DOCDIR := $(JRE_API_DOCSDIR)/nio/sctp/spec
-SCTPAPI2COREAPI := ../../../$(JDKJRE2COREAPI)
-SCTPAPI_DOCTITLE := SCTP API
-SCTPAPI_WINDOWTITLE := SCTP API
-SCTPAPI_HEADER := <strong>SCTP API</strong>
-SCTPAPI_BOTTOM := $(call CommonBottom,$(SCTPAPI_FIRST_COPYRIGHT_YEAR))
-# SCTPAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-SCTPAPI_INDEX_HTML = $(SCTPAPI_DOCDIR)/index.html
-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
-$(SCTPAPI_INDEX_HTML): GET2DOCSDIR=$(SCTPAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(SCTPAPI_OPTIONS_FILE),$(SCTPAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(SCTPAPI_OPTIONS_FILE) @$(SCTPAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(SCTPAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(SCTPAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(SCTPAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(SCTPAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(SCTPAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(SCTPAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(SCTPAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(SCTPAPI_PACKAGES_FILE): $(call PackageDependencies,$(SCTPAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(SCTPAPI_PKGS))
-
-#############################################################
-#
-# jaccessdocs - Java Accessibility Utilities
-#
-
-ALL_OTHER_TARGETS += jaccessdocs
-
-JACCESSAPI_DOCDIR := $(JRE_API_DOCSDIR)/accessibility/jaccess/spec
-JACCESSAPI2COREAPI := ../../../$(JDKJRE2COREAPI)
-JACCESSAPI_DOCTITLE := JACCESS API
-JACCESSAPI_WINDOWTITLE := JACCESS API
-JACCESSAPI_HEADER := <strong>JACCESS API</strong>
-JACCESSAPI_BOTTOM := $(call CommonBottom,$(JACCESSAPI_FIRST_COPYRIGHT_YEAR))
-# JACCESSAPI_PKGS is located in NON_CORE_PKGS.gmk
-
-JACCESSAPI_INDEX_HTML = $(JACCESSAPI_DOCDIR)/index.html
-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
-$(JACCESSAPI_INDEX_HTML): GET2DOCSDIR=$(JACCESSAPI2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JACCESSAPI_INDEX_HTML): $(JACCESSAPI_OPTIONS_FILE) $(JACCESSAPI_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JACCESSAPI_OPTIONS_FILE),$(JACCESSAPI_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JACCESSAPI_OPTIONS_FILE) @$(JACCESSAPI_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JACCESSAPI_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-	  $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:all) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JACCESSAPI_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(JACCESSAPI_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JACCESSAPI_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JACCESSAPI_HEADER)$(DRAFT_HEADER)) ; \
-	  $(call OptionPair,-bottom,$(JACCESSAPI_BOTTOM)$(DRAFT_BOTTOM)) ; \
-	  $(call OptionTrip,-linkoffline,$(JACCESSAPI2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JACCESSAPI_PACKAGES_FILE): $(call PackageDependencies,$(JACCESSAPI_PKGS))
-	$(prep-target)
-	$(call PackageFilter,$(JACCESSAPI_PKGS))
-
-#############################################################
-#
-# jdk.net docs
-#
-
-ALL_OTHER_TARGETS += jdknetdocs
-
-JDKNET_DOCDIR := $(JRE_API_DOCSDIR)/net/socketoptions/spec
-JDKNET2COREAPI := ../../../$(JDKJRE2COREAPI)
-JDKNET_DOCTITLE := jdk.net API
-JDKNET_WINDOWTITLE := jdk.net API
-JDKNET_HEADER := <strong>jdk.net API</strong>
-JDKNET_BOTTOM := $(call CommonBottom,$(JDKNET_FIRST_COPYRIGHT_YEAR))
-JDKNET_PKGS := jdk.net
-
-JDKNET_INDEX_HTML = $(JDKNET_DOCDIR)/index.html
-JDKNET_OPTIONS_FILE = $(DOCSTMPDIR)/jdknet.options
-JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages
-
-# The modules required to be documented
-JDKNET_MODULES = jdk.net
-
-jdknetdocs: $(JDKNET_INDEX_HTML)
-
-# Set relative location to core api document root
-$(JDKNET_INDEX_HTML): GET2DOCSDIR=$(JDKNET2COREAPI)/..
-
-# Run javadoc if the index file is out of date or missing
-$(JDKNET_INDEX_HTML): $(JDKNET_OPTIONS_FILE) $(JDKNET_PACKAGES_FILE) $(COREAPI_INDEX_FILE)
-	$(prep-javadoc)
-	$(call JavadocSummary,$(JDKNET_OPTIONS_FILE),$(JDKNET_PACKAGES_FILE))
-	$(JAVADOC_CMD_SMALL) -d $(@D) \
-	    @$(JDKNET_OPTIONS_FILE) @$(JDKNET_PACKAGES_FILE)
-
-# Create file with javadoc options in it
-$(JDKNET_OPTIONS_FILE):
-	$(prep-target)
-	@($(call COMMON_JAVADOCFLAGS) ; \
-          $(call COMMON_JAVADOCTAGS) ; \
-	  $(call OptionOnly,-Xdoclint:none) ; \
-          $(call OptionPair,--system,none) ; \
-	  $(call OptionPair,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(JDKNET_MODULES)) ; \
-	  $(call OptionPair,-encoding,ascii) ; \
-	  $(call OptionOnly,-nodeprecatedlist) ; \
-	  $(call OptionPair,-doctitle,$(JDKNET_DOCTITLE)) ; \
-	  $(call OptionPair,-windowtitle,$(JDKNET_WINDOWTITLE) $(DRAFT_WINTITLE)); \
-	  $(call OptionPair,-header,$(JDKNET_HEADER)$(DRAFT_HEADER)); \
-	  $(call OptionPair,-bottom,$(JDKNET_BOTTOM)$(DRAFT_BOTTOM)); \
-	  $(call OptionTrip,-linkoffline,$(JDKNET2COREAPI),$(COREAPI_DOCSDIR)/); \
-	) >> $@
-
-# Create a file with the package names in it
-$(JDKNET_PACKAGES_FILE): $(call PackageDependencies,$(JDKNET_PKGS))
-	$(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.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,--module-source-path,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
-	  $(call OptionPair,--add-modules,$(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)
-
-#
 # Add the core docs as prerequisite to the archive to trigger a rebuild
 # if the core docs were rebuilt. Ideally any doc rebuild should trigger
 # this, but the way prerequisites are currently setup in this file, that
 # is hard to achieve.
-#
 
-$(JAVADOC_ARCHIVE): $(COREAPI_INDEX_FILE)
+JAVADOC_ARCHIVE_NAME := jdk-$(VERSION_STRING)-docs.zip
+JAVADOC_ARCHIVE_ASSEMBLY_DIR := $(SUPPORT_OUTPUTDIR)/docs/zip-docs
+JAVADOC_ARCHIVE_DIR := $(OUTPUT_ROOT)/bundles
+JAVADOC_ARCHIVE := $(JAVADOC_ARCHIVE_DIR)/$(JAVADOC_ARCHIVE_NAME)
+
+$(JAVADOC_ARCHIVE): $(CORE_INDEX_FILE)
 	$(call LogInfo, Compressing javadoc to single $(JAVADOC_ARCHIVE_NAME))
 	$(MKDIR) -p $(JAVADOC_ARCHIVE_DIR)
 	$(RM) -r $(JAVADOC_ARCHIVE_ASSEMBLY_DIR)
 	$(MKDIR) -p $(JAVADOC_ARCHIVE_ASSEMBLY_DIR)
-	all_roots=`$(FIND) $(DOCSDIR) | $(GREP) index.html | grep -v old/doclet`; \
+	all_roots=`$(FIND) $(JAVADOC_OUTPUTDIR) | $(GREP) index.html | grep -v old/doclet`; \
 	pushd $(JAVADOC_ARCHIVE_ASSEMBLY_DIR); \
 	for index_file in $${all_roots} ; do \
 	  target_dir=`dirname $${index_file}`; \
@@ -1742,10 +1041,21 @@
 	$(ZIP) -q -r $(JAVADOC_ARCHIVE) * ; \
 	popd ;
 
-#############################################################
-.PHONY: all docs coredocs otherdocs \
-     $(ALL_OTHER_TARGETS) zip-docs
+ZIP_TARGETS += $(JAVADOC_ARCHIVE)
+
+################################################################################
+
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, , Javadoc.gmk))
 
 ################################################################################
 
-$(eval $(call IncludeCustomExtension, , Javadoc-post.gmk))
+docs-javadoc: $(TARGETS)
+
+docs-copy: $(COPY_TARGETS)
+
+docs-zip: $(ZIP_TARGETS)
+
+all: docs-javadoc docs-copy docs-zip
+
+.PHONY: default all docs-javadoc docs-copy docs-zip
--- a/make/Main.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/Main.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -341,15 +341,15 @@
 # Docs targets
 
 docs-javadoc:
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk docs)
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk docs-javadoc)
 
-docs-jvmtidoc:
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk jvmtidocs)
+docs-copy:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk docs-copy)
 
-zip-docs:
-	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk zip-docs)
+docs-zip:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk docs-zip)
 
-ALL_TARGETS += docs-javadoc docs-jvmtidoc zip-docs
+ALL_TARGETS += docs-javadoc docs-copy docs-zip
 
 ################################################################################
 # Cross compilation support
@@ -376,15 +376,29 @@
 # The interim-image is a small jlinked image that is used to generate artifacts
 # at build time for use when linking the real images.
 
+INTERIM_JMOD_TARGETS := $(addsuffix -interim-jmod, $(INTERIM_IMAGE_MODULES))
+
+define DeclareInterimJmodRecipe
+  $1-interim-jmod:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f CreateJmods.gmk \
+	    MODULE=$1 \
+	    JMODS_DIR=$(INTERIM_JMODS_DIR) \
+	    JMODS_TEMPDIR=$(INTERIM_JMODS_DIR)/temp \
+	    INTERIM_JMOD=true \
+	)
+endef
+
+$(foreach m, $(INTERIM_IMAGE_MODULES), $(eval $(call DeclareInterimJmodRecipe,$m)))
+
 interim-image:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f InterimImage.gmk)
 
 ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
-  generate-classlist:
-	+($(CD) $(JDK_TOPDIR)/make && $(MAKE) $(MAKE_ARGS) -f GenerateClasslist.gmk)
+  generate-link-opt-data:
+	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f GenerateLinkOptData.gmk)
 endif
 
-ALL_TARGETS += interim-image generate-classlist
+ALL_TARGETS += $(INTERIM_JMOD_TARGETS) interim-image generate-link-opt-data
 
 ################################################################################
 # Build tests
@@ -607,13 +621,15 @@
   # When creating a BUILDJDK, the java compilation has already been done by the
   # normal build and copied in.
   ifneq ($(CREATING_BUILDJDK), true)
-    $(foreach m, $(JAVA_MODULES), $(eval $m-jmod: $m-java))
+    $(foreach m, $(JAVA_MODULES), $(eval $m_JMOD_DEPS += $m-java))
   endif
-  $(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))
+  $(foreach m, $(GENDATA_MODULES), $(eval $m_JMOD_DEPS += $m-gendata))
+  $(foreach m, $(RMIC_MODULES), $(eval $m_JMOD_DEPS += $m-rmic))
+  $(foreach m, $(LIBS_MODULES), $(eval $m_JMOD_DEPS += $m-libs))
+  $(foreach m, $(LAUNCHER_MODULES), $(eval $m_JMOD_DEPS += $m-launchers))
+  $(foreach m, $(COPY_MODULES), $(eval $m_JMOD_DEPS += $m-copy))
+  $(foreach m, $(ALL_MODULES), $(eval $m-jmod: $($(m)_JMOD_DEPS)))
+  $(foreach m, $(INTERIM_IMAGE_MODULES), $(eval $m-interim-jmod: $($(m)_JMOD_DEPS)))
 
   # Jmods cannot be created until we have the jmod tool ready to run. During
   # a normal build we run it from the exploded image, but when cross compiling
@@ -636,12 +652,13 @@
       buildtools-modules: create-buildjdk
     else
       # While actually creating the buildjdk, the default deps applies.
-      $(JMOD_TARGETS): $(DEFAULT_JMOD_DEPS)
+      $(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): $(DEFAULT_JMOD_DEPS)
     endif
   else
     # The normal non cross compilation case uses the default deps.
     # To avoid races with the optimize target, that also needs to happen first.
-    $(JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) exploded-image-optimize
+    $(JMOD_TARGETS) $(INTERIM_JMOD_TARGETS): $(DEFAULT_JMOD_DEPS) \
+        exploded-image-optimize
   endif
 
   zip-security: java.base-java java.security.jgss-java java.security.jgss-libs \
@@ -654,16 +671,17 @@
   ifeq ($(ENABLE_GENERATE_CLASSLIST), true)
     ifeq ($(CREATE_BUILDJDK), true)
       # If creating a buildjdk, the interim image needs to be based on that.
-      generate-classlist: create-buildjdk
+      generate-link-opt-data: create-buildjdk
     else ifeq ($(EXTERNAL_BUILDJDK), false)
       # If an external buildjdk has been provided, we skip generating an
       # interim-image and just use the external buildjdk for generating
       # classlist.
-      generate-classlist: interim-image
+      generate-link-opt-data: interim-image
     endif
-    generate-classlist: buildtools-jdk
+    generate-link-opt-data: buildtools-jdk
 
-    jdk-image jre-image: generate-classlist
+    # The generated classlist needs to go into java.base-jmod.
+    java.base-jmod jdk-image jre-image: generate-link-opt-data
   endif
 
   jdk-image: jmods zip-source source-tips demos samples jrtfs-jar
@@ -683,9 +701,10 @@
 
   docs-javadoc: $(GENSRC_TARGETS) rmic
 
-  docs-jvmtidoc: hotspot
+  # The gensrc step for jdk.jdi creates an html file that is used by docs-copy.
+  docs-copy: hotspot jdk.jdi-gensrc
 
-  zip-docs: docs-javadoc docs-jvmtidoc
+  docs-zip: docs-javadoc docs-copy
 
   test: jdk-image test-image
 
@@ -694,7 +713,7 @@
 
   create-buildjdk-interim-image: create-buildjdk-copy
 
-  interim-image: $(addsuffix -jmod, $(INTERIM_IMAGE_MODULES))
+  interim-image: $(INTERIM_JMOD_TARGETS)
 
   test-make: clean-test-make
 
@@ -812,7 +831,7 @@
 endif
 
 # This target builds the documentation image
-docs-image: docs-javadoc docs-jvmtidoc
+docs-image: docs-javadoc docs-copy
 
 # This target builds the test image
 test-image: prepare-test-image test-image-hotspot-jtreg-native \
@@ -860,7 +879,7 @@
 CLEAN_SUPPORT_DIR_TARGETS := $(addprefix clean-, $(CLEAN_SUPPORT_DIRS))
 CLEAN_TESTS += hotspot-jtreg-native jdk-jtreg-native lib
 CLEAN_TEST_TARGETS += $(addprefix clean-test-, $(CLEAN_TESTS))
-CLEAN_PHASES := gensrc java native include docs
+CLEAN_PHASES := gensrc java native include
 CLEAN_PHASE_TARGETS := $(addprefix clean-, $(CLEAN_PHASES))
 CLEAN_MODULE_TARGETS := $(addprefix clean-, $(ALL_MODULES))
 # Construct targets of the form clean-$module-$phase
@@ -872,6 +891,9 @@
 	($(CD) $(OUTPUT_ROOT) && $(RM) -r build*.log*)
 	$(ECHO) Cleaned all build artifacts.
 
+clean-docs:
+	$(call CleanDocs)
+
 $(CLEAN_DIR_TARGETS):
 	$(call CleanDir,$(patsubst clean-%, %, $@))
 
@@ -911,7 +933,7 @@
 	)
 	$(ECHO) Cleaned everything, you will have to re-run configure.
 
-ALL_TARGETS += clean dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_SUPPORT_DIR_TARGETS) \
+ALL_TARGETS += clean clean-docs dist-clean $(CLEAN_DIR_TARGETS) $(CLEAN_SUPPORT_DIR_TARGETS) \
     $(CLEAN_TEST_TARGETS) $(CLEAN_PHASE_TARGETS) $(CLEAN_MODULE_TARGETS) \
     $(CLEAN_MODULE_PHASE_TARGETS)
 
--- a/make/MainSupport.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/MainSupport.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -41,6 +41,15 @@
 	    JOBS=$(JOBS) $1) || true
 endef
 
+define CleanDocs
+	@$(PRINTF) "Cleaning docs ..."
+	@$(PRINTF) "\n" $(LOG_DEBUG)
+	$(RM) -r $(SUPPORT_OUTPUTDIR)/docs
+	$(RM) -r $(SUPPORT_OUTPUTDIR)/javadoc
+	$(RM) -r $(IMAGES_OUTPUTDIR)/docs
+	@$(PRINTF) " done\n"
+endef
+
 # Cleans the dir given as $1
 define CleanDir
 	@$(PRINTF) "Cleaning $(strip $1) build artifacts ..."
@@ -99,15 +108,6 @@
 	@$(PRINTF) " done\n"
 endef
 
-define Clean-docs
-	@$(PRINTF) "Cleaning docs ..."
-	@$(PRINTF) "\n" $(LOG_DEBUG)
-	$(RM) -r $(SUPPORT_OUTPUTDIR)/docs
-	$(RM) -r $(IMAGES_OUTPUTDIR)/docs
-	$(RM) $(OUTPUT_ROOT)/bundles/jdk-*-docs.zip
-	@$(PRINTF) " done\n"
-endef
-
 define CleanModule
   $(call Clean-gensrc, $1)
   $(call Clean-java, $1)
--- a/make/ZipSource.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/ZipSource.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -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,61 +28,68 @@
 include $(SPEC)
 include MakeBase.gmk
 include JavaCompilation.gmk
+include Modules.gmk
+
+SRC_ZIP_WORK_DIR := $(SUPPORT_OUTPUTDIR)/src
 
 # Hook to include the corresponding custom file, if present.
 $(eval $(call IncludeCustomExtension, , ZipSource.gmk))
 
 ################################################################################
+# Create the directory structure for src.zip using symlinks.
+# <module>/<package>/<file>.java
 
-# Use ?= to enable override in custom makefile
-SRC_ZIP_INCLUDES ?= \
-    com \
-    java \
-    javax \
-    jdk \
-    org \
-    sun \
-    #
+# Find extra source dirs for a module that are not part of normal compilation
+# but should be included in src.zip.
+# $1: Module to find dirs for
+ExtraSrcDirs = \
+    $(wildcard $(SUPPORT_OUTPUTDIR)/rmic/$(strip $1))
 
-SRC_ZIP_EXCLUDES ?=
+ALL_MODULES := $(FindAllModules)
 
-SRC_ZIP_SRCS += $(wildcard \
-    $(JDK_TOPDIR)/src/*/share/classes \
-    $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS)/classes \
-    $(JDK_TOPDIR)/src/*/$(OPENJDK_TARGET_OS_API_DIR)/classes \
-    $(LANGTOOLS_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* \
+# Generate the src dirs in the first make invocation and then call this makefile
+# again to create src.zip.
+$(foreach m, $(ALL_MODULES), \
+  $(foreach d, $(call FindModuleSrcDirs, $m) $(call ExtraSrcDirs, $m), \
+    $(eval $d_TARGET := $(SRC_ZIP_WORK_DIR)/$(patsubst $(TOPDIR)/%,%,$d)/$m) \
+    $(if $(SRC_GENERATED), , \
+      $(eval $$($d_TARGET): $d ; \
+          $$(if $(filter $(TOPDIR)/%, $d), $$(link-file-relative), $$(link-file-absolute)) \
+      ) \
     ) \
-    #
+    $(eval SRC_ZIP_SRCS += $$($d_TARGET)) \
+    $(eval SRC_ZIP_SRCS_$m += $$($d_TARGET)) \
+  ) \
+)
+
+TARGETS += $(SRC_ZIP_SRCS)
 
-# Need to copy launcher src files into desired directory structure
-# before zipping the sources.
-$(eval $(call SetupCopyFiles,COPY_LAUNCHER_SRC, \
-    SRC := $(JDK_TOPDIR)/src/java.base, \
-    DEST := $(SUPPORT_OUTPUTDIR)/src/launcher, \
-    FLATTEN := true, \
-    FILES := $(wildcard \
-        $(JDK_TOPDIR)/src/java.base/share/native/launcher/* \
-        $(JDK_TOPDIR)/src/java.base/share/native/libjli/* \
-        $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjli/java_md*)))
+################################################################################
+# Only evaluate the creation of src.zip in a sub make call when the symlinked
+# src directory structure has been generated.
+ifeq ($(SRC_GENERATED), true)
+  $(eval $(call SetupZipArchive, BUILD_SRC_ZIP, \
+      SRC := $(dir $(SRC_ZIP_SRCS)), \
+      INCLUDES := $(SRC_ZIP_INCLUDES), \
+      INCLUDE_FILES := $(SRC_ZIP_INCLUDE_FILES), \
+      EXCLUDES := $(SRC_ZIP_EXCLUDES), \
+      EXCLUDE_FILES := $(SRC_ZIP_EXCLUDE_FILES), \
+      SUFFIXES := .java, \
+      ZIP := $(SUPPORT_OUTPUTDIR)/src.zip, \
+  ))
 
-# This dir needs to exist before macro is evaluated to avoid warning from find.
-$(call MakeDir, $(SUPPORT_OUTPUTDIR)/src)
-$(eval $(call SetupZipArchive,BUILD_SRC_ZIP, \
-    SRC := $(SRC_ZIP_SRCS) $(SUPPORT_OUTPUTDIR)/src, \
-    INCLUDES := $(SRC_ZIP_INCLUDES) launcher, \
-    EXCLUDES := $(SRC_ZIP_EXCLUDES), \
-    EXCLUDE_FILES := $(SRC_ZIP_EXCLUDE_FILES), \
-    SUFFIXES := .java .c .h, \
-    ZIP := $(SUPPORT_OUTPUTDIR)/src.zip, \
-    EXTRA_DEPS := $(COPY_LAUNCHER_SRC)))
+  do-zip: $(BUILD_SRC_ZIP)
+
+  .PHONY: do-zip
+endif
+
+zip: $(SRC_ZIP_SRCS)
+	+$(MAKE) $(MAKE_ARGS) -f ZipSource.gmk do-zip SRC_GENERATED=true
+
+TARGETS += zip
 
 ################################################################################
 
-all: $(BUILD_SRC_ZIP)
+all: $(TARGETS)
 
-.PHONY: default all
+.PHONY: default all zip
--- a/make/common/MakeBase.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/common/MakeBase.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -454,7 +454,7 @@
       Too many named arguments to macro, please update MAX_PARAMS in MakeBase.gmk))
   # Iterate over 2 3 4... and evaluate the named parameters with $1_ as prefix
   $(foreach i,$(PARAM_SEQUENCE), $(if $(strip $($i)),\
-    $(strip $1)_$(strip $($i)))$(NEWLINE))
+    $(strip $1)_$(strip $(call DoubleDollar, $($i))))$(NEWLINE))
   # Debug print all named parameter names and values
   $(if $(findstring $(LOG_LEVEL),debug trace), \
     $(info $0 $(strip $1) $(foreach i,$(PARAM_SEQUENCE), \
@@ -575,25 +575,21 @@
     $($(strip $1)_dotdots)/$($(strip $1)_suffix)
 
 ################################################################################
-# link-file-* works similarly to install file but creates a symlink instead on
-# platforms that support it. There are two versions, either creating a relative
-# or an absolute link.
-ifeq ($(OPENJDK_BUILD_OS), windows)
-  link-file-absolute = $(install-file)
-  link-file-relative = $(install-file)
-else
-  define link-file-relative
+# link-file-* works similarly to install-file but creates a symlink instead.
+# There are two versions, either creating a relative or an absolute link. Be
+# careful when using this on Windows since the symlink created is only valid in
+# the unix emulation environment.
+define link-file-relative
 	$(call MakeDir, $(@D))
 	$(RM) $@
 	$(LN) -s $(call RelativePath, $<, $(@D)) $@
-  endef
+endef
 
-  define link-file-absolute
+define link-file-absolute
 	$(call MakeDir, $(@D))
 	$(RM) $@
 	$(LN) -s $< $@
-  endef
-endif
+endef
 
 ################################################################################
 # Filter out duplicate sub strings while preserving order. Keeps the first occurance.
--- a/make/common/Modules.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/common/Modules.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -108,6 +108,7 @@
     jdk.charsets \
     jdk.crypto.ec \
     jdk.crypto.pkcs11 \
+    jdk.desktop \
     jdk.dynalink \
     jdk.jsobject \
     jdk.localedata \
@@ -177,6 +178,16 @@
           $(patsubst %,%/$(strip $1)/$(sub)/module-info.java, $(TOP_SRC_DIRS))) \
         $(patsubst %,%/$(strip $1)/module-info.java, $(IMPORT_MODULES_SRC)))
 
+# Find module-info.java files in the specific source dir
+# Param 1 - Src dir to find module-info.java files in
+FindModuleInfosForSrcDir = \
+    $(wildcard \
+        $(foreach sub, $(SRC_SUBDIRS), \
+          $(patsubst %,%/*/$(sub)/module-info.java, $(strip $1)) \
+        ) \
+        $(patsubst %,%/*/module-info.java, $(strip $1)) \
+    )
+
 # 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.
@@ -192,6 +203,13 @@
     $(sort $(filter-out $(MODULES_FILTER), \
     $(call GetModuleNameFromModuleInfo, $(MODULE_INFOS))))
 
+# Find all modules in a specific src dir
+# Param 1 - Src dir to find modules in
+FindModulesForSrcDir = \
+    $(sort $(filter-out $(MODULES_FILTER), \
+        $(call GetModuleNameFromModuleInfo, $(call FindModuleInfosForSrcDir, $1)) \
+    ))
+
 FindImportedModules = \
     $(filter-out $(MODULES_FILTER), \
     $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*))))
--- a/make/common/NativeCompilation.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/common/NativeCompilation.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -746,9 +746,10 @@
   # This is a rough heuristic and may not always print accurate information.
   $$($1_BUILD_INFO): $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
         ifeq ($$(wildcard $$($1_TARGET)),)
-	  $(ECHO) 'Creating $$($1_BASENAME) from $$(words $$(filter-out %.vardeps, $$?)) file(s)'
+	  $(ECHO) 'Creating $$(subst $$(BUILD_OUTPUT)/,,$$($1_TARGET)) from $$(words \
+	      $$(filter-out %.vardeps, $$?)) file(s)'
         else
-	  $(ECHO) $$(strip 'Updating $$($1_BASENAME)' \
+	  $(ECHO) $$(strip 'Updating $$(subst $$(BUILD_OUTPUT)/,,$$($1_TARGET))' \
 	      $$(if $$(filter-out %.vardeps, $$?), \
 	        'due to $$(words $$(filter-out %.vardeps, $$?)) file(s)', \
 	      $$(if $$(filter %.vardeps, $$?), 'due to makefile changes')))
--- a/make/common/ZipArchive.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/make/common/ZipArchive.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -73,6 +73,11 @@
     else
       $1_ZIP_INCLUDES := $$(addprefix -i$(SPACE)$(DQUOTE),$$(addsuffix /*$(DQUOTE),$$($1_INCLUDES)))
     endif
+  else
+    ifneq ($$($1_SUFFIXES),)
+      $1_ZIP_INCLUDES := $$(foreach s,$$($1_SUFFIXES), \
+          $$(addprefix -i$(SPACE)$(DQUOTE),*$$s$(DQUOTE)))
+    endif
   endif
   ifneq ($$($1_INCLUDE_FILES),)
     $1_ZIP_INCLUDES += $$(addprefix -i$(SPACE),$$($1_INCLUDE_FILES))
--- a/nashorn/.hgtags	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/.hgtags	Fri Nov 11 16:44:36 2016 +0100
@@ -375,3 +375,5 @@
 e3b11296395b39bfeb3364f26c2ef77fa652e300 jdk-9+139
 785843878cf78d50cc2959ea2c5a4202bbe885b4 jdk-9+140
 a46b7d3867957a868a6cc8ee66c05079b883733a jdk-9+141
+d3f5d7311a1aec3152b17d75046d5d298245a0b4 jdk-9+142
+b4e57ead3fae4939b70dd345d1f6744a1dedfa21 jdk-9+143
--- a/nashorn/samples/dynalink/ArrayStreamLinkerExporter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/ArrayStreamLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -38,9 +38,10 @@
 import java.util.stream.LongStream;
 import java.util.stream.Stream;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
@@ -104,9 +105,9 @@
                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
                 final Operation op = desc.getOperation();
                 final Object name = NamedOperation.getName(op);
-                final boolean getProp = CompositeOperation.contains(
+                final boolean getProp = NamespaceOperation.contains(
                         NamedOperation.getBaseOperation(op),
-                        StandardOperation.GET_PROPERTY);
+                        StandardOperation.GET, StandardNamespace.PROPERTY);
                 if (getProp && "stream".equals(name)) {
                     return new GuardedInvocation(ARRAY_TO_STREAM,
                         Guards.isOfClass(self.getClass(), GUARD_TYPE));
--- a/nashorn/samples/dynalink/BufferIndexingLinkerExporter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/BufferIndexingLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -29,6 +29,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import static jdk.dynalink.StandardNamespace.ELEMENT;
+import static jdk.dynalink.StandardNamespace.PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+import static jdk.dynalink.StandardOperation.SET;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodType;
 import java.nio.Buffer;
@@ -42,10 +47,10 @@
 import java.util.ArrayList;
 import java.util.List;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
-import jdk.dynalink.StandardOperation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
 import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
@@ -135,23 +140,6 @@
         IS_DOUBLEBUFFER = Guards.isInstance(DoubleBuffer.class, GUARD_TYPE);
     }
 
-    // locate the first standard operation from the call descriptor
-    private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
-        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
-        if (base instanceof StandardOperation) {
-            return (StandardOperation)base;
-        } else if (base instanceof CompositeOperation) {
-            final CompositeOperation cop = (CompositeOperation)base;
-            for(int i = 0; i < cop.getOperationCount(); ++i) {
-                final Operation op = cop.getOperation(i);
-                if (op instanceof StandardOperation) {
-                    return (StandardOperation)op;
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
     public List<GuardingDynamicLinker> get() {
         final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
@@ -170,22 +158,25 @@
                 }
 
                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
-                final StandardOperation op = getFirstStandardOperation(desc);
-                if (op == null) {
+                final Operation namedOp = desc.getOperation();
+                final Operation namespaceOp = NamedOperation.getBaseOperation(namedOp);
+                final Operation op = NamespaceOperation.getBaseOperation(namespaceOp);
+                final StandardNamespace ns = StandardNamespace.findFirst(namespaceOp);
+                if (ns == null) {
                     return null;
                 }
 
-                switch (op) {
-                    case GET_ELEMENT:
+                if (op == GET) {
+                    if (ns == ELEMENT) {
                         return linkGetElement(self);
-                    case SET_ELEMENT:
-                        return linkSetElement(self);
-                    case GET_PROPERTY: {
+                    } else if (ns == PROPERTY) {
                         final Object name = NamedOperation.getName(desc.getOperation());
                         if ("length".equals(name)) {
                             return linkLength();
                         }
                     }
+                } else if (op == SET && ns == ELEMENT) {
+                    return linkSetElement(self);
                 }
 
                 return null;
--- a/nashorn/samples/dynalink/DOMLinkerExporter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/DOMLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,9 +35,10 @@
 import java.util.ArrayList;
 import java.util.List;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
@@ -132,9 +133,9 @@
                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
                 final Operation op = desc.getOperation();
                 final Object name = NamedOperation.getName(op);
-                final boolean getProp = CompositeOperation.contains(
+                final boolean getProp = NamespaceOperation.contains(
                         NamedOperation.getBaseOperation(op),
-                        StandardOperation.GET_PROPERTY);
+                        StandardOperation.GET, StandardNamespace.PROPERTY);
                 if (getProp && name instanceof String) {
                     final String nameStr = (String)name;
 
--- a/nashorn/samples/dynalink/MissingMethodLinkerExporter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/MissingMethodLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,9 +35,10 @@
 import java.util.ArrayList;
 import java.util.List;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.BeansLinker;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -99,23 +100,6 @@
             "getName", MethodType.methodType(String.class));
     }
 
-    // locate the first standard operation from the call descriptor
-    private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
-        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
-        if (base instanceof StandardOperation) {
-            return (StandardOperation)base;
-        } else if (base instanceof CompositeOperation) {
-            final CompositeOperation cop = (CompositeOperation)base;
-            for(int i = 0; i < cop.getOperationCount(); ++i) {
-                final Operation op = cop.getOperation(i);
-                if (op instanceof StandardOperation) {
-                    return (StandardOperation)op;
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
     public List<GuardingDynamicLinker> get() {
         final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
@@ -140,8 +124,12 @@
                 // we return that method object. If not, we return a MissingMethod object.
                 if (self instanceof MissingMethodHandler) {
                     // Check if this is a named GET_METHOD first.
-                    final boolean isGetMethod = getFirstStandardOperation(desc) == StandardOperation.GET_METHOD;
-                    final Object name = NamedOperation.getName(desc.getOperation());
+                    final Operation namedOp = desc.getOperation();
+                    final Operation namespaceOp = NamedOperation.getBaseOperation(namedOp);
+                    final Operation op = NamespaceOperation.getBaseOperation(namespaceOp);
+
+                    final boolean isGetMethod = op == StandardOperation.GET && StandardNamespace.findFirst(namespaceOp) == StandardNamespace.METHOD;
+                    final Object name = NamedOperation.getName(namedOp);
                     if (isGetMethod && name instanceof String) {
                         final GuardingDynamicLinker javaLinker = beansLinker.getLinkerForClass(self.getClass());
                         GuardedInvocation inv;
@@ -166,7 +154,7 @@
                 } else if (self instanceof MissingMethod) {
                     // This is step (2). We call MissingMethodHandler.doesNotUnderstand here
                     // Check if this is this a CALL first.
-                    final boolean isCall = getFirstStandardOperation(desc) == StandardOperation.CALL;
+                    final boolean isCall = NamedOperation.getBaseOperation(desc.getOperation()) == StandardOperation.CALL;
                     if (isCall) {
                         MethodHandle mh = DOES_NOT_UNDERSTAND;
 
--- a/nashorn/samples/dynalink/UnderscoreNameLinkerExporter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/UnderscoreNameLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -34,9 +34,10 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
@@ -68,23 +69,6 @@
         return buf.toString();
     }
 
-    // locate the first standard operation from the call descriptor
-    private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
-        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
-        if (base instanceof StandardOperation) {
-            return (StandardOperation)base;
-        } else if (base instanceof CompositeOperation) {
-            final CompositeOperation cop = (CompositeOperation)base;
-            for(int i = 0; i < cop.getOperationCount(); ++i) {
-                final Operation op = cop.getOperation(i);
-                if (op instanceof StandardOperation) {
-                    return (StandardOperation)op;
-                }
-            }
-        }
-        return null;
-    }
-
     @Override
     public List<GuardingDynamicLinker> get() {
         final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
@@ -92,12 +76,14 @@
             @Override
             public GuardedInvocation getGuardedInvocation(final LinkRequest request,
                 final LinkerServices linkerServices) throws Exception {
-                final Object self = request.getReceiver();
                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
                 final Operation op = desc.getOperation();
                 final Object name = NamedOperation.getName(op);
+                final Operation namespaceOp = NamedOperation.getBaseOperation(op);
                 // is this a named GET_METHOD?
-                final boolean isGetMethod = getFirstStandardOperation(desc) == StandardOperation.GET_METHOD;
+                final boolean isGetMethod =
+                        NamespaceOperation.getBaseOperation(namespaceOp) == StandardOperation.GET
+                        && StandardNamespace.findFirst(namespaceOp) == StandardNamespace.METHOD;
                 if (isGetMethod && name instanceof String) {
                     final String str = (String)name;
                     if (str.indexOf('_') == -1) {
@@ -106,13 +92,9 @@
 
                     final String nameStr = translateToCamelCase(str);
                     // create a new call descriptor to use translated name
-                    final CallSiteDescriptor newDesc = new CallSiteDescriptor(
-                        desc.getLookup(),
-                        new NamedOperation(NamedOperation.getBaseOperation(op), nameStr),
-                        desc.getMethodType());
+                    final CallSiteDescriptor newDesc = desc.changeOperation(((NamedOperation)op).changeName(nameStr));
                     // create a new Link request to link the call site with translated name
-                    final LinkRequest newRequest = new SimpleLinkRequest(newDesc,
-                        request.isCallSiteUnstable(), request.getArguments());
+                    final LinkRequest newRequest = request.replaceArguments(newDesc, request.getArguments());
                     // return guarded invocation linking the translated request
                     return linkerServices.getGuardedInvocation(newRequest);
                 }
--- a/nashorn/samples/dynalink/underscore_linker.js	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/samples/dynalink/underscore_linker.js	Fri Nov 11 16:44:36 2016 +0100
@@ -46,5 +46,6 @@
 // but make sure classpath points to the pluggable linker jar!
 
 `jjs -cp underscore_linker.jar underscore.js`
+print($ERR)
 print($OUT)
 
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -83,9 +83,11 @@
 
 package jdk.dynalink;
 
+import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
 import java.util.Objects;
+import java.util.function.Supplier;
 
 /**
  * Call site descriptors contain all the information necessary for linking a
@@ -148,44 +150,82 @@
     }
 
     /**
-     * Creates a new call site descriptor from this descriptor, which is
-     * identical to this, except it changes the method type. Invokes
-     * {@link #changeMethodTypeInternal(MethodType)} and checks that it returns
-     * a descriptor of the same class as this descriptor.
+     * Finds or creates a call site descriptor that only differs in its
+     * method type from this descriptor.
+     * Invokes {@link #changeMethodTypeInternal(MethodType)}.
      *
      * @param newMethodType the new method type
-     * @return a new call site descriptor, with the method type changed.
-     * @throws RuntimeException if {@link #changeMethodTypeInternal(MethodType)}
-     * returned a descriptor of different class than this object.
-     * @throws NullPointerException if {@link #changeMethodTypeInternal(MethodType)}
-     * returned null.
+     * @return a call site descriptor with changed method type.
+     * @throws NullPointerException if {@code newMethodType} is null.
      */
     public final CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
-        final CallSiteDescriptor changed = Objects.requireNonNull(
-                changeMethodTypeInternal(newMethodType),
-                "changeMethodTypeInternal() must not return null.");
+        final CallSiteDescriptor changed = changeMethodTypeInternal(newMethodType);
 
-        if (getClass() != changed.getClass()) {
-            throw new RuntimeException(
-                    "changeMethodTypeInternal() must return an object of the same class it is invoked on.");
+        if (getClass() != CallSiteDescriptor.class) {
+            assertChangeInvariants(changed, "changeMethodTypeInternal");
+            alwaysAssert(operation == changed.operation, () -> "changeMethodTypeInternal must not change the descriptor's operation");
+            alwaysAssert(newMethodType == changed.methodType, () -> "changeMethodTypeInternal didn't set the correct new method type");
         }
-
         return changed;
     }
 
     /**
-     * Creates a new call site descriptor from this descriptor, which is
-     * identical to this, except it changes the method type. Subclasses must
-     * override this method to return an object of their exact class.
+     * Finds or creates a call site descriptor that only differs in its
+     * method type from this descriptor. Subclasses must override this method
+     * to return an object of their exact class. If an overridden method changes
+     * something other than the method type in the descriptor (its class, lookup,
+     * or operation), or returns null, an {@code AssertionError} will be thrown
+     * from {@link #changeMethodType(MethodType)}.
      *
      * @param newMethodType the new method type
-     * @return a new call site descriptor, with the method type changed.
+     * @return a call site descriptor with the changed method type.
      */
     protected CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) {
         return new CallSiteDescriptor(getLookupPrivileged(), operation, newMethodType);
     }
 
     /**
+     * Finds or creates a call site descriptor that only differs in its
+     * operation from this descriptor.
+     * Invokes {@link #changeOperationInternal(Operation)}.
+     *
+     * @param newOperation the new operation
+     * @return a call site descriptor with the changed operation.
+     * @throws NullPointerException if {@code newOperation} is null.
+     * @throws SecurityException if the descriptor's lookup isn't the
+     * {@link MethodHandles#publicLookup()}, and a security manager is present,
+     * and a check for {@code RuntimePermission("dynalink.getLookup")} fails.
+     * This is necessary as changing the operation in the call site descriptor
+     * allows fabrication of descriptors for arbitrary operations with the lookup.
+     */
+    public final CallSiteDescriptor changeOperation(final Operation newOperation) {
+        getLookup(); // force security check
+        final CallSiteDescriptor changed = changeOperationInternal(newOperation);
+
+        if (getClass() != CallSiteDescriptor.class) {
+            assertChangeInvariants(changed, "changeOperationInternal");
+            alwaysAssert(methodType == changed.methodType, () -> "changeOperationInternal must not change the descriptor's method type");
+            alwaysAssert(newOperation == changed.operation, () -> "changeOperationInternal didn't set the correct new operation");
+        }
+        return changed;
+    }
+
+    /**
+     * Finds or creates a call site descriptor that only differs in its
+     * operation from this descriptor. Subclasses must override this method
+     * to return an object of their exact class. If an overridden method changes
+     * something other than the operation in the descriptor (its class, lookup,
+     * or method type), or returns null, an {@code AssertionError} will be thrown
+     * from {@link #changeOperation(Operation)}.
+     *
+     * @param newOperation the new operation
+     * @return a call site descriptor with the changed operation.
+     */
+    protected CallSiteDescriptor changeOperationInternal(final Operation newOperation) {
+        return new CallSiteDescriptor(getLookupPrivileged(), newOperation, methodType);
+    }
+
+    /**
      * Returns true if this call site descriptor is equal to the passed object.
      * It is considered equal if the other object is of the exact same class,
      * their operations and method types are equal, and their lookups have the
@@ -255,4 +295,16 @@
         final StringBuilder b = new StringBuilder(o.length() + mt.length() + 1 + l.length());
         return b.append(o).append(mt).append('@').append(l).toString();
     }
+
+    private void assertChangeInvariants(final CallSiteDescriptor changed, final String caller) {
+        alwaysAssert(changed != null, () -> caller + " must not return null.");
+        alwaysAssert(getClass() == changed.getClass(), () -> caller + " must not change the descriptor's class");
+        alwaysAssert(lookupsEqual(getLookupPrivileged(), changed.getLookupPrivileged()), () -> caller + " must not change the descriptor's lookup");
+    }
+
+    private static void alwaysAssert(final boolean cond, final Supplier<String> errorMessage) {
+        if (!cond) {
+            throw new AssertionError(errorMessage.get());
+        }
+    }
 }
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CompositeOperation.java	Mon Nov 14 11:15:43 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,297 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file, and Oracle licenses the original version of this file under the BSD
- * license:
- */
-/*
-   Copyright 2015 Attila Szegedi
-
-   Licensed under both the Apache License, Version 2.0 (the "Apache License")
-   and the BSD License (the "BSD License"), with licensee being free to
-   choose either of the two at their discretion.
-
-   You may not use this file except in compliance with either the Apache
-   License or the BSD License.
-
-   If you choose to use this file in compliance with the Apache License, the
-   following notice applies to you:
-
-       You may obtain a copy of the Apache License at
-
-           http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing, software
-       distributed under the License is distributed on an "AS IS" BASIS,
-       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-       implied. See the License for the specific language governing
-       permissions and limitations under the License.
-
-   If you choose to use this file in compliance with the BSD License, the
-   following notice applies to you:
-
-       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 the copyright holder nor the names of
-         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 COPYRIGHT HOLDER
-       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.
-*/
-
-package jdk.dynalink;
-
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * Describes an operation that is composed of at least two other operations. The
- * component operations are treated as alternatives to each other in order of
- * preference. The semantics of the composite operation is "first successful".
- * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be
- * interpreted as <i>get the property named "color" on the object, but if the
- * property does not exist, then get the collection element named "color"
- * instead</i>.
- * <p>
- * Composite operations are helpful in implementation of languages that
- * don't distinguish between one or more of the property, method, and element
- * namespaces, or when expressing operations against objects that can be
- * considered both ordinary objects and collections, e.g. Java
- * {@link java.util.Map} objects. A composite operation
- * {@code GET_PROPERTY|GET_ELEMENT:empty} against a Java map will always match
- * the {@link java.util.Map#isEmpty()} property, but
- * {@code GET_ELEMENT|GET_PROPERTY:empty} will actually match a map element with
- * key {@code "empty"} if the map contains that key, and only fall back to the
- * {@code isEmpty()} property getter if the map does not contain the key. If
- * the source language mandates this semantics, it can be easily achieved using
- * composite operations.
- * <p>
- * Even if the language itself doesn't distinguish between some of the
- * namespaces, it can be helpful to map different syntaxes to different
- * compositions. E.g. the source expression {@code obj.color} could map to
- * {@code GET_PROPERTY|GET_ELEMENT|GET_METHOD:color}, but a different source
- * expression that looks like collection element access {@code obj[key]} could
- * be expressed instead as {@code GET_ELEMENT|GET_PROPERTY|GET_METHOD}.
- * Finally, if the retrieved value is subsequently called, then it makes sense
- * to bring {@code GET_METHOD} to the front of the list: the getter part of the
- * source expression {@code obj.color()} should be
- * {@code GET_METHOD|GET_PROPERTY|GET_ELEMENT:color} and the one for
- * {@code obj[key]()} should be {@code GET_METHOD|GET_ELEMENT|GET_PROPERTY}.
- * <p>
- * The elements of a composite operation can not be composites or named
- * operations, but rather simple operations such are elements of
- * {@link StandardOperation}. A composite operation itself can serve as the base
- * operation of a named operation, though; a typical way to construct e.g. the
- * {@code GET_ELEMENT|GET_PROPERTY:empty} from above would be:
- * <pre>
- * Operation getElementOrPropertyEmpty = new NamedOperation(
- *     new CompositeOperation(
- *         StandardOperation.GET_ELEMENT,
- *         StandardOperation.GET_PROPERTY),
- *     "empty");
- * </pre>
- * <p>
- * Not all compositions make sense. Typically, any combination in any order of
- * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and
- * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and
- * {@code SET_ELEMENT}; other standard operations should not be combined. The
- * constructor will allow any combination of operations, though.
- */
-public final class CompositeOperation implements Operation {
-    private final Operation[] operations;
-
-    /**
-     * Constructs a new composite operation.
-     * @param operations the components for this composite operation. The passed
-     * array will be cloned.
-     * @throws IllegalArgumentException if less than two components are
-     * specified, or any component is itself a {@link CompositeOperation} or a
-     * {@link NamedOperation}.
-     * @throws NullPointerException if either the operations array or any of its
-     * elements are {@code null}.
-     */
-    public CompositeOperation(final Operation... operations) {
-        Objects.requireNonNull(operations, "operations array is null");
-        if (operations.length < 2) {
-            throw new IllegalArgumentException("Must have at least two operations");
-        }
-        final Operation[] clonedOps = operations.clone();
-        for(int i = 0; i < clonedOps.length; ++i) {
-            final Operation op = clonedOps[i];
-            if (op == null) {
-                throw new NullPointerException("operations[" + i + "] is null");
-            } else if (op instanceof NamedOperation) {
-                throw new IllegalArgumentException("operations[" + i + "] is a NamedOperation");
-            } else if (op instanceof CompositeOperation) {
-                throw new IllegalArgumentException("operations[" + i + "] is a CompositeOperation");
-            }
-        }
-        this.operations = clonedOps;
-    }
-
-    /**
-     * Returns the component operations in this composite operation. The
-     * returned array is a copy and changes to it don't have effect on this
-     * object.
-     * @return the component operations in this composite operation.
-     */
-    public Operation[] getOperations() {
-        return operations.clone();
-    }
-
-    /**
-     * Returns the number of component operations in this composite operation.
-     * @return the number of component operations in this composite operation.
-     */
-    public int getOperationCount() {
-        return operations.length;
-    }
-
-    /**
-     * Returns the i-th component operation in this composite operation.
-     * @param i the operation index
-     * @return the i-th component operation in this composite operation.
-     * @throws IndexOutOfBoundsException if the index is out of range.
-     */
-    public Operation getOperation(final int i) {
-        try {
-            return operations[i];
-        } catch (final ArrayIndexOutOfBoundsException e) {
-            throw new IndexOutOfBoundsException(Integer.toString(i));
-        }
-    }
-
-    /**
-     * Returns true if this composite operation contains an operation equal to
-     * the specified operation.
-     * @param operation the operation being searched for. Must not be null.
-     * @return true if the if this composite operation contains an operation
-     * equal to the specified operation.
-     */
-    public boolean contains(final Operation operation) {
-        Objects.requireNonNull(operation);
-        for(final Operation component: operations) {
-            if (component.equals(operation)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns true if the other object is also a composite operation and their
-     * component operations are equal.
-     * @param obj the object to compare to
-     * @return true if this object is equal to the other one, false otherwise.
-     */
-    @Override
-    public boolean equals(final Object obj) {
-        if (obj instanceof CompositeOperation) {
-            return Arrays.equals(operations, ((CompositeOperation)obj).operations);
-        }
-        return false;
-    }
-
-    /**
-     * Returns the hash code of this composite operation. Defined to be equal
-     * to {@code java.util.Arrays.hashCode(operations)}.
-     */
-    @Override
-    public int hashCode() {
-        return Arrays.hashCode(operations);
-    };
-
-    /**
-     * Returns the string representation of this composite operation. Defined to
-     * be the {@code toString} of its component operations, each separated by
-     * the vertical line character (e.g. {@code "GET_PROPERTY|GET_ELEMENT"}).
-     * @return the string representation of this composite operation.
-     */
-    @Override
-    public String toString() {
-        final StringBuilder b = new StringBuilder();
-        b.append(operations[0]);
-        for(int i = 1; i < operations.length; ++i) {
-            b.append('|').append(operations[i]);
-        }
-        return b.toString();
-    }
-
-    /**
-     * Returns the components of the passed operation if it is a composite
-     * operation, otherwise returns an array containing the operation itself.
-     * This allows for returning an array of component even if it is not known
-     * whether the operation is itself a composite (treating a non-composite
-     * operation as if it were a single-element composite of itself).
-     * @param op the operation whose components are retrieved.
-     * @return if the passed operation is a composite operation, returns its
-     * {@link #getOperations()}, otherwise returns the operation itself.
-     */
-    public static Operation[] getOperations(final Operation op) {
-        return op instanceof CompositeOperation
-                ? ((CompositeOperation)op).operations.clone()
-                : new Operation[] { op };
-    }
-
-    /**
-     * Returns true if the specified potentially composite operation is a
-     * {@link CompositeOperation} and contains an operation equal to the
-     * specified operation. If {@code composite} is not a
-     * {@link CompositeOperation}, then the two operations are compared for
-     * equality.
-     * @param composite the potentially composite operation. Must not be null.
-     * @param operation the operation being searched for. Must not be null.
-     * @return true if the if the passed operation is a
-     * {@link CompositeOperation} and contains a component operation equal to
-     * the specified operation, or if it is not a {@link CompositeOperation} and
-     * is equal to {@code operation}.
-     */
-    public static boolean contains(final Operation composite, final Operation operation) {
-        if (composite instanceof CompositeOperation) {
-            return ((CompositeOperation)composite).contains(operation);
-        }
-        return composite.equals(Objects.requireNonNull(operation));
-    }
-}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java	Fri Nov 11 16:44:36 2016 +0100
@@ -88,15 +88,47 @@
 /**
  * Operation that associates a name with another operation. Typically used with
  * operations that normally take a name or an index to bind them to a fixed
- * name. E.g. {@code new NamedOperation(StandardOperation.GET_PROPERTY, "color")}
+ * name. E.g.
+ * <pre>
+ *     new NamedOperation(
+ *         new NamespaceOperation(
+ *             StandardOperation.GET,
+ *             StandardNamespace.PROPERTY),
+ *         "color")
+ * </pre>
  * will be a named operation for getting the property named "color" on the
  * object it is applied to, and
- * {@code new NamedOperation(StandardOperation.GET_ELEMENT, 3)} will be a named
- * operation for getting the element at index 3 from the collection it is
- * applied to. In these cases, the expected signature of the call site for the
+ * <pre>
+ *     new NamedOperation(
+ *         new NamespaceOperation(
+ *             StandardOperation.GET,
+ *             StandardNamespace.ELEMENT),
+ *         3)
+ * </pre>
+ * will be a named operation for getting the element at index 3 from the collection
+ * it is applied to ("name" in this context is akin to "address" and encompasses both
+ * textual names, numeric indices, or any other kinds of addressing that linkers can
+ * understand). In these cases, the expected signature of the call site for the
  * operation will change to no longer include the name parameter. Specifically,
  * the documentation for all {@link StandardOperation} members describes how
  * they are affected by being incorporated into a named operation.
+ * <p>While {@code NamedOperation} can be constructed directly, it is often convenient
+ * to use the {@link Operation#named(Object)} factory method instead, e.g.:
+ * <pre>
+ *    StandardOperation.GET
+ *        .withNamespace(StandardNamespace.ELEMENT),
+ *        .named(3)
+ *     )
+ * </pre>
+ * <p>
+ * Even though {@code NamedOperation} is most often used with {@link NamespaceOperation} as
+ * its base, it can have other operations as its base too (except another named operation).
+ * Specifically, {@link StandardOperation#CALL} as well as {@link StandardOperation#NEW} can
+ * both be used with {@code NamedOperation} directly. The contract for these operations is such
+ * that when they are used as named operations, their name is only used for diagnostic messages,
+ * usually containing the textual representation of the source expression that retrieved the
+ * callee, e.g. {@code StandardOperation.CALL.named("window.open")}.
+ * </p>
  */
 public final class NamedOperation implements Operation {
     private final Operation baseOperation;
@@ -116,7 +148,7 @@
      */
     public NamedOperation(final Operation baseOperation, final Object name) {
         if (baseOperation instanceof NamedOperation) {
-            throw new IllegalArgumentException("baseOperation is a named operation");
+            throw new IllegalArgumentException("baseOperation is a NamedOperation");
         }
         this.baseOperation = Objects.requireNonNull(baseOperation, "baseOperation is null");
         this.name = Objects.requireNonNull(name, "name is null");
@@ -139,6 +171,16 @@
     }
 
     /**
+     * Finds or creates a named operation that differs from this one only in the name.
+     * @param newName the new name to replace the old name with.
+     * @return a named operation with the changed name.
+     * @throws NullPointerException if the name is null.
+     */
+    public final NamedOperation changeName(final String newName) {
+        return new NamedOperation(baseOperation, newName);
+    }
+
+    /**
      * Compares this named operation to another object. Returns true if the
      * other object is also a named operation, and both their base operations
      * and name are equal.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/Namespace.java	Fri Nov 11 16:44:36 2016 +0100
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2016 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       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 the copyright holder nor the names of
+         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 COPYRIGHT HOLDER
+       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.
+*/
+
+package jdk.dynalink;
+
+/**
+ * An object that describes a namespace that is the target of a dynamic operation
+ * on an object. Every object can have one or more namespaces. Dynalink defines a
+ * set of standard namespaces with the {@link StandardNamespace} enum. Operations
+ * that need to specify a namespace they operate on can be expressed using
+ * {@link NamespaceOperation}.
+ */
+public interface Namespace {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NamespaceOperation.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2016 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       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 the copyright holder nor the names of
+         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 COPYRIGHT HOLDER
+       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.
+*/
+
+package jdk.dynalink;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Describes an operation that operates on at least one {@link Namespace} of
+ * an object. E.g. a property getter would be described as
+ * <pre>
+ * Operation propertyGetter = new NamespaceOperation(
+ *     StandardOperation.GET,
+ *     StandardNamespace.PROPERTY);
+ * </pre>
+ * They are often combined with {@link NamedOperation}, e.g. to express a
+ * property getter for a property named "color", you would construct:
+ * <pre>
+ * Operation colorPropertyGetter = new NamedOperation(
+ *     new NamespaceOperation(
+ *         StandardOperation.GET,
+ *         StandardNamespace.PROPERTY),
+ *     "color");
+ * </pre>
+ * <p>While {@code NamespaceOperation} can be constructed directly, it is often convenient
+ * to use the {@link Operation#withNamespace(Namespace)} and {@link Operation#withNamespaces(Namespace...)} factory
+ * methods instead, e.g.:
+ * <pre>
+ * Operation getElementOrPropertyEmpty =
+ *     StandardOperation.GET
+ *         .withNamespace(StandardNamespace.PROPERTY)
+ *         .named("color");
+ * </pre>
+ * <h3>Operations on multiple namespaces</h3>
+ * If multiple namespaces are specified, the namespaces are treated as
+ * alternatives to each other in order of preference. The semantics of
+ * such operation is "first applicable".
+ * That is, a composite of {@code GET:PROPERTY|ELEMENT:color} should be
+ * interpreted as <i>get the property named "color" on the object, but if the
+ * property does not exist, then get the collection element named "color"
+ * instead</i>.
+ * <p>
+ * Operations with multiple namespaces are helpful in implementation of languages that
+ * don't distinguish between one or more of the namespaces, or when expressing operations
+ * against objects that can be considered both ordinary objects and collections, e.g. Java
+ * {@link java.util.Map} objects. A {@code GET:PROPERTY|ELEMENT:empty} operation
+ * against a Java map will always match
+ * the {@link java.util.Map#isEmpty()} property, but
+ * {@code GET:ELEMENT|PROPERTY:empty} will actually match a map element with
+ * key {@code "empty"} if the map contains that key, and only fall back to the
+ * {@code isEmpty()} property getter if the map does not contain the key. If
+ * the source language mandates this semantics, it can be easily achieved using
+ * operations on multiple namespaces.
+ * <p>
+ * Even if the language itself doesn't distinguish between some of the
+ * namespaces, it can be helpful to map different syntaxes to different namespace orderings.
+ * E.g. the source expression {@code obj.color} could map to
+ * {@code GET:PROPERTY|ELEMENT|METHOD:color}, but a different source
+ * expression that looks like collection element access {@code obj[key]} could
+ * be expressed instead as {@code GET:ELEMENT|PROPERTY|METHOD} in order to favor the
+ * element semantics. Finally, if the retrieved value is subsequently called, then it makes sense
+ * to bring {@code METHOD} to the front of the namespace list: the getter part of the
+ * source expression {@code obj.color()} could be
+ * {@code GET:METHOD|PROPERTY|ELEMENT:color} and the one for
+ * {@code obj[key]()} could be {@code GET:METHOD|ELEMENT|PROPERTY}.
+ * <p>
+ * The base operation of a namespace operation can not itself be a namespace or named
+ * operation, but rather one of simple operations such are elements of
+ * {@link StandardOperation}. A namespace operation itself can serve as the base
+ * operation of a named operation, though; a typical way to construct e.g. the
+ * {@code GET:ELEMENT|PROPERTY:empty} from above would be:
+ * <pre>
+ * Operation getElementOrPropertyEmpty = StandardOperation.GET
+ *     .withNamespaces(
+ *         StandardNamespace.ELEMENT,
+ *         StandardNamespace.PROPERTY)
+ *     .named("empty");
+ * </pre>
+ */
+public final class NamespaceOperation implements Operation {
+    private final Operation baseOperation;
+    private final Namespace[] namespaces;
+
+    /**
+     * Constructs a new namespace operation.
+     * @param baseOperation the base operation that operates on one or more namespaces.
+     * @param namespaces one or more namespaces this operation operates on.
+     * @throws IllegalArgumentException if less than one namespace is
+     * specified, or the base operation is itself a {@link NamespaceOperation} or a
+     * {@link NamedOperation}.
+     * @throws NullPointerException if either the {@code namespaces} array or any of its
+     * elements are {@code null}, or if {@code baseOperation} is {@code null}.
+     */
+    public NamespaceOperation(final Operation baseOperation, final Namespace... namespaces) {
+        this.baseOperation = Objects.requireNonNull(baseOperation, "baseOperation is null");
+        if (baseOperation instanceof NamedOperation) {
+            throw new IllegalArgumentException("baseOperation is a NamedOperation");
+        } else if (baseOperation instanceof NamespaceOperation) {
+           throw new IllegalArgumentException("baseOperation is a NamespaceOperation");
+        }
+
+        this.namespaces = Objects.requireNonNull(namespaces, "namespaces array is null").clone();
+        if (namespaces.length < 1) {
+            throw new IllegalArgumentException("Must specify at least one namespace");
+        }
+        for(int i = 0; i < namespaces.length; ++i) {
+            final int fi = i;
+            Objects.requireNonNull(namespaces[i], () -> "operations[" + fi + "] is null");
+        }
+    }
+
+    /**
+     * Returns the base operation of this named operation.
+     * @return the base operation of this named operation.
+     */
+    public Operation getBaseOperation() {
+        return baseOperation;
+    }
+
+    /**
+     * Returns the namespaces in this namespace operation. The returned
+     * array is a copy and changes to it don't have effect on this
+     * object.
+     * @return the namespaces in this namespace operation.
+     */
+    public Namespace[] getNamespaces() {
+        return namespaces.clone();
+    }
+
+    /**
+     * Returns the number of namespaces in this namespace operation.
+     * @return the number of namespaces in this namespace operation.
+     */
+    public int getNamespaceCount() {
+        return namespaces.length;
+    }
+
+    /**
+     * Returns the i-th namespace in this namespace operation.
+     * @param i the namespace index
+     * @return the i-th namespace in this namespace operation.
+     * @throws IndexOutOfBoundsException if the index is out of range.
+     */
+    public Namespace getNamespace(final int i) {
+        try {
+            return namespaces[i];
+        } catch (final ArrayIndexOutOfBoundsException e) {
+            throw new IndexOutOfBoundsException(Integer.toString(i));
+        }
+    }
+
+    /**
+     * Returns true if this namespace operation contains a namespace equal to
+     * the specified namespace.
+     * @param namespace the namespace being searched for. Must not be null.
+     * @return true if the if this namespace operation contains a namespace
+     * equal to the specified namespace.
+     */
+    public boolean contains(final Namespace namespace) {
+        Objects.requireNonNull(namespace);
+        for(final Namespace component: namespaces) {
+            if (component.equals(namespace)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the other object is also a namespace operation and their
+     * base operation and namespaces are equal.
+     * @param obj the object to compare to
+     * @return true if this object is equal to the other one, false otherwise.
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof NamespaceOperation) {
+            final NamespaceOperation other = (NamespaceOperation)obj;
+            return baseOperation.equals(other.baseOperation) && Arrays.equals(namespaces, other.namespaces);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the hash code of this namespace operation. Defined to be equal
+     * to {@code baseOperation.hashCode() + 31 * Arrays.hashCode(namespaces)}.
+     */
+    @Override
+    public int hashCode() {
+        return baseOperation.hashCode() + 31 * Arrays.hashCode(namespaces);
+    };
+
+    /**
+     * Returns the string representation of this namespace operation. Defined to
+     * be the {@code toString} of its base operation, followed by a colon character,
+     * followed with the list of its namespaces separated with the vertical line
+     * character (e.g. {@code "GET:PROPERTY|ELEMENT"}).
+     * @return the string representation of this namespace operation.
+     */
+    @Override
+    public String toString() {
+        final StringBuilder b = new StringBuilder();
+        b.append(baseOperation).append(':');
+        b.append(namespaces[0]);
+        for(int i = 1; i < namespaces.length; ++i) {
+            b.append('|').append(namespaces[i]);
+        }
+        return b.toString();
+    }
+
+    /**
+     * If the passed operation is a namespace operation, returns its
+     * {@link #getBaseOperation()}, otherwise returns the operation as is.
+     * @param op the operation
+     * @return the base operation of the passed operation.
+     */
+    public static Operation getBaseOperation(final Operation op) {
+        return op instanceof NamespaceOperation ? ((NamespaceOperation )op).getBaseOperation() : op;
+    }
+
+    /**
+     * If the passed operation is a namespace operation, returns its
+     * {@link #getNamespaces()}, otherwise returns an empty array.
+     * @param op the operation
+     * @return the namespaces of the passed operation.
+     */
+    public static Namespace[] getNamespaces(final Operation op) {
+        return op instanceof NamespaceOperation ? ((NamespaceOperation)op).getNamespaces() : new Namespace[0];
+    }
+
+    /**
+     * Returns true if the specified operation is a {@link NamespaceOperation}
+     * and its base operation is equal to the specified operation, and it
+     * contains the specified namespace. If it is not a {@link NamespaceOperation},
+     * then it returns false.
+     * @param op the operation. Must not be null.
+     * @param baseOperation the base operation being searched for. Must not be null.
+     * @param namespace the namespace being searched for. Must not be null.
+     * @return true if the if the passed operation is a {@link NamespaceOperation},
+     * its base operation equals the searched base operation, and contains a namespace
+     * equal to the searched namespace.
+     */
+    public static boolean contains(final Operation op, final Operation baseOperation, final Namespace namespace) {
+        if (op instanceof NamespaceOperation) {
+            final NamespaceOperation no = (NamespaceOperation)op;
+            return no.baseOperation.equals(baseOperation) && no.contains(namespace);
+        }
+        return false;
+    }
+}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java	Fri Nov 11 16:44:36 2016 +0100
@@ -86,14 +86,51 @@
 /**
  * An object that describes a dynamic operation. Dynalink defines a set of
  * standard operations with the {@link StandardOperation} class, as well as a
- * way to attach a fixed name to an operation using {@link NamedOperation} and
- * to express a set of alternative operations using {@link CompositeOperation}.
+ * way to express the target {@link Namespace namespace(s)} of an operation
+ * on an object using {@link NamespaceOperation} and finally a way to attach
+ * a fixed target name to an operation using {@link NamedOperation}.
  * When presenting examples in this documentation, we will refer to standard
- * operations using their name (e.g. {@code GET_PROPERTY}), to composite
- * operations by separating their components with the vertical line character
- * (e.g. {@code GET_PROPERTY|GET_ELEMENT}), and finally to named operations by
- * separating the base operation and the name with the colon character (e.g.
- * {@code GET_PROPERTY|GET_ELEMENT:color}).
+ * operations using their name (e.g. {@code GET}), to namespace operations
+ * by separating their base operation with a colon from their namespace
+ * (e.g. {@code GET:PROPERTY}), or in case of multiple namespaces we will
+ * further separate those with the vertical line character (e.g.
+ * {@code GET:PROPERTY|ELEMENT}), and finally we will refer to named operations
+ * by separating the base operation and the name with the colon character (e.g.
+ * {@code GET:PROPERTY|ELEMENT:color}).
  */
 public interface Operation {
+    /**
+     * Returns a {@link NamespaceOperation} using this operation as its base.
+     * @param namespace the namespace that is the target of the namespace operation.
+     * @return a {@link NamespaceOperation} with this operation as its base and the specified
+     * namespace as its target.
+     * @throws IllegalArgumentException if this operation is already a namespace operation or a named operation.
+     * @throws NullPointerException if {@code namespace} is null.
+     */
+    default NamespaceOperation withNamespace(final Namespace namespace) {
+        return withNamespaces(namespace);
+    }
+
+    /**
+     * Returns a {@link NamespaceOperation} using this operation as its base.
+     * @param namespaces the namespaces that are the target of the namespace operation.
+     * @return a {@link NamespaceOperation} with this operation as its base and the specified
+     * namespaces as its targets.
+     * @throws IllegalArgumentException if this operation is already a namespace operation or a named operation.
+     * @throws NullPointerException if {@code namespace} or any of its elements is null.
+     */
+    default NamespaceOperation withNamespaces(final Namespace... namespaces) {
+        return new NamespaceOperation(this, namespaces);
+    }
+
+    /**
+     * Returns a {@link NamedOperation} using this operation as its base.
+     * @param name the name that is the target of the named operation.
+     * @return a {@link NamedOperation} with this operation as its base and the specified name.
+     * @throws IllegalArgumentException if this operation is already a named operation.
+     * @throws NullPointerException if {@code name} is null.
+     */
+    default NamedOperation named(final Object name) {
+        return new NamedOperation(this, name);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/StandardNamespace.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file, and Oracle licenses the original version of this file under the BSD
+ * license:
+ */
+/*
+   Copyright 2016 Attila Szegedi
+
+   Licensed under both the Apache License, Version 2.0 (the "Apache License")
+   and the BSD License (the "BSD License"), with licensee being free to
+   choose either of the two at their discretion.
+
+   You may not use this file except in compliance with either the Apache
+   License or the BSD License.
+
+   If you choose to use this file in compliance with the Apache License, the
+   following notice applies to you:
+
+       You may obtain a copy of the Apache License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing, software
+       distributed under the License is distributed on an "AS IS" BASIS,
+       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+       implied. See the License for the specific language governing
+       permissions and limitations under the License.
+
+   If you choose to use this file in compliance with the BSD License, the
+   following notice applies to you:
+
+       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 the copyright holder nor the names of
+         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 COPYRIGHT HOLDER
+       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.
+*/
+
+package jdk.dynalink;
+
+/**
+ * An enumeration of standard namespaces defined by Dynalink.
+ */
+public enum StandardNamespace implements Namespace {
+    /**
+     * Standard namespace for properties of an object.
+     */
+    PROPERTY,
+    /**
+     * Standard namespace for elements of a collection object.
+     */
+    ELEMENT,
+    /**
+     * Standard namespace for methods of an object. The method objects retrieved
+     * through a {@link StandardOperation#GET} on this namespace can be (and where
+     * object semantics allows they should be) unbound, that is: not bound to the
+     * object they were retrieved through. When they are used with
+     * {@link StandardOperation#CALL} an explicit "this" receiver argument is always
+     * passed to them. Of course bound methods can be returned if the object semantics
+     * requires them and such methods are free to ignore the receiver passed in the
+     * {@code CALL} operation or even raise an error when it is different from the one
+     * the method is bound to, or exhibit any other behavior their semantics requires
+     * in such case.
+     */
+    METHOD;
+
+    /**
+     * If the passed in operation is a {@link NamespaceOperation}, or a
+     * {@link NamedOperation} wrapping a {@link NamespaceOperation}, then it
+     * returns the first (if any) {@link StandardNamespace} in its namespace
+     * list. If the passed operation is not a namespace operation (optionally
+     * wrapped in a named operation), or if it doesn't have any standard
+     * namespaces in it, returns {@code null}.
+     * @param op the operation
+     * @return the first standard namespace in the operation's namespace list
+     */
+    public static StandardNamespace findFirst(final Operation op) {
+        for(final Namespace ns: NamespaceOperation.getNamespaces(NamedOperation.getBaseOperation(op))) {
+            if (ns instanceof StandardNamespace) {
+                return (StandardNamespace)ns;
+            }
+        }
+        return null;
+    }
+}
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java	Fri Nov 11 16:44:36 2016 +0100
@@ -84,79 +84,40 @@
 package jdk.dynalink;
 
 /**
- * Defines the standard dynamic operations. Getter and setter operations defined
- * in this enumeration can be composed into a {@link CompositeOperation}, and
- * {@link NamedOperation} can be used to bind the name parameter of operations
- * that take one, in which case it disappears from the type signature.
+ * Defines the standard dynamic operations. The operations {@link #GET} and {@link #SET} must
+ * be used as part of a {@link NamespaceOperation}. {@link NamedOperation} can then be further used on these
+ * {@link NamespaceOperation}s to bind the name parameter of {@link #GET} and {@link #SET} operations, in which case it
+ * disappears from their type signature.
+ * {@link NamedOperation} can also be used to decorate {@link #CALL} and {@link #NEW} operations with a
+ * diagnostic name, and as such it does not affect their type signature.
  */
 public enum StandardOperation implements Operation {
     /**
-     * Get the value of a property defined on an object. Call sites with this
+     * Get the value from a namespace defined on an object. Call sites with this
      * operation should have a signature of
-     * <tt>(receiver,&nbsp;propertyName)&rarr;value</tt> or
+     * <tt>(receiver,&nbsp;name)&rarr;value</tt> or
      * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}, with
      * all parameters and return type being of any type (either primitive or
-     * reference).
+     * reference). This operation must always be used as part of a {@link NamespaceOperation}.
      */
-    GET_PROPERTY,
-    /**
-     * Set the value of a property defined on an object. Call sites with this
-     * operation should have a signature of
-     * <tt>(receiver,&nbsp;propertyName,&nbsp;value)&rarr;void</tt> or
-     * <tt>(receiver,&nbsp;value)&rarr;void</tt> when used with {@link NamedOperation},
-     * with all parameters and return type being of any type (either primitive
-     * or reference).
-     */
-    SET_PROPERTY,
+    GET,
     /**
-     * Get the value of an element of a collection. Call sites with this
+     * Set the value in a namespace defined on an object. Call sites with this
      * operation should have a signature of
-     * <tt>(receiver,&nbsp;index)&rarr;value</tt> or
-     * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}, with
-     * all parameters and return type being of any type (either primitive or
-     * reference).
-     */
-    GET_ELEMENT,
-    /**
-     * Set the value of an element of a collection. Call sites with this
-     * operation should have a signature of
-     * <tt>(receiver,&nbsp;index,&nbsp;value)&rarr;void</tt> or
+     * <tt>(receiver,&nbsp;name,&nbsp;value)&rarr;void</tt> or
      * <tt>(receiver,&nbsp;value)&rarr;void</tt> when used with {@link NamedOperation},
      * with all parameters and return type being of any type (either primitive
-     * or reference).
+     * or reference). This operation must always be used as part of a {@link NamespaceOperation}.
      */
-    SET_ELEMENT,
-    /**
-     * Get the length of an array or size of a collection. Call sites with
-     * this operation should have a signature of <tt>(receiver)&rarr;value</tt>,
-     * with all parameters and return type being of any type (either primitive
-     * or reference).
-     */
-    GET_LENGTH,
+    SET,
     /**
-     * Gets an object representing a method defined on an object. Call sites
-     * with this operation should have a signature of
-     * <tt>(receiver,&nbsp;methodName)&rarr;value</tt>, or
-     * <tt>(receiver)&rarr;value</tt> when used with {@link NamedOperation}
-     * with all parameters and return type being of any type (either primitive
-     * or reference).
-     */
-    GET_METHOD,
-    /**
-     * Calls a method defined on an object. Call sites with this
-     * operation should have a signature of
-     * <tt>(receiver,&nbsp;methodName,&nbsp;arguments...)&rarr;value</tt> or
-     * <tt>(receiver,&nbsp;arguments...)&rarr;value</tt> when used with {@link NamedOperation},
-     * with all parameters and return type being of any type (either primitive
-     * or reference).
-     */
-    CALL_METHOD,
-    /**
-     * Calls a callable object. Call sites with this operation should have a
-     * signature of <tt>(receiver,&nbsp;arguments...)&rarr;value</tt>, with all
-     * parameters and return type being of any type (either primitive or
-     * reference). Typically, if the callable is a method of an object, the
-     * first argument will act as the "this" value passed to the called method.
+     * Call a callable object. Call sites with this operation should have a
+     * signature of <tt>(callable,&nbsp;receiver,&nbsp;arguments...)&rarr;value</tt>,
+     * with all parameters and return type being of any type (either primitive or
+     * reference). Typically, the callables are presumed to be methods of an object, so
+     * an explicit receiver value is always passed to the callable before the arguments.
+     * If a callable has no concept of a receiver, it is free to ignore the value of the
+     * receiver argument.
      * The <tt>CALL</tt> operation is allowed to be used with a
      * {@link NamedOperation} even though it does not take a name. Using it with
      * a named operation won't affect its signature; the name is solely meant to
@@ -164,8 +125,8 @@
      */
     CALL,
     /**
-     * Calls a constructor object. Call sites with this operation should have a
-     * signature of <tt>(receiver,&nbsp;arguments...)&rarr;value</tt>, with all
+     * Call a constructor object. Call sites with this operation should have a
+     * signature of <tt>(constructor,&nbsp;arguments...)&rarr;value</tt>, with all
      * parameters and return type being of any type (either primitive or
      * reference). The <tt>NEW</tt> operation is allowed to be used with a
      * {@link NamedOperation} even though it does not take a name. Using it with
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -99,9 +99,11 @@
 import java.util.Map;
 import java.util.Set;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Namespace;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
 import jdk.dynalink.internal.InternalTypeUtilities;
@@ -360,22 +362,6 @@
             directLinkerServices = linkerServices;
         }
 
-        // Handle NamedOperation(CALL_METHOD, name) separately
-        final Operation operation = callSiteDescriptor.getOperation();
-        if (operation instanceof NamedOperation) {
-            final NamedOperation namedOperation = (NamedOperation)operation;
-            if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) {
-                final GuardedInvocation inv =
-                        createGuardedDynamicMethodInvocation(callSiteDescriptor,
-                        directLinkerServices, namedOperation.getName().toString(), methods);
-                if (inv == null) {
-                    return createNoSuchMemberHandler(missingMemberHandlerFactory,
-                            request, directLinkerServices).getGuardedInvocation();
-                }
-                return inv;
-            }
-        }
-
         final GuardedInvocationComponent gic = getGuardedInvocationComponent(
                 new ComponentLinkRequest(request, directLinkerServices,
                         missingMemberHandlerFactory));
@@ -386,7 +372,8 @@
         final LinkRequest linkRequest;
         final LinkerServices linkerServices;
         final MissingMemberHandlerFactory missingMemberHandlerFactory;
-        final List<Operation> operations;
+        final Operation baseOperation;
+        final List<Namespace> namespaces;
         final Object name;
 
         ComponentLinkRequest(final LinkRequest linkRequest,
@@ -395,21 +382,22 @@
             this.linkRequest = linkRequest;
             this.linkerServices = linkerServices;
             this.missingMemberHandlerFactory = missingMemberHandlerFactory;
-            final Operation operation = linkRequest.getCallSiteDescriptor().getOperation();
-            this.operations = Arrays.asList(
-                    CompositeOperation.getOperations(
-                            NamedOperation.getBaseOperation(operation)));
-            this.name = NamedOperation.getName(operation);
+            final Operation namedOp = linkRequest.getCallSiteDescriptor().getOperation();
+            this.name = NamedOperation.getName(namedOp);
+            final Operation namespaceOp = NamedOperation.getBaseOperation(namedOp);
+            this.baseOperation = NamespaceOperation.getBaseOperation(namespaceOp);
+            this.namespaces = Arrays.asList(NamespaceOperation.getNamespaces(namespaceOp));
         }
 
         private ComponentLinkRequest(final LinkRequest linkRequest,
                 final LinkerServices linkerServices,
                 final MissingMemberHandlerFactory missingMemberHandlerFactory,
-                final List<Operation> operations, final Object name) {
+                final Operation baseOperation, final List<Namespace> namespaces, final Object name) {
             this.linkRequest = linkRequest;
             this.linkerServices = linkerServices;
             this.missingMemberHandlerFactory = missingMemberHandlerFactory;
-            this.operations = operations;
+            this.baseOperation = baseOperation;
+            this.namespaces = namespaces;
             this.name = name;
         }
 
@@ -417,29 +405,33 @@
             return linkRequest.getCallSiteDescriptor();
         }
 
-        ComponentLinkRequest popOperations() {
+        ComponentLinkRequest popNamespace() {
             return new ComponentLinkRequest(linkRequest, linkerServices,
-                    missingMemberHandlerFactory,
-                    operations.subList(1, operations.size()), name);
+                    missingMemberHandlerFactory, baseOperation,
+                namespaces.subList(1, namespaces.size()), name);
         }
     }
 
     protected GuardedInvocationComponent getGuardedInvocationComponent(final ComponentLinkRequest req)
     throws Exception {
-        final Operation op = req.operations.get(0);
-        if (op instanceof StandardOperation) {
-            switch((StandardOperation)op) {
-            case GET_PROPERTY: return getPropertyGetter(req.popOperations());
-            case SET_PROPERTY: return getPropertySetter(req.popOperations());
-            case GET_METHOD: return getMethodGetter(req.popOperations());
-            default:
+        if (!req.namespaces.isEmpty()) {
+            final Namespace ns = req.namespaces.get(0);
+            final Operation op = req.baseOperation;
+            if (op == StandardOperation.GET) {
+                if (ns == StandardNamespace.PROPERTY) {
+                    return getPropertyGetter(req.popNamespace());
+                } else if (ns == StandardNamespace.METHOD) {
+                    return getMethodGetter(req.popNamespace());
+                }
+            } else if (op == StandardOperation.SET && ns == StandardNamespace.PROPERTY) {
+                return getPropertySetter(req.popNamespace());
             }
         }
         return null;
     }
 
     GuardedInvocationComponent getNextComponent(final ComponentLinkRequest req) throws Exception {
-        if (req.operations.isEmpty()) {
+        if (req.namespaces.isEmpty()) {
             return createNoSuchMemberHandler(req.missingMemberHandlerFactory,
                     req.linkRequest, req.linkerServices);
         }
@@ -447,7 +439,7 @@
         if (gic != null) {
             return gic;
         }
-        return getNextComponent(req.popOperations());
+        return getNextComponent(req.popNamespace());
     }
 
     private GuardedInvocationComponent createNoSuchMemberHandler(
@@ -626,8 +618,7 @@
         if(gi != null) {
             return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
         }
-        // If we don't have a property setter with this name, always fall back to the next operation in the
-        // composite (if any)
+        // If we don't have a property setter with this name, always fall back to the next namespace (if any).
         return getNextComponent(req);
     }
 
@@ -808,8 +799,8 @@
             // We have no such method, always delegate to the next component
             return getNextComponent(req);
         }
-        // No delegation to the next component of the composite operation; if we have a method with that name,
-        // we'll always return it at this point.
+        // No delegation to the next namespace; if we have a method with that name, we'll always return it at
+        // this point.
         final MethodType type = getMethodGetterType(req);
         return getClassGuardedInvocationComponent(req.linkerServices.asType(MethodHandles.dropArguments(
                 MethodHandles.constant(Object.class, method), 0, type.parameterType(0)), type), type);
@@ -880,7 +871,7 @@
     @SuppressWarnings("unused")
     // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't
     // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for
-    // GET_METHOD linking).
+    // GET:METHOD linking).
     private Object getDynamicMethod(final Object name) {
         return getDynamicMethod(String.valueOf(name), methods);
     }
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -92,7 +92,9 @@
 import java.util.List;
 import java.util.Map;
 import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.Namespace;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -112,10 +114,11 @@
         if(clazz.isArray()) {
             // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an
             // explicit property is beneficial for them.
-            // REVISIT: is it maybe a code smell that StandardOperation.GET_LENGTH is not needed?
             setPropertyGetter("length", MethodHandles.arrayLength(clazz), ValidationType.EXACT_CLASS);
-        } else if(List.class.isAssignableFrom(clazz)) {
+        } else if(Collection.class.isAssignableFrom(clazz)) {
             setPropertyGetter("length", GET_COLLECTION_LENGTH, ValidationType.INSTANCE_OF);
+        } else if(Map.class.isAssignableFrom(clazz)) {
+            setPropertyGetter("length", GET_MAP_LENGTH, ValidationType.INSTANCE_OF);
         }
     }
 
@@ -135,14 +138,14 @@
         if(superGic != null) {
             return superGic;
         }
-        if (!req.operations.isEmpty()) {
-            final Operation op = req.operations.get(0);
-            if (op instanceof StandardOperation) {
-                switch ((StandardOperation)op) {
-                case GET_ELEMENT: return getElementGetter(req.popOperations());
-                case SET_ELEMENT: return getElementSetter(req.popOperations());
-                case GET_LENGTH:  return getLengthGetter(req.getDescriptor());
-                default:
+        if (!req.namespaces.isEmpty()) {
+            final Operation op = req.baseOperation;
+            final Namespace ns = req.namespaces.get(0);
+            if (ns == StandardNamespace.ELEMENT) {
+                if (op == StandardOperation.GET) {
+                    return getElementGetter(req.popNamespace());
+                } else if (op == StandardOperation.SET) {
+                    return getElementSetter(req.popNamespace());
                 }
             }
         }
@@ -524,38 +527,6 @@
     private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size",
             MethodType.methodType(int.class));
 
-    private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
-
-    private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) {
-        assertParameterCount(callSiteDescriptor, 1);
-        final MethodType callSiteType = callSiteDescriptor.getMethodType();
-        final Class<?> declaredType = callSiteType.parameterType(0);
-        // If declared type of receiver at the call site is already an array, collection, or map, bind without guard.
-        // Thing is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance
-        // they're dealing with an array, collection, or map, but hey...
-        if(declaredType.isArray()) {
-            return new GuardedInvocationComponent(MethodHandles.arrayLength(declaredType).asType(callSiteType));
-        } else if(Collection.class.isAssignableFrom(declaredType)) {
-            return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType));
-        } else if(Map.class.isAssignableFrom(declaredType)) {
-            return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType));
-        }
-
-        // Otherwise, create a binding based on the actual type of the argument with an appropriate guard.
-        if(clazz.isArray()) {
-            return new GuardedInvocationComponent(MethodHandles.arrayLength(clazz).asType(callSiteType),
-                    Guards.isArray(0, callSiteType), ValidationType.EXACT_CLASS);
-        } if(Collection.class.isAssignableFrom(clazz)) {
-            return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType), Guards.asType(
-                    COLLECTION_GUARD, callSiteType), Collection.class, ValidationType.INSTANCE_OF);
-        } if(Map.class.isAssignableFrom(clazz)) {
-            return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType), Guards.asType(MAP_GUARD,
-                    callSiteType), Map.class, ValidationType.INSTANCE_OF);
-        }
-        // Can't retrieve length for objects that are neither arrays, nor collections, nor maps.
-        return null;
-    }
-
     private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) {
         if(descriptor.getMethodType().parameterCount() != paramCount) {
             throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters.");
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -87,6 +87,7 @@
 import java.util.Collections;
 import java.util.Set;
 import jdk.dynalink.DynamicLinkerFactory;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
@@ -102,21 +103,18 @@
  * <ul>
  * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()},
  * and {@code isXxx()} as property setters and getters for
- * {@link StandardOperation#SET_PROPERTY} and {@link StandardOperation#GET_PROPERTY}
- * operations;</li>
- * <li>expose all public methods for invocation through
- * {@link StandardOperation#CALL_METHOD} operation;</li>
+ * {@link StandardOperation#SET} and {@link StandardOperation#GET} operations in the
+ * {@link StandardNamespace#PROPERTY} namespace;</li>
  * <li>expose all public methods for retrieval for
- * {@link StandardOperation#GET_METHOD} operation; the methods thus retrieved
- * can then be invoked using {@link StandardOperation#CALL}.</li>
+ * {@link StandardOperation#GET} operation in the {@link StandardNamespace#METHOD} namespace;
+ * the methods thus retrieved can then be invoked using {@link StandardOperation#CALL}.</li>
  * <li>expose all public fields as properties, unless there are getters or
  * setters for the properties of the same name;</li>
- * <li>expose {@link StandardOperation#GET_LENGTH},
- * {@link StandardOperation#GET_ELEMENT} and {@link StandardOperation#SET_ELEMENT}
- * on native Java arrays, as well as {@link java.util.List} and
- * {@link java.util.Map} objects; ({@link StandardOperation#GET_LENGTH} works on
- * any {@link java.util.Collection});</li>
- * <li>expose a virtual property named {@code length} on Java arrays;</li>
+ * <li> expose elements of native Java arrays, {@link java.util.List} and {@link java.util.Map} objects as
+ * {@link StandardOperation#GET} and {@link StandardOperation#SET} operations in the
+ * {@link StandardNamespace#ELEMENT} namespace;</li>
+ * <li>expose a virtual property named {@code length} on Java arrays, {@link java.util.Collection} and
+ * {@link java.util.Map} objects;</li>
  * <li>expose {@link StandardOperation#NEW} on instances of {@link StaticClass}
  * as calls to constructors, including those static class objects that represent
  * Java arrays (their constructors take a single {@code int} parameter
@@ -130,10 +128,10 @@
  * <p><strong>Overloaded method resolution</strong> is performed automatically
  * for property setters, methods, and constructors. Additionally, manual
  * overloaded method selection is supported by having a call site specify a name
- * for a method that contains an explicit signature, i.e.
- * {@code NamedMethod(GET_METHOD, "parseInt(String,int)")}. You can use
- * non-qualified class names in such signatures regardless of those classes'
- * packages, they will match any class with the same non-qualified name. You
+ * for a method that contains an explicit signature, e.g.
+ * {@code StandardOperation.GET.withNamespace(METHOD).named("parseInt(String,int)")}
+ * You can use non-qualified class names in such signatures regardless of those
+ * classes' packages, they will match any class with the same non-qualified name. You
  * only have to use a fully qualified class name in case non-qualified class
  * names would cause selection ambiguity (that is extremely rare). Overloaded
  * resolution for constructors is not automatic as there is no logical place to
@@ -235,7 +233,7 @@
 
     /**
      * Returns true if the object is a Java dynamic method (e.g., one
-     * obtained through a {@code GET_METHOD} operation on a Java object or
+     * obtained through a {@code GET:METHOD} operation on a Java object or
      * {@link StaticClass} or through
      * {@link #getConstructorMethod(Class, String)}.
      *
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -88,6 +88,7 @@
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
@@ -98,7 +99,8 @@
 /**
  * Simple linker that implements the {@link StandardOperation#CALL} operation
  * for {@link DynamicMethod} objects - the objects returned by
- * {@link StandardOperation#GET_METHOD} through {@link AbstractJavaLinker}.
+ * {@link StandardOperation#GET} on {@link StandardNamespace#METHOD} namespace through
+ * {@link AbstractJavaLinker}.
  */
 class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
     @Override
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java	Fri Nov 11 16:44:36 2016 +0100
@@ -87,7 +87,7 @@
 import jdk.dynalink.linker.GuardedInvocation;
 
 /**
- * Represents one component for a GuardedInvocation of a potentially composite operation of an
+ * Represents one component for a GuardedInvocation of a potentially multi-namespace operation of an
  * {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its
  * guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz"
  * expressions. This allows choosing the most restrictive guard as the guard for the composition of two components.
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java	Fri Nov 11 16:44:36 2016 +0100
@@ -92,7 +92,7 @@
  * methods, properties, and fields), as well as construction of instances using
  * {@link StandardOperation#NEW} operation. In Dynalink, {@link Class} objects
  * are not treated specially and act as ordinary Java objects; you can use e.g.
- * {@code NamedOperation(GET_PROPERTY, "superclass")} as a property getter to
+ * {@code GET:PROPERTY:superclass} as a property getter to
  * invoke {@code clazz.getSuperclass()}. On the other hand, you can not use
  * {@code Class} objects to access static members of a class, nor to create new
  * instances of the class using {@code NEW}. This is consistent with how
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -91,7 +91,7 @@
 import java.util.Set;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
-import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -168,17 +168,12 @@
             if (superGic != null) {
                 return superGic;
             }
-            if (!req.operations.isEmpty()) {
-                final Operation op = req.operations.get(0);
-                if (op instanceof StandardOperation) {
-                    switch ((StandardOperation)op) {
-                    case GET_ELEMENT:
-                    case SET_ELEMENT:
-                        // StaticClass doesn't behave as a collection
-                        return getNextComponent(req.popOperations());
-                    default:
-                    }
-                }
+            if (!req.namespaces.isEmpty()
+                && req.namespaces.get(0) == StandardNamespace.ELEMENT
+                && (req.baseOperation == StandardOperation.GET || req.baseOperation == StandardOperation.SET))
+            {
+                // StaticClass doesn't behave as a collection
+                return getNextComponent(req.popNamespace());
             }
             return null;
         }
--- a/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java	Fri Nov 11 16:44:36 2016 +0100
@@ -129,7 +129,7 @@
  * bytecode would look something like this:
  * <pre>
  * aload 2 // load "obj" on stack
- * invokedynamic "GET_PROPERTY:color"(Object)Object // invoke property getter on object of unknown type
+ * invokedynamic "GET:PROPERTY:color"(Object)Object // invoke property getter on object of unknown type
  * astore 3 // store the return value into local variable "color"
  * </pre>
  * In order to link the {@code invokedynamic} instruction, we need a bootstrap
@@ -175,9 +175,9 @@
  * dynamic operations. It does not prescribe how would you encode the operations
  * in your call site, though. That is why in the above example the
  * {@code parseOperation} function is left empty, and you would be expected to
- * provide the code to parse the string {@code "GET_PROPERTY:color"}
+ * provide the code to parse the string {@code "GET:PROPERTY:color"}
  * in the call site's name into a named property getter operation object as
- * {@code new NamedOperation(StandardOperation.GET_PROPERTY), "color")}.
+ * {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}.
  * </ul>
  * <p>What can you already do with the above setup? {@code DynamicLinkerFactory}
  * by default creates a {@code DynamicLinker} that can link Java objects with the
@@ -231,18 +231,20 @@
  * Dynalink defines several standard operations in its
  * {@link jdk.dynalink.StandardOperation} class. The linker for Java
  * objects can link all of these operations, and you are encouraged to at
- * minimum support and use these operations in your language too. To associate
- * a fixed name with an operation, you can use
- * {@link jdk.dynalink.NamedOperation} as in the above example where
- * {@code StandardOperation.GET_PROPERTY} was combined with the name
- * {@code "color"} in a {@code NamedOperation} to form a property getter for the
- * property named "color".
- * <h2>Composite operations</h2>
+ * minimum support and use these operations in your language too. The
+ * standard operations {@code GET} and {@code SET} need to be combined with
+ * at least one {@link jdk.dynalink.Namespace} to be useful, e.g. to express a
+ * property getter, you'd use {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY)}.
+ * Dynalink defines three standard namespaces in the {@link jdk.dynalink.StandardNamespace} class.
+ * To associate a fixed name with an operation, you can use
+ * {@link jdk.dynalink.NamedOperation} as in the previous example:
+ * {@code StandardOperation.GET.withNamespace(StandardNamespace.PROPERTY).named("color")}
+ * expresses a getter for the property named "color".
+ * <h2>Operations on multiple namespaces</h2>
  * Some languages might not have separate namespaces on objects for
  * properties, elements, and methods, and a source language construct might
- * address two or three of them. Dynalink supports specifying composite
- * operations for this purpose using the
- * {@link jdk.dynalink.CompositeOperation} class.
+ * address several of them at once. Dynalink supports specifying multiple
+ * {@link jdk.dynalink.Namespace} objects with {@link jdk.dynalink.NamespaceOperation}.
  * <h2>Language-specific linkers</h2>
  * Languages that define their own object model different than the JVM
  * class-based model and/or use their own type conversions will need to create
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java	Fri Nov 11 16:44:36 2016 +0100
@@ -343,7 +343,7 @@
                     symbol = null;
                 } else if (symbol.isParam()) {
                     // Duplicate parameter. Null return will force an error.
-                    throw new AssertionError("duplicate parameter");
+                    throwParserException(ECMAErrors.getMessage("syntax.error.duplicate.parameter", name), origin);
                 }
             } else if (isVar) {
                 if (isBlockScope) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Lower.java	Fri Nov 11 16:44:36 2016 +0100
@@ -45,6 +45,7 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ClassNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.DebuggerNode;
 import jdk.nashorn.internal.ir.EmptyNode;
@@ -60,9 +61,11 @@
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.ObjectNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.Statement;
@@ -70,6 +73,7 @@
 import jdk.nashorn.internal.ir.Symbol;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
@@ -78,6 +82,8 @@
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -98,6 +104,7 @@
 
     private final DebugLogger log;
     private final boolean es6;
+    private final Source source;
 
     // Conservative pattern to test if element names consist of characters valid for identifiers.
     // This matches any non-zero length alphanumeric string including _ and $ and not starting with a digit.
@@ -146,6 +153,7 @@
 
         this.log = initLogger(compiler.getContext());
         this.es6 = compiler.getScriptEnvironment()._es6;
+        this.source = compiler.getSource();
     }
 
     @Override
@@ -241,6 +249,10 @@
             }
         }
 
+        if (es6 && expressionStatement.destructuringDeclarationType() != null) {
+            throwNotImplementedYet("es6.destructuring", expressionStatement);
+        }
+
         return addStatement(node);
     }
 
@@ -250,6 +262,14 @@
     }
 
     @Override
+    public boolean enterForNode(final ForNode forNode) {
+        if (es6 && (forNode.getInit() instanceof ObjectNode || forNode.getInit() instanceof ArrayLiteralNode)) {
+            throwNotImplementedYet("es6.destructuring", forNode);
+        }
+        return super.enterForNode(forNode);
+    }
+
+    @Override
     public Node leaveForNode(final ForNode forNode) {
         ForNode newForNode = forNode;
 
@@ -270,6 +290,37 @@
     }
 
     @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        if (es6) {
+            if (functionNode.getKind() == FunctionNode.Kind.MODULE) {
+                throwNotImplementedYet("es6.module", functionNode);
+            }
+
+            if (functionNode.getKind() == FunctionNode.Kind.GENERATOR) {
+                throwNotImplementedYet("es6.generator", functionNode);
+            }
+            if (functionNode.usesSuper()) {
+                throwNotImplementedYet("es6.super", functionNode);
+            }
+
+            final int numParams = functionNode.getNumOfParams();
+            if (numParams > 0) {
+                final IdentNode lastParam = functionNode.getParameter(numParams - 1);
+                if (lastParam.isRestParameter()) {
+                    throwNotImplementedYet("es6.rest.param", lastParam);
+                }
+            }
+            for (final IdentNode param : functionNode.getParameters()) {
+                if (param.isDestructuredParameter()) {
+                    throwNotImplementedYet("es6.destructuring", functionNode);
+                }
+            }
+        }
+
+        return super.enterFunctionNode(functionNode);
+    }
+
+    @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         log.info("END FunctionNode: ", functionNode.getName());
         return functionNode;
@@ -578,6 +629,29 @@
     }
 
     @Override
+    public boolean enterUnaryNode(final UnaryNode unaryNode) {
+        if (es6) {
+            if (unaryNode.isTokenType(TokenType.YIELD) ||
+                unaryNode.isTokenType(TokenType.YIELD_STAR)) {
+                throwNotImplementedYet("es6.yield", unaryNode);
+            } else if (unaryNode.isTokenType(TokenType.SPREAD_ARGUMENT) ||
+                       unaryNode.isTokenType(TokenType.SPREAD_ARRAY)) {
+                throwNotImplementedYet("es6.spread", unaryNode);
+            }
+        }
+
+        return super.enterUnaryNode(unaryNode);
+    }
+
+    @Override
+    public boolean enterASSIGN(BinaryNode binaryNode) {
+        if (es6 && (binaryNode.lhs() instanceof ObjectNode || binaryNode.lhs() instanceof ArrayLiteralNode)) {
+            throwNotImplementedYet("es6.destructuring", binaryNode);
+        }
+        return super.enterASSIGN(binaryNode);
+    }
+
+    @Override
     public Node leaveVarNode(final VarNode varNode) {
         addStatement(varNode);
         if (varNode.getFlag(VarNode.IS_LAST_FUNCTION_DECLARATION)
@@ -608,6 +682,12 @@
         return addStatement(withNode);
     }
 
+    @Override
+    public boolean enterClassNode(final ClassNode classNode) {
+        throwNotImplementedYet("es6.class", classNode);
+        return super.enterClassNode(classNode);
+    }
+
     /**
      * Given a function node that is a callee in a CallNode, replace it with
      * the appropriate marker function. This is used by {@link CodeGenerator}
@@ -766,4 +846,13 @@
         }
         return false;
     }
+
+    private void throwNotImplementedYet(final String msgId, final Node node) {
+        final long token = node.getToken();
+        final int line = source.getLine(node.getStart());
+        final int column = source.getColumn(node.getStart());
+        final String message = ECMAErrors.getMessage("unimplemented." + msgId);
+        final String formatted = ErrorManager.format(message, source, line, column, token);
+        throw new RuntimeException(formatted);
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -45,7 +45,7 @@
     }
 
     @Override
-    public final boolean enterUnaryNode(final UnaryNode unaryNode) {
+    public boolean enterUnaryNode(final UnaryNode unaryNode) {
         switch (unaryNode.tokenType()) {
         case ADD:
             return enterADD(unaryNode);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java	Fri Nov 11 16:44:36 2016 +0100
@@ -48,7 +48,6 @@
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
 import jdk.nashorn.api.scripting.ClassFilter;
@@ -2449,17 +2448,17 @@
     }
 
     @Override
-    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
+    public GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final String name = NashornCallSiteDescriptor.getOperand(desc);
         final boolean isScope = NashornCallSiteDescriptor.isScope(desc);
 
         if (lexicalScope != null && isScope && !NashornCallSiteDescriptor.isApplyToCall(desc)) {
             if (lexicalScope.hasOwnProperty(name)) {
-                return lexicalScope.findGetMethod(desc, request, operation);
+                return lexicalScope.findGetMethod(desc, request);
             }
         }
 
-        final GuardedInvocation invocation =  super.findGetMethod(desc, request, operation);
+        final GuardedInvocation invocation =  super.findGetMethod(desc, request);
 
         // We want to avoid adding our generic lexical scope switchpoint to global constant invocations,
         // because those are invalidated per-key in the addBoundProperties method above.
@@ -3061,8 +3060,8 @@
         }
 
         @Override
-        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
-            return filterInvocation(super.findGetMethod(desc, request, operation));
+        protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+            return filterInvocation(super.findGetMethod(desc, request));
         }
 
         @Override
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -37,7 +37,6 @@
 import java.util.Iterator;
 import java.util.List;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.lookup.Lookup;
@@ -365,7 +364,7 @@
 
         Object obj;
         if (func instanceof ScriptFunction) {
-            obj = ScriptRuntime.apply((ScriptFunction)func, adaptee);
+            obj = ScriptRuntime.apply((ScriptFunction)func, this);
         } else {
             obj = new NativeArray(0);
         }
@@ -473,11 +472,11 @@
     }
 
     @Override
-    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
+    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final String name = NashornCallSiteDescriptor.getOperand(desc);
         if (overrides && super.hasOwnProperty(name)) {
             try {
-                final GuardedInvocation inv = super.findGetMethod(desc, request, operation);
+                final GuardedInvocation inv = super.findGetMethod(desc, request);
                 if (inv != null) {
                     return inv;
                 }
@@ -486,11 +485,9 @@
             }
         }
 
-        switch(operation) {
-        case GET_PROPERTY:
-        case GET_ELEMENT:
+        if (!NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
             return findHook(desc, __get__);
-        case GET_METHOD:
+        } else {
             final FindProperty find = adaptee.findProperty(__call__, true);
             if (find != null) {
                 final Object value = find.getObjectValue();
@@ -505,11 +502,7 @@
                 }
             }
             throw typeError("no.such.function", name, ScriptRuntime.safeToString(this));
-        default:
-            break;
         }
-
-        throw new AssertionError("should not reach here");
     }
 
     @Override
@@ -544,7 +537,7 @@
     private Object callAdaptee(final Object retValue, final String name, final Object... args) {
         final Object func = adaptee.get(name);
         if (func instanceof ScriptFunction) {
-            return ScriptRuntime.apply((ScriptFunction)func, adaptee, args);
+            return ScriptRuntime.apply((ScriptFunction)func, this, args);
         }
         return retValue;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,6 +25,10 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.dynalink.StandardNamespace.METHOD;
+import static jdk.dynalink.StandardNamespace.PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+import static jdk.dynalink.StandardOperation.SET;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
@@ -40,9 +44,7 @@
 import java.util.Set;
 import java.util.concurrent.Callable;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.NamedOperation;
 import jdk.dynalink.Operation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.BeansLinker;
 import jdk.dynalink.beans.StaticClass;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -97,6 +99,10 @@
                 });
     }
 
+    private static final Operation GET_METHOD   = GET.withNamespace(METHOD);
+    private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
+    private static final Operation SET_PROPERTY = SET.withNamespace(PROPERTY);
+
     @SuppressWarnings("unused")
     private static ScriptObject get__proto__(final Object self) {
         // See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__
@@ -782,7 +788,7 @@
         for(final String methodName: methodNames) {
             final MethodHandle method;
             try {
-                method = getBeanOperation(linker, StandardOperation.GET_METHOD, methodName, getterType, source);
+                method = getBeanOperation(linker, GET_METHOD, methodName, getterType, source);
             } catch(final IllegalAccessError e) {
                 // Presumably, this was a caller sensitive method. Ignore it and carry on.
                 continue;
@@ -794,7 +800,7 @@
             MethodHandle getter;
             if(readablePropertyNames.contains(propertyName)) {
                 try {
-                    getter = getBeanOperation(linker, StandardOperation.GET_PROPERTY, propertyName, getterType, source);
+                    getter = getBeanOperation(linker, GET_PROPERTY, propertyName, getterType, source);
                 } catch(final IllegalAccessError e) {
                     // Presumably, this was a caller sensitive method. Ignore it and carry on.
                     getter = Lookup.EMPTY_GETTER;
@@ -806,7 +812,7 @@
             MethodHandle setter;
             if(isWritable) {
                 try {
-                    setter = getBeanOperation(linker, StandardOperation.SET_PROPERTY, propertyName, setterType, source);
+                    setter = getBeanOperation(linker, SET_PROPERTY, propertyName, setterType, source);
                 } catch(final IllegalAccessError e) {
                     // Presumably, this was a caller sensitive method. Ignore it and carry on.
                     setter = Lookup.EMPTY_SETTER;
@@ -836,11 +842,11 @@
         }
     }
 
-    private static MethodHandle getBeanOperation(final GuardingDynamicLinker linker, final StandardOperation operation,
+    private static MethodHandle getBeanOperation(final GuardingDynamicLinker linker, final Operation operation,
             final String name, final MethodType methodType, final Object source) {
         final GuardedInvocation inv;
         try {
-            inv = NashornBeansLinker.getGuardedInvocation(linker, createLinkRequest(new NamedOperation(operation, name), methodType, source), Bootstrap.getLinkerServices());
+            inv = NashornBeansLinker.getGuardedInvocation(linker, createLinkRequest(operation.named(name), methodType, source), Bootstrap.getLinkerServices());
             assert passesGuard(source, inv.getGuard());
         } catch(RuntimeException|Error e) {
             throw e;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java	Fri Nov 11 16:44:36 2016 +0100
@@ -42,7 +42,6 @@
 import java.util.Locale;
 import java.util.Set;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.lookup.MethodHandleFactory.LookupException;
@@ -127,15 +126,15 @@
 
     // This is to support length as method call as well.
     @Override
-    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
+    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final String name = NashornCallSiteDescriptor.getOperand(desc);
 
         // if str.length(), then let the bean linker handle it
-        if ("length".equals(name) && operation == StandardOperation.GET_METHOD) {
+        if ("length".equals(name) && NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
             return null;
         }
 
-        return super.findGetMethod(desc, request, operation);
+        return super.findGetMethod(desc, request);
     }
 
     // This is to provide array-like access to string characters without creating a NativeString wrapper.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Fri Nov 11 16:44:36 2016 +0100
@@ -1962,6 +1962,18 @@
             switch (type) {
             case SEMICOLON:
                 // for (init; test; modify)
+                if (varDeclList != null) {
+                    assert init == null;
+                    init = varDeclList.init;
+                    // late check for missing assignment, now we know it's a for (init; test; modify) loop
+                    if (varDeclList.missingAssignment != null) {
+                        if (varDeclList.missingAssignment instanceof IdentNode) {
+                            throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)varDeclList.missingAssignment).getName()));
+                        } else {
+                            throw error(AbstractParser.message("missing.destructuring.assignment"), varDeclList.missingAssignment.getToken());
+                        }
+                    }
+                }
 
                 // for each (init; test; modify) is invalid
                 if ((flags & ForNode.IS_FOR_EACH) != 0) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Fri Nov 11 16:44:36 2016 +0100
@@ -67,7 +67,6 @@
 import java.util.concurrent.atomic.LongAdder;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
@@ -1858,23 +1857,16 @@
      * @return GuardedInvocation for the callsite
      */
     public GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request) {
-        // NOTE: we support GET_ELEMENT and SET_ELEMENT as JavaScript doesn't distinguish items from properties. Nashorn itself
-        // emits "GET_PROPERTY|GET_ELEMENT|GET_METHOD:identifier" for "<expr>.<identifier>" and "GET_ELEMENT|GET_PROPERTY|GET_METHOD" for "<expr>[<expr>]", but we are
+        // NOTE: we support GET:ELEMENT and SET:ELEMENT as JavaScript doesn't distinguish items from properties. Nashorn itself
+        // emits "GET:PROPERTY|ELEMENT|METHOD:identifier" for "<expr>.<identifier>" and "GET:ELEMENT|PROPERTY|METHOD" for "<expr>[<expr>]", but we are
         // more flexible here and dispatch not on operation name (getProp vs. getElem), but rather on whether the
         // operation has an associated name or not.
-        final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
-        if (op == null) {
-            return null;
-        }
-        switch (op) {
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-        case GET_METHOD:
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
+        case GET:
             return desc.getOperation() instanceof NamedOperation
-                    ? findGetMethod(desc, request, op)
+                    ? findGetMethod(desc, request)
                     : findGetIndexMethod(desc, request);
-        case SET_PROPERTY:
-        case SET_ELEMENT:
+        case SET:
             return desc.getOperation() instanceof NamedOperation
                     ? findSetMethod(desc, request)
                     : findSetIndexMethod(desc, request);
@@ -1883,8 +1875,8 @@
         case NEW:
             return findNewMethod(desc, request);
         default:
+            return null;
         }
-        return null;
     }
 
     /**
@@ -1952,11 +1944,10 @@
      *
      * @param desc     the call site descriptor
      * @param request  the link request
-     * @param operation operation for get: getProp, getMethod, getElem etc
      *
      * @return GuardedInvocation to be invoked at call site.
      */
-    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final StandardOperation operation) {
+    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
 
         String name = NashornCallSiteDescriptor.getOperand(desc);
@@ -1967,21 +1958,17 @@
         }
 
         if (request.isCallSiteUnstable() || hasWithScope()) {
-            return findMegaMorphicGetMethod(desc, name, operation == StandardOperation.GET_METHOD);
+            return findMegaMorphicGetMethod(desc, name, NashornCallSiteDescriptor.isMethodFirstOperation(desc));
         }
 
         final FindProperty find = findProperty(name, true, NashornCallSiteDescriptor.isScope(desc), this);
         MethodHandle mh;
 
         if (find == null) {
-            switch (operation) {
-            case GET_ELEMENT: // getElem only gets here if element name is constant, so treat it like a property access
-            case GET_PROPERTY:
+            if (!NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
                 return noSuchProperty(desc, request);
-            case GET_METHOD:
+            } else {
                 return noSuchMethod(desc, request);
-            default:
-                throw new AssertionError(operation); // never invoked with any other operation
             }
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java	Fri Nov 11 16:44:36 2016 +0100
@@ -32,7 +32,6 @@
 import java.lang.invoke.MethodHandles;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.support.Guards;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
@@ -93,29 +92,22 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     public static GuardedInvocation lookup(final CallSiteDescriptor desc) {
-        final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
-        if (op == null) {
-            return null;
-        }
-        switch (op) {
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
         case CALL:
         case NEW:
             final String name = NashornCallSiteDescriptor.getOperand(desc);
             final String msg = name != null? "not.a.function" : "cant.call.undefined";
             throw typeError(msg, name);
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-        case GET_METHOD:
-            // NOTE: we support GET_ELEMENT and SET_ELEMENT as JavaScript doesn't distinguish items from properties. Nashorn itself
-            // emits "GET_PROPERTY|GET_ELEMENT|GET_METHOD:identifier" for "<expr>.<identifier>" and "GET_ELEMENT|GET_PROPERTY|GET_METHOD" for "<expr>[<expr>]", but we are
+        case GET:
+            // NOTE: we support GET:ELEMENT and SET:ELEMENT as JavaScript doesn't distinguish items from properties. Nashorn itself
+            // emits "GET:PROPERTY|ELEMENT|METHOD:identifier" for "<expr>.<identifier>" and "GET:ELEMENT|PROPERTY|METHOD" for "<expr>[<expr>]", but we are
             // more flexible here and dispatch not on operation name (getProp vs. getElem), but rather on whether the
             // operation has an associated name or not.
             if (!(desc.getOperation() instanceof NamedOperation)) {
                 return findGetIndexMethod(desc);
             }
             return findGetMethod(desc);
-        case SET_PROPERTY:
-        case SET_ELEMENT:
+        case SET:
             if (!(desc.getOperation() instanceof NamedOperation)) {
                 return findSetIndexMethod(desc);
             }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java	Fri Nov 11 16:44:36 2016 +0100
@@ -97,9 +97,6 @@
             return super.lookup(desc, request);
         }
 
-        // With scopes can never be observed outside of Nashorn code, so all call sites that can address it will of
-        // necessity have a Nashorn descriptor - it is safe to cast.
-        final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
         GuardedInvocation link = null;
         final Operation op = desc.getOperation();
 
@@ -111,7 +108,7 @@
         if (find != null) {
             link = expression.lookup(desc, request);
             if (link != null) {
-                return fixExpressionCallSite(ndesc, link);
+                return fixExpressionCallSite(desc, link);
             }
         }
 
@@ -126,39 +123,30 @@
         // __noSuchProperty__ and __noSuchMethod__ in expression
         final String fallBack;
 
-        final StandardOperation firstOp = ndesc.getFirstOperation();
-        switch (firstOp) {
-        case GET_METHOD:
-            fallBack = NO_SUCH_METHOD_NAME;
-            break;
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-            fallBack = NO_SUCH_PROPERTY_NAME;
-            break;
-        default:
+        final Operation firstOp = NashornCallSiteDescriptor.getBaseOperation(desc);
+        if (firstOp == StandardOperation.GET) {
+            if (NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
+                fallBack = NO_SUCH_METHOD_NAME;
+            } else {
+                fallBack = NO_SUCH_PROPERTY_NAME;
+            }
+        } else {
             fallBack = null;
-            break;
         }
 
         if (fallBack != null) {
             find = expression.findProperty(fallBack, true);
             if (find != null) {
-                switch (firstOp) {
-                case GET_METHOD:
+                if (NO_SUCH_METHOD_NAME.equals(fallBack)) {
                     link = expression.noSuchMethod(desc, request);
-                    break;
-                case GET_PROPERTY:
-                case GET_ELEMENT:
+                } else if (NO_SUCH_PROPERTY_NAME.equals(fallBack)) {
                     link = expression.noSuchProperty(desc, request);
-                    break;
-                default:
-                    break;
                 }
             }
         }
 
         if (link != null) {
-            return fixExpressionCallSite(ndesc, link);
+            return fixExpressionCallSite(desc, link);
         }
 
         // still not found, may be scope can handle with it's own
@@ -245,10 +233,10 @@
         return link.asType(newInvType);
     }
 
-    private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
+    private static GuardedInvocation fixExpressionCallSite(final CallSiteDescriptor desc, final GuardedInvocation link) {
         // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
         // expression.
-        if (desc.getFirstOperation() != StandardOperation.GET_METHOD) {
+        if (NashornCallSiteDescriptor.getBaseOperation(desc) != StandardOperation.GET || !NashornCallSiteDescriptor.isMethodFirstOperation(desc)) {
             return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
         }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,7 +35,6 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
 import jdk.dynalink.linker.LinkerServices;
@@ -91,24 +90,17 @@
             inv = null;
         }
 
-        final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
-        if (op == null) {
-            return inv;
-        }
         final String name = NashornCallSiteDescriptor.getOperand(desc);
-        switch (op) {
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-        case GET_METHOD:
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
+        case GET:
             return name != null ? findGetMethod(name, inv) : findGetIndexMethod(inv);
-        case SET_PROPERTY:
-        case SET_ELEMENT:
+        case SET:
             return name != null ? findSetMethod(name, inv) : findSetIndexMethod();
         case CALL:
             return findCallMethod(desc);
         default:
+            return null;
         }
-        return null;
     }
 
     private static GuardedInvocation findGetMethod(final String name, final GuardedInvocation inv) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -33,6 +33,7 @@
 import java.util.Map;
 import javax.script.Bindings;
 import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.Operation;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
@@ -92,29 +93,31 @@
     }
 
     private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception {
-        final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
-        if (op == null) {
-            return null;
-        }
-        final String name = NashornCallSiteDescriptor.getOperand(desc);
-        switch (op) {
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-        case GET_METHOD:
-            if (name != null) {
-                return findGetMethod(name);
+        final Operation op = NashornCallSiteDescriptor.getBaseOperation(desc);
+        if (op instanceof StandardOperation) {
+            final String name = NashornCallSiteDescriptor.getOperand(desc);
+            switch ((StandardOperation)op) {
+            case GET:
+                if (NashornCallSiteDescriptor.hasStandardNamespace(desc)) {
+                    if (name != null) {
+                        return findGetMethod(name);
+                    }
+                    // For indexed get, we want get GuardedInvocation beans linker and pass it.
+                    // JSObjectLinker.get uses this fallback getter for explicit signature method access.
+                    return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
+                }
+                break;
+            case SET:
+                if (NashornCallSiteDescriptor.hasStandardNamespace(desc)) {
+                    return name != null ? findSetMethod(name) : findSetIndexMethod();
+                }
+                break;
+            case CALL:
+                return findCallMethod(desc);
+            case NEW:
+                return findNewMethod(desc);
+            default:
             }
-            // For indexed get, we want get GuardedInvocation beans linker and pass it.
-            // JSObjectLinker.get uses this fallback getter for explicit signature method access.
-            return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
-        case SET_PROPERTY:
-        case SET_ELEMENT:
-            return name != null ? findSetMethod(name) : findSetIndexMethod();
-        case CALL:
-            return findCallMethod(desc);
-        case NEW:
-            return findNewMethod(desc);
-        default:
         }
         return null;
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,15 +25,15 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.dynalink.StandardNamespace.METHOD;
+import static jdk.dynalink.StandardOperation.GET;
 import static jdk.nashorn.internal.runtime.linker.JavaAdapterBytecodeGenerator.SUPER_PREFIX;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.NamedOperation;
 import jdk.dynalink.Operation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.BeansLinker;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
@@ -61,6 +61,8 @@
         IS_ADAPTER_OF_CLASS = lookup.findOwnStatic("isAdapterOfClass", boolean.class, Class.class, Object.class);
     }
 
+    private static final Operation GET_METHOD = GET.withNamespace(METHOD);
+
     private final BeansLinker beansLinker;
 
     JavaSuperAdapterLinker(final BeansLinker beansLinker) {
@@ -82,8 +84,8 @@
 
         final CallSiteDescriptor descriptor = linkRequest.getCallSiteDescriptor();
 
-        if(!NashornCallSiteDescriptor.contains(descriptor, StandardOperation.GET_METHOD)) {
-            // We only handle GET_METHOD
+        if(!NashornCallSiteDescriptor.contains(descriptor, GET, METHOD)) {
+            // We only handle GET:METHOD
             return null;
         }
 
@@ -97,8 +99,7 @@
         final MethodType type = descriptor.getMethodType();
         final Class<?> adapterClass = adapter.getClass();
         final String name = NashornCallSiteDescriptor.getOperand(descriptor);
-        final Operation newOp = name == null ? StandardOperation.GET_METHOD :
-            new NamedOperation(StandardOperation.GET_METHOD, SUPER_PREFIX + name);
+        final Operation newOp = name == null ? GET_METHOD : GET_METHOD.named(SUPER_PREFIX + name);
 
         final CallSiteDescriptor newDescriptor = new CallSiteDescriptor(
                 NashornCallSiteDescriptor.getLookupInternal(descriptor), newOp,
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -35,7 +35,9 @@
 import java.util.function.Supplier;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
 import jdk.dynalink.SecureLookupSupplier;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.BeansLinker;
 import jdk.dynalink.linker.ConversionComparator.Comparison;
@@ -46,6 +48,7 @@
 import jdk.dynalink.linker.MethodHandleTransformer;
 import jdk.dynalink.linker.support.DefaultInternalObjectFilter;
 import jdk.dynalink.linker.support.Lookup;
+import jdk.dynalink.linker.support.SimpleLinkRequest;
 import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
@@ -68,6 +71,9 @@
     // Object type arguments of Java method calls, field set and array set.
     private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
 
+    private static final Operation GET_METHOD = StandardOperation.GET.withNamespace(StandardNamespace.METHOD);
+    private static final MethodType GET_METHOD_TYPE = MethodType.methodType(Object.class, Object.class);
+
     private static final MethodHandle EXPORT_ARGUMENT;
     private static final MethodHandle IMPORT_RESULT;
     private static final MethodHandle FILTER_CONSSTRING;
@@ -114,20 +120,38 @@
             // those are script functions.
             final String name = getFunctionalInterfaceMethodName(self.getClass());
             if (name != null) {
-                final MethodType callType = desc.getMethodType();
-                // drop callee (Undefined ScriptFunction) and change the request to be CALL_METHOD:<name>
-                final CallSiteDescriptor newDesc = new CallSiteDescriptor(
+                // Obtain the method
+                final CallSiteDescriptor getMethodDesc = new CallSiteDescriptor(
                         NashornCallSiteDescriptor.getLookupInternal(desc),
-                        new NamedOperation(StandardOperation.CALL_METHOD, name),
-                        desc.getMethodType().dropParameterTypes(1, 2));
-                final GuardedInvocation gi = getGuardedInvocation(beansLinker,
-                        linkRequest.replaceArguments(newDesc, linkRequest.getArguments()),
+                        GET_METHOD.named(name), GET_METHOD_TYPE);
+                final GuardedInvocation getMethodInv = linkerServices.getGuardedInvocation(
+                        new SimpleLinkRequest(getMethodDesc, false, self));
+                final Object method;
+                try {
+                    method = getMethodInv.getInvocation().invokeExact(self);
+                } catch (final Exception|Error e) {
+                    throw e;
+                } catch (final Throwable t) {
+                    throw new RuntimeException(t);
+                }
+
+                final Object[] args = linkRequest.getArguments();
+                args[1] = args[0]; // callee (the functional object) becomes this
+                args[0] = method; // the method becomes the callee
+
+                final MethodType callType = desc.getMethodType();
+
+                final CallSiteDescriptor newDesc = desc.changeMethodType(
+                        desc.getMethodType().changeParameterType(0, Object.class).changeParameterType(1, callType.parameterType(0)));
+                final GuardedInvocation gi = getGuardedInvocation(beansLinker, linkRequest.replaceArguments(newDesc, args),
                         new NashornBeansLinkerServices(linkerServices));
 
-                // drop 'thiz' passed from the script.
-                return gi.replaceMethods(
-                    MH.dropArguments(linkerServices.filterInternalObjects(gi.getInvocation()), 1, callType.parameterType(1)),
-                    gi.getGuard());
+                // Bind to the method, drop the original "this" and use original "callee" as this:
+                final MethodHandle inv = linkerServices.filterInternalObjects(gi
+                        .getInvocation()  // (method, this, args...)
+                        .bindTo(method)); // (this, args...)
+                final MethodHandle calleeToThis = MH.dropArguments(inv, 1, callType.parameterType(1)); // (callee->this, <drop>, args...)
+                return gi.replaceMethods(calleeToThis, gi.getGuard());
             }
         }
         return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -38,7 +38,6 @@
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.NamedOperation;
 import jdk.dynalink.Operation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.BeansLinker;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
@@ -98,7 +97,7 @@
     private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception {
         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
         final Object self = linkRequest.getReceiver();
-        switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) {
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
         case NEW:
             if(BeansLinker.isDynamicConstructor(self)) {
                 throw typeError("no.constructor.matches.args", ScriptRuntime.safeToString(self));
@@ -124,35 +123,26 @@
 
     static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
-        final StandardOperation op = NashornCallSiteDescriptor.getFirstStandardOperation(desc);
-        if (op != null) {
-            final String operand = NashornCallSiteDescriptor.getOperand(desc);
-            switch (op) {
-            case GET_METHOD:
-            case GET_PROPERTY:
-            case GET_ELEMENT: {
-                if (NashornCallSiteDescriptor.isOptimistic(desc)) {
-                    return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc);
-                }
-                if (NashornCallSiteDescriptor.getOperand(desc) != null) {
-                    return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc);
-                }
-                return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc);
+        final String operand = NashornCallSiteDescriptor.getOperand(desc);
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
+        case GET:
+            if (NashornCallSiteDescriptor.isOptimistic(desc)) {
+                return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc);
+            } else if (operand != null) {
+                return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc);
             }
-            case SET_PROPERTY:
-            case SET_ELEMENT:
-                final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
-                if (strict) {
-                    return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc);
-                }
-                if (NashornCallSiteDescriptor.getOperand(desc) != null) {
-                    return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc);
-                }
-                return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc);
-            default:
+            return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc);
+        case SET:
+            final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
+            if (strict) {
+                return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc);
+            } else if (operand != null) {
+                return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc);
             }
+            return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc);
+        default:
+            throw new AssertionError("unknown call type " + desc);
         }
-        throw new AssertionError("unknown call type " + desc);
     }
 
     private static MethodHandle bindOperand(final MethodHandle handle, final String operand) {
@@ -217,17 +207,13 @@
 
     private static GuardedInvocation linkNull(final LinkRequest linkRequest) {
         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
-        switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) {
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
         case NEW:
         case CALL:
             throw typeError("not.a.function", "null");
-        case GET_METHOD:
-            throw typeError("no.such.function", getArgument(linkRequest), "null");
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-            throw typeError("cant.get.property", getArgument(linkRequest), "null");
-        case SET_PROPERTY:
-        case SET_ELEMENT:
+        case GET:
+            throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null");
+        case SET:
             throw typeError("cant.set.property", getArgument(linkRequest), "null");
         default:
             throw new AssertionError("unknown call type " + desc);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,6 +25,12 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.dynalink.StandardNamespace.ELEMENT;
+import static jdk.dynalink.StandardNamespace.METHOD;
+import static jdk.dynalink.StandardNamespace.PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+import static jdk.dynalink.StandardOperation.SET;
+
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
@@ -40,10 +46,11 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.stream.Stream;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.Operation;
 import jdk.dynalink.SecureLookupSupplier;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.nashorn.internal.ir.debug.NashornTextifier;
 import jdk.nashorn.internal.runtime.AccessControlContextFactory;
@@ -78,12 +85,12 @@
 
     // Correspond to the operation indices above.
     private static final Operation[] OPERATIONS = new Operation[] {
-        new CompositeOperation(StandardOperation.GET_PROPERTY, StandardOperation.GET_ELEMENT, StandardOperation.GET_METHOD),
-        new CompositeOperation(StandardOperation.GET_ELEMENT, StandardOperation.GET_PROPERTY, StandardOperation.GET_METHOD),
-        new CompositeOperation(StandardOperation.GET_METHOD, StandardOperation.GET_PROPERTY, StandardOperation.GET_ELEMENT),
-        new CompositeOperation(StandardOperation.GET_METHOD, StandardOperation.GET_ELEMENT, StandardOperation.GET_PROPERTY),
-        new CompositeOperation(StandardOperation.SET_PROPERTY, StandardOperation.SET_ELEMENT),
-        new CompositeOperation(StandardOperation.SET_ELEMENT, StandardOperation.SET_PROPERTY),
+        GET.withNamespaces(PROPERTY, ELEMENT, METHOD),
+        GET.withNamespaces(ELEMENT, PROPERTY, METHOD),
+        GET.withNamespaces(METHOD, PROPERTY, ELEMENT),
+        GET.withNamespaces(METHOD, ELEMENT, PROPERTY),
+        SET.withNamespaces(PROPERTY, ELEMENT),
+        SET.withNamespaces(ELEMENT, PROPERTY),
         StandardOperation.CALL,
         StandardOperation.NEW
     };
@@ -248,7 +255,7 @@
                 return existing;
             }
         }
-        final NamedOperation newOp = new NamedOperation(baseOp, name);
+        final NamedOperation newOp = baseOp.named(name);
         namedOps.put(name, new WeakReference<>(newOp));
         return newOp;
     }
@@ -288,16 +295,6 @@
     }
 
     /**
-     * Returns the named operand in this descriptor's operation. Equivalent to
-     * {@code ((NamedOperation)getOperation()).getName().toString()} for call
-     * sites with a named operand. For call sites without named operands returns null.
-     * @return the named operand in this descriptor's operation.
-     */
-    public String getOperand() {
-        return getOperand(this);
-    }
-
-    /**
      * Returns the named operand in the passed descriptor's operation.
      * Equivalent to
      * {@code ((NamedOperation)desc.getOperation()).getName().toString()} for
@@ -311,70 +308,63 @@
         return operation instanceof NamedOperation ? ((NamedOperation)operation).getName().toString() : null;
     }
 
+    private static StandardNamespace findFirstStandardNamespace(final CallSiteDescriptor desc) {
+        return StandardNamespace.findFirst(desc.getOperation());
+    }
+
     /**
-     * Returns the first operation in this call site descriptor's potentially
-     * composite operation. E.g. if this call site descriptor has a composite
-     * operation {@code GET_PROPERTY|GET_METHOD|GET_ELEM}, it will return
-     * {@code GET_PROPERTY}. Nashorn - being a ECMAScript engine - does not
-     * distinguish between property, element, and method namespace; ECMAScript
-     * objects just have one single property namespace for all these, therefore
-     * it is largely irrelevant what the composite operation is structured like;
-     * if the first operation can't be satisfied, neither can the others. The
-     * first operation is however sometimes used to slightly alter the
-     * semantics; for example, a distinction between {@code GET_PROPERTY} and
-     * {@code GET_METHOD} being the first operation can translate into whether
-     * {@code "__noSuchProperty__"} or {@code "__noSuchMethod__"} will be
-     * executed in case the property is not found. Note that if a call site
-     * descriptor comes from outside of Nashorn, its class will be different,
-     * and there is no guarantee about the way it composes its operations. For
-     * that reason, for potentially foreign call site descriptors you should use
-     * {@link #getFirstStandardOperation(CallSiteDescriptor)} instead.
-     * @return the first operation in this call site descriptor. Note this will
-     * always be a {@code StandardOperation} as Nashorn internally only uses
-     * standard operations.
+     * Returns true if the operation of the call descriptor is operating on the method namespace first.
+     * @param desc the call descriptor in question.
+     * @return true if the operation of the call descriptor is operating on the method namespace first.
      */
-    public StandardOperation getFirstOperation() {
-        final Operation base = NamedOperation.getBaseOperation(getOperation());
-        if (base instanceof CompositeOperation) {
-            return (StandardOperation)((CompositeOperation)base).getOperation(0);
-        }
-        return (StandardOperation)base;
+    public static boolean isMethodFirstOperation(final CallSiteDescriptor desc) {
+        return findFirstStandardNamespace(desc) == StandardNamespace.METHOD;
+    }
+
+    /**
+     * Returns true if there's a namespace operation in the call descriptor and it is operating on at least
+     * one {@link StandardNamespace}. This method is only needed for exported linkers, since internal linkers
+     * always operate on Nashorn-generated call sites, and they always operate on standard namespaces only.
+     * @param desc the call descriptor in question.
+     * @return true if the operation of the call descriptor is operating on at least one standard namespace.
+     */
+    public static boolean hasStandardNamespace(final CallSiteDescriptor desc) {
+        return findFirstStandardNamespace(desc) != null;
     }
 
     /**
-     * Returns the first standard operation in the (potentially composite)
-     * operation of the passed call site descriptor.
+     * Returns the base operation in this call site descriptor after unwrapping it from both a named operation
+     * and a namespace operation.
      * @param desc the call site descriptor.
-     * @return Returns the first standard operation in the (potentially
-     * composite) operation of the passed call site descriptor. Can return null
-     * if the call site contains no standard operations.
+     * @return the base operation in this call site descriptor.
      */
-    public static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) {
-        final Operation base = NamedOperation.getBaseOperation(desc.getOperation());
-        if (base instanceof StandardOperation) {
-            return (StandardOperation)base;
-        } else if (base instanceof CompositeOperation) {
-            final CompositeOperation cop = (CompositeOperation)base;
-            for(int i = 0; i < cop.getOperationCount(); ++i) {
-                final Operation op = cop.getOperation(i);
-                if (op instanceof StandardOperation) {
-                    return (StandardOperation)op;
-                }
-            }
-        }
-        return null;
+    public static Operation getBaseOperation(final CallSiteDescriptor desc) {
+        return NamespaceOperation.getBaseOperation(NamedOperation.getBaseOperation(desc.getOperation()));
     }
 
     /**
-     * Returns true if the passed call site descriptor's operation contains (or
-     * is) the specified standard operation.
+     * Returns the standard operation that is the base operation in this call site descriptor.
+     * @param desc the call site descriptor.
+     * @return the standard operation that is the base operation in this call site descriptor.
+     * @throws ClassCastException if the base operation is not a standard operation. This method is only
+     * safe to use when the base operation is known to be a standard operation (e.g. all Nashorn call sites
+     * are such, so it's safe to use from internal linkers).
+     */
+    public static StandardOperation getStandardOperation(final CallSiteDescriptor desc) {
+        return (StandardOperation)getBaseOperation(desc);
+    }
+
+    /**
+     * Returns true if the passed call site descriptor contains the specified standard operation on the
+     * specified standard namespace.
      * @param desc the call site descriptor.
      * @param operation the operation whose presence is tested.
-     * @return Returns true if the call site descriptor's operation contains (or
-     * is) the specified standard operation.
+     * @param namespace the namespace on which the operation operates.
+     * @return Returns true if the call site descriptor contains the specified standard operation on the
+     * specified standard namespace.
      */
-    public static boolean contains(final CallSiteDescriptor desc, final StandardOperation operation) {
-        return CompositeOperation.contains(NamedOperation.getBaseOperation(desc.getOperation()), operation);
+    public static boolean contains(final CallSiteDescriptor desc, final StandardOperation operation, final StandardNamespace namespace) {
+        return NamespaceOperation.contains(NamedOperation.getBaseOperation(desc.getOperation()), operation, namespace);
     }
 
     /**
@@ -383,8 +373,8 @@
      * @param obj object on which CALL or NEW is used
      * @return error message
      */
-    public String getFunctionErrorMessage(final Object obj) {
-        final String funcDesc = getOperand();
+    private String getFunctionErrorMessage(final Object obj) {
+        final String funcDesc = getOperand(this);
         return funcDesc != null? funcDesc : ScriptRuntime.safeToString(obj);
     }
 
@@ -552,4 +542,9 @@
     public CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) {
         return get(getLookupPrivileged(), getOperation(), newMethodType, flags);
     }
+
+    @Override
+    protected CallSiteDescriptor changeOperationInternal(final Operation newOperation) {
+        return get(getLookupPrivileged(), newOperation, getMethodType(), flags);
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java	Fri Nov 11 16:44:36 2016 +0100
@@ -99,10 +99,8 @@
         final String name = NashornCallSiteDescriptor.getOperand(desc);
         final FindProperty find = name != null ? wrappedReceiver.findProperty(name, true) : null;
 
-        switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) {
-        case GET_PROPERTY:
-        case GET_ELEMENT:
-        case GET_METHOD:
+        switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
+        case GET:
             //checks whether the property name is hard-coded in the call-site (i.e. a getProp vs a getElem, or setProp vs setElem)
             //if it is we can make assumptions on the property: that if it is not defined on primitive wrapper itself it never will be.
             //so in that case we can skip creation of primitive wrapper and start our search with the prototype.
@@ -133,8 +131,7 @@
                 }
             }
             break;
-        case SET_PROPERTY:
-        case SET_ELEMENT:
+        case SET:
             return getPrimitiveSetter(name, guard, wrapFilter, NashornCallSiteDescriptor.isStrict(desc));
         default:
             break;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java	Fri Nov 11 16:44:36 2016 +0100
@@ -30,6 +30,7 @@
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.linker.LinkRequest;
@@ -129,9 +130,9 @@
             // allow 'static' access on Class objects representing public classes of non-restricted packages
             if ((self instanceof Class) && Modifier.isPublic(((Class<?>)self).getModifiers())) {
                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
-                if ("static".equals(NashornCallSiteDescriptor.getOperand(desc)) && NashornCallSiteDescriptor.contains(desc, StandardOperation.GET_PROPERTY)) {
+                if ("static".equals(NashornCallSiteDescriptor.getOperand(desc)) && NashornCallSiteDescriptor.contains(desc, StandardOperation.GET, StandardNamespace.PROPERTY)) {
                     if (Context.isAccessibleClass((Class<?>)self) && !isReflectionClass((Class<?>)self)) {
-                        // If "GET_PROPERTY:static" passes access checks, allow access.
+                        // If "GET:PROPERTY:static" passes access checks, allow access.
                         return;
                     }
                 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Fri Nov 11 16:44:36 2016 +0100
@@ -214,6 +214,7 @@
 syntax.error.strict.cant.delete=cannot delete "{0}" in strict mode
 syntax.error.redeclare.variable=Variable "{0}" has already been declared
 syntax.error.unprotected.switch.declaration=Unsupported {0} declaration in unprotected switch statement
+syntax.error.duplicate.parameter=Duplicate parameter name "{0}"
 
 io.error.cant.write=cannot write "{0}"
 
@@ -222,3 +223,12 @@
 
 uri.error.bad.uri=Bad URI "{0}" near offset {1}
 list.adapter.null.global=Attempted to create the adapter from outside a JavaScript execution context.
+
+unimplemented.es6.module=ES6 modules are not yet implemented
+unimplemented.es6.rest.param=ES6 function rest parameter declaration is not yet implemented
+unimplemented.es6.yield=ES6 yield and yield* are not yet implemented
+unimplemented.es6.spread=ES6 spread operator is not yet implemented
+unimplemented.es6.class=ES6 class declarations and expressions are not yet implemented
+unimplemented.es6.destructuring=ES6 destructuring is not yet implemented
+unimplemented.es6.generator=ES6 generator is not yet implemented
+unimplemented.es6.super=ES6 super keyword is not yet implemented
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/class.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * Class declaration is not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+try {
+   eval("class Foo {}");
+} catch (e) {
+   print(String(e).replace(/\\/g, "/"))
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/class.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,3 @@
+java.lang.RuntimeException: test/script/basic/es6/class.js#33:3<eval>:1:0 ES6 class declarations and expressions are not yet implemented
+class Foo {}
+^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/destructuring.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * Destructuring is not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+
+function check(code) {
+   try {
+      eval(code);
+   } catch (e) {
+      print(String(e).replace(/\\/g, "/"))
+   }
+}
+
+check("var { x: y } = obj;");
+check("let { x: y } = obj;");
+check("const { x: y } = obj;");
+check("({ x: y }) = obj;");
+check("for (var { x: y } of obj) ;");
+check("for (let { x: y } of obj) ;");
+check("var { x, y } = obj;");
+check("let { x, y } = obj;");
+check("const { x, y } = obj;");
+check("({ x, y }) = obj;");
+check("for (var { x, y } of obj) ;");
+check("for (let { x, y } of obj) ;");
+check("var [a, b] = obj;");
+check("let [a, b] = obj;");
+check("const [a, b] = obj;");
+check("[a, b] = obj;");
+check("for ([a, b] of obj) ;");
+check("for (var [a, b] of obj) ;");
+check("for (let [a, b] of obj) ;");
+check("(function({ x: y }) { return x; })()");
+check("(function({ x }) { return x; })()");
+check("(function([x]) { return x; })()");
+check("for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ;");
+check("for ([ arrow = () => {} ] of [[]]) ;");
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/destructuring.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,72 @@
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+var { x: y } = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+let { x: y } = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:6 ES6 destructuring is not yet implemented
+const { x: y } = obj;
+      ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:1 ES6 destructuring is not yet implemented
+({ x: y }) = obj;
+ ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (var { x: y } of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (let { x: y } of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+var { x, y } = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+let { x, y } = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:6 ES6 destructuring is not yet implemented
+const { x, y } = obj;
+      ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:1 ES6 destructuring is not yet implemented
+({ x, y }) = obj;
+ ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (var { x, y } of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (let { x, y } of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+var [a, b] = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:4 ES6 destructuring is not yet implemented
+let [a, b] = obj;
+    ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:6 ES6 destructuring is not yet implemented
+const [a, b] = obj;
+      ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+[a, b] = obj;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for ([a, b] of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (var [a, b] of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for (let [a, b] of obj) ;
+^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:9 ES6 destructuring is not yet implemented
+(function({ x: y }) { return x; })()
+         ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:9 ES6 destructuring is not yet implemented
+(function({ x }) { return x; })()
+         ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:9 ES6 destructuring is not yet implemented
+(function([x]) { return x; })()
+         ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:9 ES6 destructuring is not yet implemented
+for (var [[x, y, z] = [4, 5, 6]] = [7, 8, 9]; iterCount < 1; ) ;
+         ^
+java.lang.RuntimeException: test/script/basic/es6/destructuring.js#35:6<eval>:1:0 ES6 destructuring is not yet implemented
+for ([ arrow = () => {} ] of [[]]) ;
+^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/generator.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * Generators are not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function check(code) {
+   try {
+      eval(code);
+   } catch (e) {
+      print(String(e).replace(/\\/g, "/"))
+   }
+}
+
+check("function* func() { yield 1; }");
+check("({ * generatorMethod() { yield 1; } })");
+check("var func = function*() { yield 1; }");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/generator.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,9 @@
+java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6<eval>:1:17 ES6 generator is not yet implemented
+function* func() { yield 1; }
+                 ^
+java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6<eval>:1:23 ES6 generator is not yet implemented
+({ * generatorMethod() { yield 1; } })
+                       ^
+java.lang.RuntimeException: test/script/basic/es6/generator.js#34:6<eval>:1:23 ES6 generator is not yet implemented
+var func = function*() { yield 1; }
+                       ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/restparam.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * ES6 rest params are not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+
+function check(code) {
+   try {
+      eval(code);
+   } catch (e) {
+      print(String(e).replace(/\\/g, "/"))
+   }
+}
+
+check("function func(...args) {}");
+check("function func(x, y, ...args) {}");
+check("({ meth(...args) {} })");
+check("({ meth(x, y, ...args) {} })");
+check("({ meth(x = 0, x) {} })");
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/restparam.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,15 @@
+java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6<eval>:1:17 ES6 function rest parameter declaration is not yet implemented
+function func(...args) {}
+                 ^
+java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6<eval>:1:23 ES6 function rest parameter declaration is not yet implemented
+function func(x, y, ...args) {}
+                       ^
+java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6<eval>:1:11 ES6 function rest parameter declaration is not yet implemented
+({ meth(...args) {} })
+           ^
+java.lang.RuntimeException: test/script/basic/es6/restparam.js#35:6<eval>:1:17 ES6 function rest parameter declaration is not yet implemented
+({ meth(x, y, ...args) {} })
+                 ^
+SyntaxError: test/script/basic/es6/restparam.js#35:6<eval>:1:15 Duplicate parameter name "x"
+({ meth(x = 0, x) {} })
+               ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/spread.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * ES6 spread operator is not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function check(code) {
+    try {
+        eval(code);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"))
+    }
+}
+
+check("var x = [...args]");
+check("var x = [1, 2, ...args]");
+check("var x = [...args, 3, 5]");
+check("var r = func(...arr)");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/spread.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,12 @@
+java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8<eval>:1:9 ES6 spread operator is not yet implemented
+var x = [...args]
+         ^
+java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8<eval>:1:15 ES6 spread operator is not yet implemented
+var x = [1, 2, ...args]
+               ^
+java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8<eval>:1:9 ES6 spread operator is not yet implemented
+var x = [...args, 3, 5]
+         ^
+java.lang.RuntimeException: test/script/basic/es6/spread.js#34:8<eval>:1:13 ES6 spread operator is not yet implemented
+var r = func(...arr)
+             ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/super.js	Fri Nov 11 16:44:36 2016 +0100
@@ -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.
+ */
+
+/**
+ * ES6 super keyword is not implemented
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ */
+
+function check(code) {
+    try {
+        eval(code);
+    } catch (e) {
+        print(String(e).replace(/\\/g, "/"))
+    }
+}
+
+check("({ meth() { x = super.x } })");
+check("({ meth() { x = super.x() } })");
+check("({ meth() { x = super['x'] } })");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/super.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,9 @@
+java.lang.RuntimeException: test/script/basic/es6/super.js#34:8<eval>:1:10 ES6 super keyword is not yet implemented
+({ meth() { x = super.x } })
+          ^
+java.lang.RuntimeException: test/script/basic/es6/super.js#34:8<eval>:1:10 ES6 super keyword is not yet implemented
+({ meth() { x = super.x() } })
+          ^
+java.lang.RuntimeException: test/script/basic/es6/super.js#34:8<eval>:1:10 ES6 super keyword is not yet implemented
+({ meth() { x = super['x'] } })
+          ^
--- a/nashorn/test/script/basic/jsadapter-ids.js	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/script/basic/jsadapter-ids.js	Fri Nov 11 16:44:36 2016 +0100
@@ -30,6 +30,7 @@
 
 var obj = new JSAdapter() {
     __getIds__: function() {
+        Assert.assertTrue(this === obj);
         print("__getIds__ called");
         return [ "foo", "bar" ];
     }
--- a/nashorn/test/script/basic/jsadapter.js	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/script/basic/jsadapter.js	Fri Nov 11 16:44:36 2016 +0100
@@ -30,39 +30,81 @@
 
 var obj = new JSAdapter() {
     __get__: function(name) {
+        Assert.assertTrue(this === obj);
         print("getter called for '" + name + "'"); return name;
     },
 
     __put__: function(name, value) {
+        Assert.assertTrue(this === obj);
         print("setter called for '" + name + "' with " + value);
     },
 
     __call__: function(name, arg1, arg2) {
+        Assert.assertTrue(this === obj);
         print("method '" + name + "' called with " + arg1 + ", " + arg2);
     },
 
     __new__: function(arg1, arg2) {
+        Assert.assertTrue(this === obj);
         print("new with " + arg1 + ", " + arg2);
     },
 
     __getKeys__: function() {
+        Assert.assertTrue(this === obj);
         print("__getKeys__ called");
         return [ "foo", "bar" ];
     },
 
     __getValues__: function() {
+        Assert.assertTrue(this === obj);
         print("__getValues__ called");
         return [ "fooval", "barval" ];
     },
 
     __has__: function(name) {
+        Assert.assertTrue(this === obj);
         print("__has__ called with '" + name + "'");
         return name == "js";
     },
 
     __delete__: function(name) {
+        Assert.assertTrue(this === obj);
         print("__delete__ called with '" + name + "'");
         return true;
+    },
+
+    __preventExtensions__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__preventExtensions__ called");
+    },
+
+    __freeze__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__freeze__ called");
+
+    },
+
+    __isFrozen__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__isFrozen__ called");
+        return false;
+    },
+
+    __seal__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__seal__ called");
+    },
+
+    __isSealed__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__isSealed__ called");
+        return false;
+    },
+
+    __isExtensible__ : function() {
+        Assert.assertTrue(this === obj);
+        print("__isExtensible__ called");
+        return true;
     }
 };
 
@@ -103,3 +145,13 @@
 print(obj["js"]);
 obj["js"] = "javascript";
 print(obj["javascript"]);
+
+// call __isExtensible__, __isSealed__, __isFrozen__
+print(Object.isExtensible(obj));
+print(Object.isSealed(obj));
+print(Object.isFrozen(obj));
+
+// call __freeze__, __seal__, __preventExtensions__
+Object.freeze(obj);
+Object.seal(obj);
+Object.preventExtensions(obj);
--- a/nashorn/test/script/basic/jsadapter.js.EXPECTED	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/script/basic/jsadapter.js.EXPECTED	Fri Nov 11 16:44:36 2016 +0100
@@ -20,3 +20,12 @@
 setter called for 'js' with javascript
 getter called for 'javascript'
 javascript
+__isExtensible__ called
+true
+__isSealed__ called
+false
+__isFrozen__ called
+false
+__freeze__ called
+__seal__ called
+__preventExtensions__ called
--- a/nashorn/test/script/basic/jsadapterlink.js	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/script/basic/jsadapterlink.js	Fri Nov 11 16:44:36 2016 +0100
@@ -31,18 +31,21 @@
 
 var js1 = new JSAdapter() {
     __get__: function(name) {
+        Assert.assertTrue(this === js1);
         return "js1->" + name;
     }
 };
 
 var js2 = new JSAdapter() {
     __get__: function(name) {
+        Assert.assertTrue(this === js2);
         return "js2->" + name;
     }
 };
 
 var js3 = new JSAdapter() {
     __get__: function(name) {
+        Assert.assertTrue(this === js3);
         return "js3->" + name;
     }
 };
--- a/nashorn/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter	Fri Nov 11 16:44:36 2016 +0100
@@ -1,2 +1,3 @@
 jdk.dynalink.test.UntrustedGuardingDynamicLinkerExporter
 jdk.dynalink.test.TrustedGuardingDynamicLinkerExporter
+jdk.dynalink.test.TrustedUnderscoreNameLinkerExporter
--- a/nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,14 +24,13 @@
  */
 package jdk.dynalink.beans.test;
 
+import static jdk.dynalink.StandardNamespace.ELEMENT;
+import static jdk.dynalink.StandardNamespace.METHOD;
+import static jdk.dynalink.StandardNamespace.PROPERTY;
 import static jdk.dynalink.StandardOperation.CALL;
-import static jdk.dynalink.StandardOperation.CALL_METHOD;
-import static jdk.dynalink.StandardOperation.GET_ELEMENT;
-import static jdk.dynalink.StandardOperation.GET_LENGTH;
-import static jdk.dynalink.StandardOperation.GET_METHOD;
-import static jdk.dynalink.StandardOperation.GET_PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
 import static jdk.dynalink.StandardOperation.NEW;
-import static jdk.dynalink.StandardOperation.SET_ELEMENT;
+import static jdk.dynalink.StandardOperation.SET;
 
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
@@ -39,7 +38,6 @@
 import java.lang.invoke.MethodType;
 import java.security.AccessControlException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import jdk.dynalink.CallSiteDescriptor;
@@ -78,12 +76,21 @@
     }
 
     private CallSite createCallSite(final boolean publicLookup, final Operation op, final Object name, final MethodType mt) {
-        return createCallSite(publicLookup, new NamedOperation(op, name), mt);
+        return createCallSite(publicLookup, op.named(name), mt);
+    }
+
+    private CallSite createGetMethodCallSite(final boolean publicLookup, final String name) {
+        return createCallSite(publicLookup, GET_METHOD, name, MethodType.methodType(Object.class, Object.class));
     }
 
     private static final MethodHandle throwArrayIndexOutOfBounds = findThrower("throwArrayIndexOutOfBounds");
     private static final MethodHandle throwIndexOutOfBounds = findThrower("throwIndexOutOfBounds");
 
+    private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
+    private static final Operation GET_ELEMENT = GET.withNamespace(ELEMENT);
+    private static final Operation GET_METHOD = GET.withNamespace(METHOD);
+    private static final Operation SET_ELEMENT = SET.withNamespace(ELEMENT);
+
     private static final MethodHandle findThrower(final String name) {
         try {
             return MethodHandles.lookup().findStatic(BeanLinkerTest.class, name,
@@ -209,26 +216,6 @@
     }
 
     @Test(dataProvider = "flags")
-    public void getlengthTest(final boolean publicLookup) throws Throwable {
-        final MethodType mt = MethodType.methodType(int.class, Object.class);
-        final CallSite cs = createCallSite(publicLookup, GET_LENGTH, mt);
-
-        final int[] arr = {23, 42};
-        Assert.assertEquals((int) cs.getTarget().invoke((Object) arr), 2);
-        Assert.assertEquals((int) cs.getTarget().invoke(Collections.EMPTY_LIST), 0);
-
-        final List<String> list = new ArrayList<>();
-        list.add("hello");
-        list.add("world");
-        list.add("dynalink");
-        Assert.assertEquals((int) cs.getTarget().invoke(list), 3);
-        list.add("nashorn");
-        Assert.assertEquals((int) cs.getTarget().invoke(list), 4);
-        list.clear();
-        Assert.assertEquals((int) cs.getTarget().invoke(list), 0);
-    }
-
-    @Test(dataProvider = "flags")
     public void getElementTest(final boolean publicLookup) throws Throwable {
         final MethodType mt = MethodType.methodType(int.class, Object.class, int.class);
         final CallSite cs = createCallSite(publicLookup, GET_ELEMENT, mt);
@@ -364,8 +351,7 @@
 
     @Test(dataProvider = "flags")
     public void instanceMethodCallTest(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(Object.class, Object.class);
-        final CallSite cs = createCallSite(publicLookup, GET_METHOD, "getClass", mt);
+        final CallSite cs = createGetMethodCallSite(publicLookup, "getClass");
         final MethodType mt2 = MethodType.methodType(Class.class, Object.class, Object.class);
         final CallSite cs2 = createCallSite(publicLookup, CALL, mt2);
 
@@ -389,23 +375,8 @@
     }
 
     @Test(dataProvider = "flags")
-    public void instanceMethodCallTest2(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(Class.class, Object.class);
-        final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getClass", mt);
-        Class clz = null;
-        try {
-            clz = (Class) cs.getTarget().invoke(new Date());
-        } catch (final Throwable th) {
-            throw new RuntimeException(th);
-        }
-
-        Assert.assertEquals(clz, Date.class);
-    }
-
-    @Test(dataProvider = "flags")
     public void staticMethodCallTest(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(Object.class, StaticClass.class);
-        final CallSite cs = createCallSite(publicLookup, GET_METHOD, "getProperty", mt);
+        final CallSite cs = createGetMethodCallSite(publicLookup, "getProperty");
         final MethodType mt2 = MethodType.methodType(String.class, Object.class, Object.class, String.class);
         final CallSite cs2 = createCallSite(publicLookup, CALL, mt2);
 
@@ -428,28 +399,15 @@
         Assert.assertEquals(str, System.getProperty("os.name"));
     }
 
-    @Test(dataProvider = "flags")
-    public void staticMethodCallTest2(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(String.class, Object.class, String.class);
-        final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getProperty", mt);
-
-        String str = null;
-        try {
-            str = (String) cs.getTarget().invoke(StaticClass.forClass(System.class), "os.name");
-        } catch (final Throwable th) {
-            throw new RuntimeException(th);
-        }
-        Assert.assertEquals(str, System.getProperty("os.name"));
-    }
-
     // try calling System.getenv and expect security exception
     @Test(dataProvider = "flags")
     public void systemGetenvTest(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(Object.class, Object.class);
-        final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getenv", mt);
+        final CallSite cs1 = createGetMethodCallSite(publicLookup, "getenv");
+        final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(Object.class, Object.class, Object.class));
 
         try {
-            cs.getTarget().invoke(StaticClass.forClass(System.class));
+            final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
+            cs2.getTarget().invoke(method, StaticClass.forClass(System.class));
             throw new RuntimeException("should not reach here in any case!");
         } catch (final Throwable th) {
             Assert.assertTrue(th instanceof SecurityException);
@@ -459,11 +417,12 @@
     // try getting a specific sensitive System property and expect security exception
     @Test(dataProvider = "flags")
     public void systemGetPropertyTest(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(String.class, Object.class, String.class);
-        final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "getProperty", mt);
+        final CallSite cs1 = createGetMethodCallSite(publicLookup, "getProperty");
+        final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(String.class, Object.class, Object.class, String.class));
 
         try {
-            cs.getTarget().invoke(StaticClass.forClass(System.class), "java.home");
+            final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
+            cs2.getTarget().invoke(method, StaticClass.forClass(System.class), "java.home");
             throw new RuntimeException("should not reach here in any case!");
         } catch (final Throwable th) {
             Assert.assertTrue(th instanceof SecurityException);
@@ -473,11 +432,12 @@
     // check a @CallerSensitive API and expect appropriate access check exception
     @Test(dataProvider = "flags")
     public void systemLoadLibraryTest(final boolean publicLookup) {
-        final MethodType mt = MethodType.methodType(void.class, Object.class, String.class);
-        final CallSite cs = createCallSite(publicLookup, CALL_METHOD, "loadLibrary", mt);
+        final CallSite cs1 = createGetMethodCallSite(publicLookup, "loadLibrary");
+        final CallSite cs2 = createCallSite(publicLookup, CALL, MethodType.methodType(void.class, Object.class, Object.class, String.class));
 
         try {
-            cs.getTarget().invoke(StaticClass.forClass(System.class), "foo");
+            final Object method = cs1.getTarget().invoke(StaticClass.forClass(System.class));
+            cs2.getTarget().invoke(method, StaticClass.forClass(System.class), "foo");
             throw new RuntimeException("should not reach here in any case!");
         } catch (final Throwable th) {
             if (publicLookup) {
--- a/nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,12 +24,12 @@
  */
 package jdk.dynalink.beans.test;
 
+import static jdk.dynalink.StandardNamespace.ELEMENT;
+import static jdk.dynalink.StandardNamespace.METHOD;
+import static jdk.dynalink.StandardNamespace.PROPERTY;
 import static jdk.dynalink.StandardOperation.CALL;
-import static jdk.dynalink.StandardOperation.GET_ELEMENT;
-import static jdk.dynalink.StandardOperation.GET_METHOD;
-import static jdk.dynalink.StandardOperation.GET_PROPERTY;
-import static jdk.dynalink.StandardOperation.SET_ELEMENT;
-import static jdk.dynalink.StandardOperation.SET_PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+import static jdk.dynalink.StandardOperation.SET;
 
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
@@ -42,12 +42,11 @@
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 import jdk.dynalink.CallSiteDescriptor;
-import jdk.dynalink.CompositeOperation;
 import jdk.dynalink.DynamicLinkerFactory;
-import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Namespace;
+import jdk.dynalink.NamespaceOperation;
 import jdk.dynalink.NoSuchDynamicMethodException;
 import jdk.dynalink.Operation;
-import jdk.dynalink.StandardOperation;
 import jdk.dynalink.support.SimpleRelinkableCallSite;
 import org.testng.Assert;
 import org.testng.annotations.Test;
@@ -67,32 +66,32 @@
 
     @Test
     public static void testPublicFieldPropertyUnnamedGetter() {
-        testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(op, new Bean1(), "answer")));
+        testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals(42, call(op, new Bean1(), "answer")));
     }
 
     @Test
     public static void testPublicFieldPropertyNamedGetter() {
-        testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(named("answer", op), new Bean1())));
+        testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals(42, call(op.named("answer"), new Bean1())));
     }
 
     @Test
     public static void testGetterPropertyUnnamedGetter() {
-        testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(op, new Bean1(), "name")));
+        testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals("bean1", call(op, new Bean1(), "name")));
     }
 
     @Test
     public static void testGetterPropertyNamedGetter() {
-        testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(named("name", op), new Bean1())));
+        testGetterPermutations(PROPERTY, (op) -> Assert.assertEquals("bean1", call(op.named("name"), new Bean1())));
     }
 
     @Test
     public static void testMethodUnnamedGetter() {
-        testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op, new Bean1(), "someMethod"), new Bean1(), "bar")));
+        testGetterPermutations(METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op, new Bean1(), "someMethod"), new Bean1(), "bar")));
     }
 
     @Test
     public static void testMethodNamedGetter() {
-        testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(named("someMethod", op), new Bean1()), new Bean1(), "bar")));
+        testGetterPermutations(METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op.named("someMethod"), new Bean1()), new Bean1(), "bar")));
     }
 
     private static final Map<String, String> MAP1 = new HashMap<>();
@@ -102,12 +101,12 @@
 
     @Test
     public static void testElementUnnamedGetter() {
-        testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(op, MAP1, "foo")));
+        testGetterPermutations(ELEMENT, (op) -> Assert.assertEquals("bar", call(op, MAP1, "foo")));
     }
 
     @Test
     public static void testElementNamedGetter() {
-        testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(named("foo", op), MAP1)));
+        testGetterPermutations(ELEMENT, (op) -> Assert.assertEquals("bar", call(op.named("foo"), MAP1)));
     }
 
     public static class Bean2 {
@@ -121,7 +120,7 @@
 
     @Test
     public static void testUnnamedFieldSetter() {
-        testSetterPermutations(SET_PROPERTY, (op) -> {
+        testSetterPermutations(PROPERTY, (op) -> {
             final Bean2 bean2 = new Bean2();
             call(op, bean2, "answer", 12);
             Assert.assertEquals(bean2.answer, 12);
@@ -130,16 +129,16 @@
 
     @Test
     public static void testNamedFieldSetter() {
-        testSetterPermutations(SET_PROPERTY, (op) -> {
+        testSetterPermutations(PROPERTY, (op) -> {
             final Bean2 bean2 = new Bean2();
-            call(named("answer", op), bean2, 14);
+            call(op.named("answer"), bean2, 14);
             Assert.assertEquals(bean2.answer, 14);
         });
     }
 
     @Test
     public static void testUnnamedPropertySetter() {
-        testSetterPermutations(SET_PROPERTY, (op) -> {
+        testSetterPermutations(PROPERTY, (op) -> {
             final Bean2 bean2 = new Bean2();
             call(op, bean2, "name", "boo");
             Assert.assertEquals(bean2.name, "boo");
@@ -148,14 +147,14 @@
 
     @Test
     public static void testNamedPropertySetter() {
-        testSetterPermutations(SET_PROPERTY, (op) -> {
+        testSetterPermutations(PROPERTY, (op) -> {
             final Bean2 bean2 = new Bean2();
-            call(named("name", op), bean2, "blah");
+            call(op.named("name"), bean2, "blah");
             Assert.assertEquals(bean2.name, "blah");
         });
     }
 
-    private static final Pattern GET_ELEMENT_THEN_PROPERTY_PATTERN = Pattern.compile(".*GET_ELEMENT.*GET_PROPERTY.*");
+    private static final Pattern GET_ELEMENT_THEN_PROPERTY_PATTERN = Pattern.compile(".*ELEMENT.*PROPERTY.*");
 
     @Test
     public static void testUnnamedElementAndPropertyGetter() {
@@ -168,10 +167,10 @@
     public static void testNamedElementAndPropertyGetter() {
         final Map<String, Object> map = new HashMap<>();
         map.put("empty", true);
-        testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(named("empty", op), map)));
+        testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(op.named("empty"), map)));
     }
 
-    private static final Pattern GET_PROPERTY_THEN_ELEMENT_PATTERN = Pattern.compile(".*GET_PROPERTY.*GET_ELEMENT.*");
+    private static final Pattern GET_PROPERTY_THEN_ELEMENT_PATTERN = Pattern.compile(".*PROPERTY.*ELEMENT.*");
 
     @Test
     public static void testUnnamedPropertyAndElementGetter() {
@@ -184,7 +183,7 @@
     public static void testNamedPropertyAndElementGetter() {
         final Map<String, Object> map = new HashMap<>();
         map.put("empty", true);
-        testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(named("empty", op), map)));
+        testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(op.named("empty"), map)));
     }
 
     public static class MapWithProperty extends HashMap<String, Object> {
@@ -200,24 +199,24 @@
         final MapWithProperty map = new MapWithProperty();
         map.put("name", "element");
 
-        call(ops(SET_PROPERTY, SET_ELEMENT), map, "name", "property");
+        call(SET.withNamespaces(PROPERTY, ELEMENT), map, "name", "property");
         Assert.assertEquals("property", map.name);
         Assert.assertEquals("element", map.get("name"));
 
-        call(ops(SET_ELEMENT, SET_PROPERTY), map, "name", "element2");
+        call(SET.withNamespaces(ELEMENT, PROPERTY), map, "name", "element2");
         Assert.assertEquals("property", map.name);
         Assert.assertEquals("element2", map.get("name"));
     }
 
     @Test
     public static void testMissingMembersAtLinkTime() {
-        testPermutations(GETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(named("foo", op), new Object())));
-        testPermutations(SETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(named("foo", op), new Object(), "newValue")));
+        testPermutations(GETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(op.named("foo"), new Object())));
+        testPermutations(SETTER_PERMUTATIONS, (op) -> expectNoSuchDynamicMethodException(()-> call(op.named("foo"), new Object(), "newValue")));
     }
 
     @Test
     public static void testMissingMembersAtRunTime() {
-        call(GET_ELEMENT, new ArrayList<>(), "foo");
+        call(GET.withNamespace(ELEMENT), new ArrayList<>(), "foo");
         Stream.of(new HashMap(), new ArrayList(), new Object[0]).forEach((receiver) -> {
             testPermutations(GETTER_PERMUTATIONS, (op) -> { System.err.println(op + " " + receiver.getClass().getName()); Assert.assertNull(call(op, receiver, "foo"));});
             // No assertion for the setter; we just expect it to silently succeed
@@ -233,59 +232,59 @@
         }
     }
 
-    private static Operation[] GETTER_PERMUTATIONS = new Operation[] {
-        GET_PROPERTY,
-        GET_METHOD,
-        GET_ELEMENT,
-        ops(GET_PROPERTY, GET_ELEMENT),
-        ops(GET_PROPERTY, GET_METHOD),
-        ops(GET_ELEMENT,  GET_PROPERTY),
-        ops(GET_ELEMENT,  GET_METHOD),
-        ops(GET_METHOD,   GET_PROPERTY),
-        ops(GET_METHOD,   GET_ELEMENT),
-        ops(GET_PROPERTY, GET_ELEMENT,  GET_METHOD),
-        ops(GET_PROPERTY, GET_METHOD,   GET_ELEMENT),
-        ops(GET_ELEMENT,  GET_PROPERTY, GET_METHOD),
-        ops(GET_ELEMENT,  GET_METHOD,   GET_PROPERTY),
-        ops(GET_METHOD,   GET_PROPERTY, GET_ELEMENT),
-        ops(GET_METHOD,   GET_ELEMENT,  GET_PROPERTY),
+    private static NamespaceOperation[] GETTER_PERMUTATIONS = new NamespaceOperation[] {
+        GET.withNamespaces(PROPERTY),
+        GET.withNamespaces(METHOD),
+        GET.withNamespaces(ELEMENT),
+        GET.withNamespaces(PROPERTY, ELEMENT),
+        GET.withNamespaces(PROPERTY, METHOD),
+        GET.withNamespaces(ELEMENT,  PROPERTY),
+        GET.withNamespaces(ELEMENT,  METHOD),
+        GET.withNamespaces(METHOD,   PROPERTY),
+        GET.withNamespaces(METHOD,   ELEMENT),
+        GET.withNamespaces(PROPERTY, ELEMENT,  METHOD),
+        GET.withNamespaces(PROPERTY, METHOD,   ELEMENT),
+        GET.withNamespaces(ELEMENT,  PROPERTY, METHOD),
+        GET.withNamespaces(ELEMENT,  METHOD,   PROPERTY),
+        GET.withNamespaces(METHOD,   PROPERTY, ELEMENT),
+        GET.withNamespaces(METHOD,   ELEMENT,  PROPERTY)
     };
 
-    private static Operation[] SETTER_PERMUTATIONS = new Operation[] {
-        SET_PROPERTY,
-        SET_ELEMENT,
-        ops(SET_PROPERTY, SET_ELEMENT),
-        ops(SET_ELEMENT,  SET_PROPERTY)
+    private static NamespaceOperation[] SETTER_PERMUTATIONS = new NamespaceOperation[] {
+        SET.withNamespaces(PROPERTY),
+        SET.withNamespaces(ELEMENT),
+        SET.withNamespaces(PROPERTY, ELEMENT),
+        SET.withNamespaces(ELEMENT, PROPERTY)
     };
 
-    private static void testPermutations(final Operation[] ops, final StandardOperation requiredOp, final int expectedCount, final Consumer<Operation> test) {
-        testPermutationsWithFilter(ops, (op)->CompositeOperation.contains(op, requiredOp), expectedCount, test);
+    private static void testPermutations(final NamespaceOperation[] ops, final Operation requiredOp, final Namespace requiredNamespace, final int expectedCount, final Consumer<NamespaceOperation> test) {
+        testPermutationsWithFilter(ops, (op)->NamespaceOperation.contains(op, requiredOp, requiredNamespace), expectedCount, test);
     }
 
-    private static void testPermutations(final Operation[] ops, final Pattern regex, final int expectedCount, final Consumer<Operation> test) {
+    private static void testPermutations(final NamespaceOperation[] ops, final Pattern regex, final int expectedCount, final Consumer<NamespaceOperation> test) {
         testPermutationsWithFilter(ops, (op)->regex.matcher(op.toString()).matches(), expectedCount, test);
     }
 
-    private static void testPermutations(final Operation[] ops, final Consumer<Operation> test) {
+    private static void testPermutations(final NamespaceOperation[] ops, final Consumer<NamespaceOperation> test) {
         testPermutationsWithFilter(ops, (op)->true, ops.length, test);
     }
 
-    private static void testPermutationsWithFilter(final Operation[] ops, final Predicate<Operation> filter, final int expectedCount, final Consumer<Operation> test) {
+    private static void testPermutationsWithFilter(final NamespaceOperation[] ops, final Predicate<NamespaceOperation> filter, final int expectedCount, final Consumer<NamespaceOperation> test) {
         final int[] counter = new int[1];
         Stream.of(ops).filter(filter).forEach((op)-> { counter[0]++; test.accept(op); });
         Assert.assertEquals(counter[0], expectedCount);
     }
 
-    private static void testGetterPermutations(final StandardOperation requiredOp, final Consumer<Operation> test) {
-        testPermutations(GETTER_PERMUTATIONS, requiredOp, 11, test);
+    private static void testGetterPermutations(final Namespace requiredNamespace, final Consumer<NamespaceOperation> test) {
+        testPermutations(GETTER_PERMUTATIONS, GET, requiredNamespace, 11, test);
     }
 
-    private static void testGetterPermutations(final Pattern regex, final int expectedCount, final Consumer<Operation> test) {
+    private static void testGetterPermutations(final Pattern regex, final int expectedCount, final Consumer<NamespaceOperation> test) {
         testPermutations(GETTER_PERMUTATIONS, regex, expectedCount, test);
     }
 
-    private static void testSetterPermutations(final StandardOperation requiredOp, final Consumer<Operation> test) {
-        testPermutations(SETTER_PERMUTATIONS, requiredOp, 3, test);
+    private static void testSetterPermutations(final Namespace requiredNamespace, final Consumer<NamespaceOperation> test) {
+        testPermutations(SETTER_PERMUTATIONS, SET, requiredNamespace, 3, test);
     }
 
     private static Object call(final Operation op, final Object... args) {
@@ -305,14 +304,6 @@
         return call(CALL, args);
     }
 
-    private static Operation named(final Object name, final Operation... ops) {
-        return new NamedOperation(ops(ops), name);
-    }
-
-    private static Operation ops(final Operation... ops) {
-        return ops.length == 1 ? ops[0] : new CompositeOperation(ops);
-    }
-
     private static MethodType t(final int argCount) {
         return MethodType.methodType(Object.class, Collections.nCopies(argCount, Object.class));
     }
--- a/nashorn/test/src/jdk/dynalink/support/test/CallSiteTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/dynalink/support/test/CallSiteTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -25,6 +25,9 @@
 
 package jdk.dynalink.support.test;
 
+import static jdk.dynalink.StandardNamespace.PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -33,14 +36,15 @@
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.DynamicLinker;
 import jdk.dynalink.DynamicLinkerFactory;
-import jdk.dynalink.NamedOperation;
-import jdk.dynalink.StandardOperation;
+import jdk.dynalink.Operation;
 import jdk.dynalink.linker.GuardedInvocation;
 import jdk.dynalink.support.SimpleRelinkableCallSite;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class CallSiteTest {
+    private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
+
     @Test
     public void testInitialize() {
         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
@@ -48,7 +52,7 @@
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
         final boolean[] initializeCalled = { Boolean.FALSE };
         linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
-            MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "DO_NOT_CARE"), mt)) {
+            MethodHandles.publicLookup(), GET_PROPERTY.named("DO_NOT_CARE"), mt)) {
                 @Override
                 public void initialize(final MethodHandle relinkAndInvoke) {
                     initializeCalled[0] = Boolean.TRUE;
@@ -66,7 +70,7 @@
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
         final boolean[] relinkCalled = { Boolean.FALSE };
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
-            MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "class"), mt)) {
+            MethodHandles.publicLookup(), GET_PROPERTY.named("class"), mt)) {
                 @Override
                 public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
                     relinkCalled[0] = Boolean.TRUE;
@@ -90,7 +94,7 @@
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
         final boolean[] resetAndRelinkCalled = { Boolean.FALSE };
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
-            MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "length"), mt)) {
+            MethodHandles.publicLookup(), GET_PROPERTY.named("length"), mt)) {
                 @Override
                 public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) {
                     resetAndRelinkCalled[0] = Boolean.TRUE;
--- a/nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,6 +24,9 @@
  */
 package jdk.dynalink.test;
 
+import static jdk.dynalink.StandardNamespace.PROPERTY;
+import static jdk.dynalink.StandardOperation.GET;
+
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -35,9 +38,9 @@
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.DynamicLinker;
 import jdk.dynalink.DynamicLinkerFactory;
-import jdk.dynalink.NamedOperation;
 import jdk.dynalink.NoSuchDynamicMethodException;
 import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
 import jdk.dynalink.StandardOperation;
 import jdk.dynalink.beans.StaticClass;
 import jdk.dynalink.linker.GuardedInvocation;
@@ -52,6 +55,8 @@
 @SuppressWarnings("javadoc")
 public class DynamicLinkerFactoryTest {
 
+    private static final Operation GET_PROPERTY = GET.withNamespace(PROPERTY);
+
     private static DynamicLinkerFactory newDynamicLinkerFactory(final boolean resetClassLoader) {
         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
         if (resetClassLoader) {
@@ -190,7 +195,7 @@
         final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
         final DynamicLinker linker = factory.createLinker();
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
-                MethodHandles.publicLookup(), StandardOperation.GET_PROPERTY, mt)));
+                MethodHandles.publicLookup(), GET_PROPERTY, mt)));
         Assert.assertFalse(reachedPrelinkTransformer[0]);
         Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
         Assert.assertTrue(reachedPrelinkTransformer[0]);
@@ -209,7 +214,7 @@
         final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class);
         final DynamicLinker linker = factory.createLinker();
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
-                MethodHandles.publicLookup(), StandardOperation.GET_PROPERTY, mt)));
+                MethodHandles.publicLookup(), GET_PROPERTY, mt)));
         Assert.assertFalse(reachedInternalObjectsFilter[0]);
         Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class);
         Assert.assertTrue(reachedInternalObjectsFilter[0]);
@@ -252,7 +257,7 @@
 
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
         final CallSiteDescriptor testDescriptor = new CallSiteDescriptor(MethodHandles.publicLookup(),
-                new NamedOperation(StandardOperation.GET_METHOD, methodName), mt);
+                GET.withNamespace(StandardNamespace.METHOD).named(methodName), mt);
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(testDescriptor));
 
         TrustedGuardingDynamicLinkerExporter.enable();
@@ -274,7 +279,7 @@
         final DynamicLinker linker = factory.createLinker();
 
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
-        final NamedOperation op = new NamedOperation(StandardOperation.GET_PROPERTY, "foo");
+        final Operation op = GET_PROPERTY.named("foo");
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
                 MethodHandles.publicLookup(), op, mt)));
         final boolean[] reachedGetMember = new boolean[1];
@@ -306,7 +311,7 @@
         // check that the nashorn exported linker can be used for ScriptObjectMirror
         final ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
         final MethodType mt = MethodType.methodType(Object.class, Object.class);
-        final NamedOperation op = new NamedOperation(StandardOperation.GET_PROPERTY, "foo");
+        final Operation op = GET_PROPERTY.named("foo");
         final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor(
                 MethodHandles.publicLookup(), op, mt)));
         Object value = null;
--- a/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/dynalink/test/LinkedCallSiteLocationTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -24,20 +24,21 @@
  */
 package jdk.dynalink.test;
 
-import static jdk.dynalink.StandardOperation.CALL_METHOD;
-
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.DynamicLinker;
 import jdk.dynalink.DynamicLinkerFactory;
-import jdk.dynalink.NamedOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
+import jdk.dynalink.StandardOperation;
 import jdk.dynalink.linker.GuardingDynamicLinker;
 import jdk.dynalink.support.SimpleRelinkableCallSite;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
 public class LinkedCallSiteLocationTest {
+    private static final Operation GET_METHOD = StandardOperation.GET.withNamespace(StandardNamespace.METHOD);
     @Test
     public void testLinkedCallSiteLocation() throws Throwable {
         final StackTraceElement[] lastLinked = new StackTraceElement[1];
@@ -51,7 +52,7 @@
         final SimpleRelinkableCallSite callSite = new SimpleRelinkableCallSite(
                 new CallSiteDescriptor(
                         MethodHandles.lookup(),
-                        new NamedOperation(CALL_METHOD, "foo"),
+                        GET_METHOD.named("foo"),
                         MethodType.methodType(void.class, Object.class)));
         linker.link(callSite);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/dynalink/test/TrustedUnderscoreNameLinkerExporter.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 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.
+ */
+
+package jdk.dynalink.test;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import jdk.dynalink.CallSiteDescriptor;
+import jdk.dynalink.NamedOperation;
+import jdk.dynalink.NamespaceOperation;
+import jdk.dynalink.Operation;
+import jdk.dynalink.StandardNamespace;
+import jdk.dynalink.StandardOperation;
+import jdk.dynalink.linker.GuardedInvocation;
+import jdk.dynalink.linker.GuardingDynamicLinker;
+import jdk.dynalink.linker.GuardingDynamicLinkerExporter;
+import jdk.dynalink.linker.LinkRequest;
+import jdk.dynalink.linker.LinkerServices;
+import jdk.dynalink.linker.support.SimpleLinkRequest;
+
+/**
+ * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276).
+ * This linker translater underscore_separated method names to CamelCase names
+ * used in Java APIs.
+ */
+public final class TrustedUnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter {
+    private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)");
+
+    // translate underscore_separated name as a CamelCase name
+    private static String translateToCamelCase(final String name) {
+        final Matcher m = UNDERSCORE_NAME.matcher(name);
+        final StringBuilder buf = new StringBuilder();
+        while (m.find()) {
+            m.appendReplacement(buf, m.group(1).toUpperCase());
+        }
+        m.appendTail(buf);
+        return buf.toString();
+    }
+
+    @Override
+    public List<GuardingDynamicLinker> get() {
+        final ArrayList<GuardingDynamicLinker> linkers = new ArrayList<>();
+        linkers.add(new GuardingDynamicLinker() {
+            @Override
+            public GuardedInvocation getGuardedInvocation(final LinkRequest request,
+                final LinkerServices linkerServices) throws Exception {
+                final CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                final Operation op = desc.getOperation();
+                final Object name = NamedOperation.getName(op);
+                final Operation namespaceOp = NamedOperation.getBaseOperation(op);
+                // is this a named GET_METHOD?
+                final boolean isGetMethod =
+                        NamespaceOperation.getBaseOperation(namespaceOp) == StandardOperation.GET
+                        && StandardNamespace.findFirst(namespaceOp) == StandardNamespace.METHOD;
+                if (isGetMethod && name instanceof String) {
+                    final String str = (String)name;
+                    if (str.indexOf('_') == -1) {
+                        return null;
+                    }
+
+                    final String nameStr = translateToCamelCase(str);
+                    // create a new call descriptor to use translated name
+                    final CallSiteDescriptor newDesc = AccessController.doPrivileged(
+                        new PrivilegedAction<CallSiteDescriptor>() {
+                            @Override
+                            public CallSiteDescriptor run() {
+                                return desc.changeOperation(((NamedOperation)op).changeName(nameStr));
+                            }
+                        });
+                    // create a new Link request to link the call site with translated name
+                    final LinkRequest newRequest = request.replaceArguments(newDesc, request.getArguments());
+                    // return guarded invocation linking the translated request
+                    return linkerServices.getGuardedInvocation(newRequest);
+                }
+
+                return null;
+            }
+        });
+        return linkers;
+    }
+}
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java	Mon Nov 14 11:15:43 2016 +0100
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/test/ArrayConversionTest.java	Fri Nov 11 16:44:36 2016 +0100
@@ -104,11 +104,11 @@
     @Test
     public void testVarArgs() throws ScriptException {
         // Sole NativeArray in vararg position becomes vararg array itself
-        runTest("assertVarArg_42_17", "[42, 17]");
+        runTest("assertVarArgWith42And17", "[42, 17]");
         // NativeArray in vararg position becomes an argument if there are more arguments
-        runTest("assertVarArg_array_17", "[42], 18");
+        runTest("assertVarArgArray7", "[42], 18");
         // Only NativeArray is converted to vararg array, other objects (e.g. a function) aren't
-        runTest("assertVarArg_function", "function() { return 'Hello' }");
+        runTest("assertVarArgFunction", "function() { return 'Hello' }");
     }
 
     private static void runTest(final String testMethodName, final String argument) throws ScriptException {
@@ -209,20 +209,20 @@
         assertEquals(Arrays.asList("apple", "orange"), array[1]);
     }
 
-    public static void assertVarArg_42_17(final Object... args) {
+    public static void assertVarArgWith42And17(final Object... args) {
         assertEquals(2, args.length);
         assertEquals(42, ((Number)args[0]).intValue());
         assertEquals(17, ((Number)args[1]).intValue());
     }
 
-    public static void assertVarArg_array_17(final Object... args) throws ScriptException {
+    public static void assertVarArgArray7(final Object... args) throws ScriptException {
         assertEquals(2, args.length);
         e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]);
         assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42"));
         assertEquals(18, ((Number)args[1]).intValue());
     }
 
-    public static void assertVarArg_function(final Object... args) throws ScriptException {
+    public static void assertVarArgFunction(final Object... args) throws ScriptException {
         assertEquals(1, args.length);
         e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]);
         assertEquals("Hello", e.eval("fn()"));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8169050_Test.java	Fri Nov 11 16:44:36 2016 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.api.scripting.test;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+/**
+ * @bug 8169050
+ * @summary underscore_linker.js sample fails after dynalink changes for JDK-8168005
+ */
+public class JDK_8169050_Test {
+    private ScriptEngine engine;
+
+    @BeforeClass
+    public void setupTest() {
+        engine = new ScriptEngineManager().getEngineByName("js");
+    }
+
+    @Test
+    public void testUndersoreName() throws ScriptException {
+        engine.eval("var S = java.util.stream.Stream, v = 0;");
+        // The underscore name 'for_each' exercises pluggable dynalink linker
+        engine.eval("S.of(4, 5, 9).for_each(function(x) { v += x })");
+        assertEquals(18, ((Number)engine.get("v")).intValue());
+    }
+}
--- a/test/Makefile	Mon Nov 14 11:15:43 2016 +0100
+++ b/test/Makefile	Fri Nov 11 16:44:36 2016 +0100
@@ -74,13 +74,14 @@
 jaxp_%:
 	@$(NO_STOPPING)$(call SUBDIR_TEST, $(JAXP_DIR), CONCURRENCY=$(JDK_TEST_JOBS) TEST="$@" $@)
 
-ifeq ($(TEST_JOBS), 0)
-  HOTSPOT_TEST_JOBS=1
-else
-  HOTSPOT_TEST_JOBS=$(TEST_JOBS)
+SUB_MAKE_ARGS :=
+ifneq ($(TEST_JOBS), 0)
+  ifneq ($(TEST_JOBS), )
+    SUB_MAKE_ARGS += CONCURRENCY=$(TEST_JOBS)
+  endif
 endif
 hotspot_%:
-	@$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), CONCURRENCY=$(HOTSPOT_TEST_JOBS) TEST="$@" $@)
+	@$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), $(SUB_MAKE_ARGS) TEST="$@" $@)
 
 #
 # jtreg_tests
--- a/test/make/TestJavaCompilation.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/test/make/TestJavaCompilation.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -202,9 +202,9 @@
     DEPENDENCIES := $(OUTPUT_DIR)/_jar3_created, \
     SRCS := $(JAR3_SRC_ROOT1) $(JAR3_SRC_ROOT2), \
     EXTRA_FILES := extra-file \
-        dir2/file$$$$foo.dollar \
+        dir2/file$$foo.dollar \
         $(JAR3_SRC_ROOT2)/extra-file-abs, \
-    EXCLUDE_FILES := dir1/file1$$$$foo.class, \
+    EXCLUDE_FILES := dir1/file1$$foo.class, \
     JAR := $(JAR3_FILE), \
 ))
 
--- a/test/make/TestMakeBase.gmk	Mon Nov 14 11:15:43 2016 +0100
+++ b/test/make/TestMakeBase.gmk	Fri Nov 11 16:44:36 2016 +0100
@@ -209,9 +209,9 @@
 	test ! -e $(VARDEP_FLAG_FILE)
         #
         # Test including some problematic characters
-	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$$$ORIGIN' $(VARDEP_TARGET_FILE)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$ORIGIN' $(VARDEP_TARGET_FILE)
 	$(RM) $(VARDEP_FLAG_FILE)
-	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$$$ORIGIN' $(VARDEP_TARGET_FILE)
+	$(MAKE) -f $(THIS_FILE) VARDEP_TEST_VAR='value4 \$$ORIGIN' $(VARDEP_TARGET_FILE)
 	test ! -e $(VARDEP_FLAG_FILE)
 
 # Test specifying a specific value file to store variable in