Merge jdk-9+117
authorduke
Wed, 05 Jul 2017 21:39:33 +0200
changeset 37761 82b8d12a553f
parent 37760 cc50ee6a8454 (diff)
parent 37647 ff3dad4e4c51 (current diff)
child 37762 13a38cb281f1
child 37763 2ea566cfe805
child 37765 d65d7bda43ce
child 37772 aba6cb725aae
child 37773 e5b3e9732c3c
child 37778 5c95f3324916
child 37780 06f3783b338f
child 37821 ff14805c665b
child 37822 8b86795b49d4
child 37826 b6d9cd218e34
child 37828 3a06bcd89461
child 37837 939747d20dd3
child 37839 0ff08f863ac1
child 37843 9c1b6cb93294
child 37844 339503342184
child 37847 ae390587c2e9
child 37849 3c7998b21c27
child 38126 c3706b502779
Merge
--- a/.hgtags-top-repo	Wed Jul 05 21:38:13 2017 +0200
+++ b/.hgtags-top-repo	Wed Jul 05 21:39:33 2017 +0200
@@ -358,3 +358,4 @@
 55b6d550828d1223b364e6ead4a56e56411c56df jdk-9+113
 1d992540870ff33fe6cc550443388588df9b9e4f jdk-9+114
 09617ce980b99d49abfd54dacfed353c47e2a115 jdk-9+115
+6743a8e0cab7b5f6f4a0575f6664892f0ab740af jdk-9+116
--- a/common/autoconf/boot-jdk.m4	Wed Jul 05 21:38:13 2017 +0200
+++ b/common/autoconf/boot-jdk.m4	Wed Jul 05 21:39:33 2017 +0200
@@ -397,6 +397,7 @@
   ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA])
   ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA])
   ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA])
+  ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA])
 
   AC_MSG_RESULT([$boot_jdk_jvmargs_small])
 
--- a/common/autoconf/compare.sh.in	Wed Jul 05 21:38:13 2017 +0200
+++ b/common/autoconf/compare.sh.in	Wed Jul 05 21:39:33 2017 +0200
@@ -31,7 +31,7 @@
 
 export LEGACY_BUILD_DIR=@OPENJDK_TARGET_OS@-@OPENJDK_TARGET_CPU_LEGACY@
 
-sexport OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
+export OPENJDK_TARGET_OS="@OPENJDK_TARGET_OS@"
 export OPENJDK_TARGET_CPU="@OPENJDK_TARGET_CPU@"
 export OPENJDK_TARGET_CPU_LIBDIR="@OPENJDK_TARGET_CPU_LIBDIR@"
 export DEBUG_LEVEL="@DEBUG_LEVEL@"
--- a/common/autoconf/generated-configure.sh	Wed Jul 05 21:38:13 2017 +0200
+++ b/common/autoconf/generated-configure.sh	Wed Jul 05 21:39:33 2017 +0200
@@ -1224,9 +1224,9 @@
 with_dxsdk
 with_dxsdk_lib
 with_dxsdk_include
-enable_jtreg_failure_handler
 enable_new_hotspot_build
 enable_hotspot_test_in_build
+enable_jtreg_failure_handler
 with_num_cores
 with_memory_size
 with_jobs
@@ -5070,7 +5070,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1460963400
+DATE_WHEN_GENERATED=1462204427
 
 ###############################################################################
 #
@@ -15492,7 +15492,7 @@
     HOTSPOT_TARGET_CPU_DEFINE=PPC32
   elif test "x$OPENJDK_TARGET_CPU" = xs390; then
     HOTSPOT_TARGET_CPU_DEFINE=S390
-  elif test "x$OPENJDK_TARGET_CPU" = ss390x; then
+  elif test "x$OPENJDK_TARGET_CPU" = xs390x; then
     HOTSPOT_TARGET_CPU_DEFINE=S390
   fi
 
@@ -15648,7 +15648,7 @@
     HOTSPOT_BUILD_CPU_DEFINE=PPC32
   elif test "x$OPENJDK_BUILD_CPU" = xs390; then
     HOTSPOT_BUILD_CPU_DEFINE=S390
-  elif test "x$OPENJDK_BUILD_CPU" = ss390x; then
+  elif test "x$OPENJDK_BUILD_CPU" = xs390x; then
     HOTSPOT_BUILD_CPU_DEFINE=S390
   fi
 
@@ -64282,6 +64282,21 @@
   fi
 
 
+  $ECHO "Check if jvm arg is ok: -XX:TieredStopAtLevel=1" >&5
+  $ECHO "Command: $JAVA -XX:TieredStopAtLevel=1 -version" >&5
+  OUTPUT=`$JAVA -XX:TieredStopAtLevel=1 -version 2>&1`
+  FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn`
+  FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""`
+  if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then
+    boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:TieredStopAtLevel=1"
+    JVM_ARG_OK=true
+  else
+    $ECHO "Arg failed:" >&5
+    $ECHO "$OUTPUT" >&5
+    JVM_ARG_OK=false
+  fi
+
+
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5
 $as_echo "$boot_jdk_jvmargs_small" >&6; }
 
--- a/common/autoconf/platform.m4	Wed Jul 05 21:38:13 2017 +0200
+++ b/common/autoconf/platform.m4	Wed Jul 05 21:39:33 2017 +0200
@@ -435,7 +435,7 @@
     HOTSPOT_$1_CPU_DEFINE=PPC32
   elif test "x$OPENJDK_$1_CPU" = xs390; then
     HOTSPOT_$1_CPU_DEFINE=S390
-  elif test "x$OPENJDK_$1_CPU" = ss390x; then
+  elif test "x$OPENJDK_$1_CPU" = xs390x; then
     HOTSPOT_$1_CPU_DEFINE=S390
   fi
   AC_SUBST(HOTSPOT_$1_CPU_DEFINE)
--- a/common/conf/jib-profiles.js	Wed Jul 05 21:38:13 2017 +0200
+++ b/common/conf/jib-profiles.js	Wed Jul 05 21:39:33 2017 +0200
@@ -212,14 +212,17 @@
  * @returns Common values
  */
 var getJibProfilesCommon = function (input) {
-    var common = {
-        dependencies: ["boot_jdk", "gnumake", "jtreg"],
-        configure_args: ["--with-default-make-target=all", "--enable-jtreg-failure-handler"],
-        configure_args_32bit: ["--with-target-bits=32", "--with-jvm-variants=client,server"],
-        configure_args_debug: ["--enable-debug"],
-        configure_args_slowdebug: ["--with-debug-level=slowdebug"],
-        organization: "jpg.infra.builddeps"
-    };
+    var common = {};
+
+    common.dependencies = ["boot_jdk", "gnumake", "jtreg"],
+    common.default_make_targets = ["product-images", "test-image"],
+    common.default_make_targets_debug = common.default_make_targets;
+    common.default_make_targets_slowdebug = common.default_make_targets;
+    common.configure_args = ["--enable-jtreg-failure-handler"],
+    common.configure_args_32bit = ["--with-target-bits=32", "--with-jvm-variants=client,server"],
+    common.configure_args_debug = ["--enable-debug"],
+    common.configure_args_slowdebug = ["--with-debug-level=slowdebug"],
+    common.organization = "jpg.infra.builddeps"
 
     return common;
 };
@@ -241,8 +244,8 @@
             target_os: "linux",
             target_cpu: "x64",
             dependencies: concat(common.dependencies, "devkit"),
-	    configure_args: concat(common.configure_args, "--with-zlib=system"),
-            make_args: common.make_args
+            configure_args: concat(common.configure_args, "--with-zlib=system"),
+            default_make_targets: concat(common.default_make_targets, "docs-image")
         },
 
         "linux-x86": {
@@ -252,39 +255,39 @@
             dependencies: concat(common.dependencies, "devkit"),
             configure_args: concat(common.configure_args, common.configure_args_32bit,
                 "--with-zlib=system"),
-            make_args: common.make_args
+            default_make_targets: common.default_make_targets
         },
 
         "macosx-x64": {
             target_os: "macosx",
             target_cpu: "x64",
             dependencies: concat(common.dependencies, "devkit"),
-	    configure_args: concat(common.configure_args, "--with-zlib=system"),
-            make_args: common.make_args
+            configure_args: concat(common.configure_args, "--with-zlib=system"),
+            default_make_targets: common.default_make_targets
         },
 
         "solaris-x64": {
             target_os: "solaris",
             target_cpu: "x64",
             dependencies: concat(common.dependencies, "devkit", "cups"),
-	    configure_args: concat(common.configure_args, "--with-zlib=system"),
-            make_args: common.make_args
+            configure_args: concat(common.configure_args, "--with-zlib=system"),
+            default_make_targets: common.default_make_targets
         },
 
         "solaris-sparcv9": {
             target_os: "solaris",
             target_cpu: "sparcv9",
             dependencies: concat(common.dependencies, "devkit", "cups"),
-	    configure_args: concat(common.configure_args, "--with-zlib=system"),
-            make_args: common.make_args
+            configure_args: concat(common.configure_args, "--with-zlib=system"),
+            default_make_targets: common.default_make_targets
         },
 
         "windows-x64": {
             target_os: "windows",
             target_cpu: "x64",
             dependencies: concat(common.dependencies, "devkit", "freetype"),
-            configure_args: common.configure_args,
-            make_args: common.make_args
+            configure_args: concat(common.configure_args),
+            default_make_targets: common.default_make_targets
         },
 
         "windows-x86": {
@@ -293,7 +296,7 @@
             build_cpu: "x64",
             dependencies: concat(common.dependencies, "devkit", "freetype"),
             configure_args: concat(common.configure_args, common.configure_args_32bit),
-            make_args: common.make_args
+            default_make_targets: common.default_make_targets
         }
     };
     profiles = concatObjects(profiles, mainProfiles);
@@ -306,14 +309,15 @@
     // implementation builds.
     var openOnlyProfiles = generateOpenOnlyProfiles(common, mainProfiles);
     // The open only profiles on linux are used for reference builds and should
-    // produce the compact profile images by default.
+    // produce the compact profile images by default. This adds "profiles" as an
+    // extra default target.
     var openOnlyProfilesExtra = {
         "linux-x64-open": {
-            configure_args: ["--with-default-make-target=all profiles"],
+            default_make_targets: "profiles"
         },
 
         "linux-x86-open": {
-            configure_args: ["--with-default-make-target=all profiles"],
+            default_make_targets: "profiles"
         }
     };
     var openOnlyProfiles = concatObjects(openOnlyProfiles, openOnlyProfilesExtra);
@@ -336,6 +340,7 @@
 
     // Generate the missing platform attributes
     profiles = generatePlatformAttributes(profiles);
+    profiles = generateDefaultMakeTargetsConfigureArg(common, profiles);
     return profiles;
 };
 
@@ -469,6 +474,8 @@
         var debugProfile = profile + "-debug";
         newProfiles[debugProfile] = clone(profiles[profile]);
         newProfiles[debugProfile].debug_level = "fastdebug";
+        newProfiles[debugProfile].default_make_targets
+            = common.default_make_targets_debug;
         newProfiles[debugProfile].labels
             = concat(newProfiles[debugProfile].labels || [], "debug"),
             newProfiles[debugProfile].configure_args
@@ -492,6 +499,8 @@
         var debugProfile = profile + "-slowdebug";
         newProfiles[debugProfile] = clone(profiles[profile]);
         newProfiles[debugProfile].debug_level = "slowdebug";
+        newProfiles[debugProfile].default_make_targets
+            = common.default_make_targets_slowdebug;
         newProfiles[debugProfile].labels
             = concat(newProfiles[debugProfile].labels || [], "slowdebug"),
             newProfiles[debugProfile].configure_args
@@ -524,6 +533,39 @@
 };
 
 /**
+ * The default_make_targets attribute on a profile is not a real Jib attribute.
+ * This function rewrites that attribute into the corresponding configure arg.
+ * Calling this function multiple times on the same profiles object is safe.
+ *
+ * @param common Common values
+ * @param profiles Profiles map to rewrite profiles for
+ * @returns {{}} New map of profiles with the make targets converted
+ */
+var generateDefaultMakeTargetsConfigureArg = function (common, profiles) {
+    var ret = concatObjects(profiles, {});
+    for (var profile in ret) {
+        if (ret[profile]["default_make_targets"] != null) {
+            var targetsString = concat(ret[profile].default_make_targets).join(" ");
+            // Iterate over all configure args and see if --with-default-make-target
+            // is already there and change it, otherwise add it.
+            var found = false;
+            for (var arg in ret[profile].configure_args) {
+                if (arg.startsWith("--with-default-make-target")) {
+                    found = true;
+                    arg.replace(/=.*/, "=" + targetsString);
+                }
+            }
+            if (!found) {
+                ret[profile].configure_args = concat(
+                    ret[profile].configure_args,
+                    "--with-default-make-target=" + targetsString);
+            }
+        }
+    }
+    return ret;
+}
+
+/**
  * Deep clones an object tree.
  *
  * @param o Object to clone
--- a/corba/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/corba/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -358,3 +358,4 @@
 cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113
 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114
 7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115
+7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116
--- a/hotspot/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/hotspot/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -518,3 +518,4 @@
 c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113
 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114
 88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115
+61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116
--- a/jaxp/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/jaxp/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -358,3 +358,4 @@
 28626780e245fccbfb9bad8e3b05f62357958038 jdk-9+113
 147114dd0641cd7c9fe6e81642eb993a7b9c6f0b jdk-9+114
 1902a5bda18e794b31fc5f520f5e7d827714b50d jdk-9+115
+9d71d20e614777cd23c1a43b38b5c08a9094d27a jdk-9+116
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Wed Jul 05 21:39:33 2017 +0200
@@ -444,13 +444,15 @@
                 }
             } else if (index == Feature.FILES.ordinal()) {
                 try {
-                    if (Util.verifyAndGetURI(value, null) == null) {
-                        CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
+                    String[] catalogFile = value.split(";[ ]*");
+                    for (String temp : catalogFile) {
+                        if (Util.verifyAndGetURI(temp, null) == null) {
+                            CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
+                        }
                     }
                 }catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) {
                     CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex);
                 }
-
             }
             if (states[index] == null || state.compareTo(states[index]) >= 0) {
                 values[index] = value;
--- a/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java	Wed Jul 05 21:39:33 2017 +0200
@@ -91,6 +91,7 @@
         permissions.add(new PropertyPermission("line.separator", "read"));
         permissions.add(new PropertyPermission("fileStringBuffer", "read"));
         permissions.add(new PropertyPermission("dataproviderthreadcount", "read"));
+        permissions.add(new RuntimePermission("charsetProvider"));
     }
 
     /*
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 package catalog;
 
 import java.io.IOException;
+import java.nio.file.Paths;
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogException;
 import javax.xml.catalog.CatalogFeatures;
@@ -34,6 +35,7 @@
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 import org.xml.sax.Attributes;
@@ -44,10 +46,49 @@
 import org.xml.sax.ext.DefaultHandler2;
 
 /*
- * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527
+ * @bug 8081248, 8144966, 8146606, 8146237, 8151154, 8150969, 8151162, 8152527, 8154220
  * @summary Tests basic Catalog functions.
  */
 public class CatalogTest {
+    static final String KEY_FILES = "javax.xml.catalog.files";
+
+    public String filepath;
+
+    /*
+     * Initializing fields
+     */
+    @BeforeClass
+    public void setUpClass() throws Exception {
+        String file1 = getClass().getResource("first_cat.xml").getFile();
+        if (System.getProperty("os.name").contains("Windows")) {
+            filepath = file1.substring(1, file1.lastIndexOf("/") + 1);
+        } else {
+            filepath = file1.substring(0, file1.lastIndexOf("/") + 1);
+        }
+    }
+
+    /*
+     * @bug 8154220
+     * Verifies that the file input is validated properly. Valid input includes
+     * multiple file paths separated by semicolon.
+     */
+    @Test(dataProvider = "hierarchyOfCatFilesData")
+    public void hierarchyOfCatFiles2(String systemId, String expectedUri) {
+        String file1 = getClass().getResource("first_cat.xml").getFile();
+        String file2 = getClass().getResource("second_cat.xml").getFile();
+        String files = file1 + ";" + file2;
+
+        try {
+            System.setProperty(KEY_FILES, files);
+            CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults());
+            String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId();
+            Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), "System ID match not right");
+        } finally {
+            System.clearProperty(KEY_FILES);
+        }
+
+    }
+
     /*
      * @bug 8152527
      * This test is the same as the JDK test ResolveEntityTests:testMatch1.
@@ -289,6 +330,19 @@
     }
 
     /*
+        DataProvider: used to verify hierarchical catalogs. Refer to JCK test
+    hierarchyOfCatFiles2.
+     */
+    @DataProvider(name = "hierarchyOfCatFilesData")
+    Object[][] getHierarchyOfCatFilesData() {
+        return new Object[][]{
+            {"http://www.oracle.com/sequence.dtd", "first.dtd"},
+            {"http://www.oracle.com/sequence_next.dtd", "next.dtd"},
+            {"http://www.oracle.com/sequence_second.dtd", "second.dtd"}
+        };
+    }
+
+    /*
         DataProvider: used to verify CatalogResolver's resolveEntity function.
         Data columns:
         catalog, prefer, systemId, publicId, expectedUri, expectedFile, msg
@@ -300,6 +354,7 @@
             {"rewriteSystem_id.xml", "system", "http://www.sys00test.com/rewrite.dtd", "PUB-404", expected, expected, "Relative rewriteSystem with xml:base at group level failed"},
         };
     }
+
     static String id = "http://openjdk.java.net/xml/catalog/dtd/system.dtd";
     /*
        DataProvider: used to verify how prefer settings affect the result of the
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/first_cat.xml	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,6 @@
+<catalog prefer="system" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+    <system systemId="http://www.oracle.com/sequence.dtd" uri="first.dtd"/>
+    <nextCatalog catalog="next_cat.xml"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/next_cat.xml	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,6 @@
+<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+    <system systemId="http://www.oracle.com/sequence.dtd" uri="next.dtd"/>
+    <system systemId="http://www.oracle.com/sequence_next.dtd" uri="next.dtd"/>
+
+</catalog>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/second_cat.xml	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,7 @@
+<catalog prefer="public" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+
+    <system systemId="http://www.oracle.com/sequence.dtd" uri="second.dtd"/>
+    <system systemId="http://www.oracle.com/sequence_next.dtd" uri="second.dtd"/>
+    <system systemId="http://www.oracle.com/sequence_second.dtd" uri="second.dtd"/>
+
+</catalog>
\ No newline at end of file
--- a/jaxws/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/jaxws/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -361,3 +361,4 @@
 e980062475c10d21137051045bf95ee229db9b27 jdk-9+113
 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114
 4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115
+529f0bf896e58525614d863e283ad155531941cb jdk-9+116
--- a/jdk/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -358,3 +358,4 @@
 68f8be44b6a6b33dfa841ec671c0ba6e4056b372 jdk-9+113
 bb8379287f3736f38c52b2d1418784e2592461d1 jdk-9+114
 35225b837d66582037eeadeb471c13235dfd793d jdk-9+115
+baeb5edb38939cdb78ae0ac6f4fd368465cbf188 jdk-9+116
--- a/jdk/make/gendata/Gendata-java.base.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/gendata/Gendata-java.base.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2014, 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
@@ -41,7 +41,7 @@
 GENDATA_UNINAME := $(JDK_OUTPUTDIR)/modules/java.base/java/lang/uniName.dat
 
 $(GENDATA_UNINAME): $(JDK_TOPDIR)/make/data/unicodedata/UnicodeData.txt $(BUILD_TOOLS_JDK)
-	$(MKDIR) -p $(@D)
+	$(call MakeDir, $(@D))
 	$(TOOL_CHARACTERNAME) $< $@
 
 TARGETS += $(GENDATA_UNINAME)
@@ -51,7 +51,7 @@
 GENDATA_CURDATA := $(JDK_OUTPUTDIR)/modules/java.base/java/util/currency.data
 
 $(GENDATA_CURDATA): $(JDK_TOPDIR)/make/data/currency/CurrencyData.properties $(BUILD_TOOLS_JDK)
-	$(MKDIR) -p $(@D)
+	$(call MakeDir, $(@D))
 	$(RM) $@
 	$(TOOL_GENERATECURRENCYDATA) -o $@.tmp < $<
 	$(MV) $@.tmp $@
@@ -67,10 +67,10 @@
 # RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile
 
 $(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC)
-	$(ECHO) "Generating java.security"
-	$(MKDIR) -p $(@D)
+	$(call LogInfo, Generating java.security)
+	$(call MakeDir, $(@D))
 	$(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \
-		$(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC) || exit 1
+	    $(OPENJDK_TARGET_CPU_ARCH) $(RESTRICTED_PKGS_SRC)
 
 TARGETS += $(GENDATA_JAVA_SECURITY)
 
@@ -78,7 +78,7 @@
 
 $(SUPPORT_OUTPUTDIR)/modules_libs/java.base/classlist: \
     $(JDK_TOPDIR)/make/data/classlist/classlist.$(OPENJDK_TARGET_OS)
-	$(MKDIR) -p $(@D)
+	$(call MakeDir, $(@D))
 	$(RM) $@ $@.tmp
 	$(TOOL_ADDJSUM) $< $@.tmp
 	$(MV) $@.tmp $@
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/launcher/Launcher-jdk.jstatd.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,30 @@
+#
+# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.  Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include LauncherCommon.gmk
+
+$(eval $(call SetupBuildLauncher, jstatd, \
+    MAIN_CLASS := sun.tools.jstatd.Jstatd, \
+))
--- a/jdk/make/launcher/Launcher-jdk.jvmstat.rmi.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-#
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License version 2 only, as
-# published by the Free Software Foundation.  Oracle designates this
-# particular file as subject to the "Classpath" exception as provided
-# by Oracle in the LICENSE file that accompanied this code.
-#
-# This code is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-# version 2 for more details (a copy is included in the LICENSE file that
-# accompanied this code).
-#
-# You should have received a copy of the GNU General Public License version
-# 2 along with this work; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
-# or visit www.oracle.com if you need additional information or have any
-# questions.
-#
-
-include LauncherCommon.gmk
-
-$(eval $(call SetupBuildLauncher, jstatd, \
-    MAIN_CLASS := sun.tools.jstatd.Jstatd, \
-))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/Lib-jdk.net.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+#
+
+include LibCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+
+  $(eval $(call SetupNativeCompilation, BUILD_LIBEXTNET, \
+      LIBRARY := extnet, \
+      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+      SRC := $(JDK_TOPDIR)/src/jdk.net/solaris/native/libextnet, \
+      OPTIMIZATION := LOW, \
+      CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.net, \
+      MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libextnet/mapfile-vers, \
+      LDFLAGS := $(LDFLAGS_JDKLIB) \
+          $(call SET_SHARED_LIBRARY_ORIGIN), \
+      LIBS := -lsocket -lc -ljava, \
+      OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libextnet, \
+  ))
+
+  $(BUILD_LIBEXTNET): $(call FindLib, java.base, java)
+
+  TARGETS += $(BUILD_LIBEXTNET)
+endif
+
+
+################################################################################
--- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers	Wed Jul 05 21:39:33 2017 +0200
@@ -179,6 +179,7 @@
         Java_sun_awt_UNIXToolkit_load_1gtk_1icon;
         Java_sun_awt_UNIXToolkit_nativeSync;
         Java_sun_awt_UNIXToolkit_gtkCheckVersionImpl;
+        Java_sun_awt_UNIXToolkit_get_1gtk_1version;
         Java_java_awt_AWTEvent_initIDs;
         Java_java_awt_event_InputEvent_initIDs;
         Java_java_awt_event_KeyEvent_initIDs;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/mapfiles/libextnet/mapfile-vers	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+#
+
+SUNWprivate_1.1 {
+	global:
+	    Java_jdk_net_SolarisSocketOptions_init;
+	    Java_jdk_net_SolarisSocketOptions_setFlowOption;
+	    Java_jdk_net_SolarisSocketOptions_getFlowOption;
+	    Java_jdk_net_SolarisSocketOptions_flowSupported;
+	local:
+	    *;
+};
--- a/jdk/make/mapfiles/libnet/mapfile-vers	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/mapfiles/libnet/mapfile-vers	Wed Jul 05 21:39:33 2017 +0200
@@ -98,10 +98,6 @@
 		Java_sun_net_sdp_SdpSupport_create0;
 		Java_sun_net_spi_DefaultProxySelector_init;
 		Java_sun_net_spi_DefaultProxySelector_getSystemProxy;
-		Java_sun_net_ExtendedOptionsImpl_init;
-		Java_sun_net_ExtendedOptionsImpl_setFlowOption;
-		Java_sun_net_ExtendedOptionsImpl_getFlowOption;
-		Java_sun_net_ExtendedOptionsImpl_flowSupported;
 		NET_AllocSockaddr;
 		NET_SockaddrToInetAddress;
                 NET_SockaddrEqualsInetAddress;
--- a/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/netbeans/client_sanity/nbproject/genfiles.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -3,6 +3,6 @@
 build.xml.stylesheet.CRC32=8064a381@1.75.2.48
 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
 # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=55414227
+nbproject/build-impl.xml.data.CRC32=16caf60f
 nbproject/build-impl.xml.script.CRC32=c12f9d04
 nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.1.48
--- a/jdk/make/netbeans/client_sanity/nbproject/project.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/netbeans/client_sanity/nbproject/project.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -76,4 +76,4 @@
 src.src.dir=..\\..\\..\\test\\sanity\\client\\SwingSet\\src
 src.src2.dir=..\\..\\..\\test\\sanity\\client\\lib\\SwingSet3\\src
 src.src3.dir=..\\..\\..\\test\\sanity\\client\\lib\\jemmy\\src
-src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Jemmy2Ext\\src
+src.src4.dir=..\\..\\..\\test\\sanity\\client\\lib\\Extensions\\src
--- a/jdk/make/netbeans/client_sanity/nbproject/project.xml	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/netbeans/client_sanity/nbproject/project.xml	Wed Jul 05 21:39:33 2017 +0200
@@ -6,7 +6,7 @@
             <name>SanityTests</name>
             <source-roots>
                 <root id="src.src3.dir" name="lib\jemmy\src"/>
-                <root id="src.src4.dir" name="lib\Jemmy2Ext\src"/>
+                <root id="src.src4.dir" name="lib\Extensions\src"/>
                 <root id="src.src2.dir" name="lib\SwingSet3\src"/>
                 <root id="src.src.dir" name="SwingSet\src"/>
             </source-roots>
--- a/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java	Wed Jul 05 21:39:33 2017 +0200
@@ -54,13 +54,13 @@
                 return String.format("        d.put(\"%s%s\", \"%s\");\n",
                                      prefix, getName(), getValue());
             case INT:
-                return String.format("        d.put(\"%s%s\", new Integer(%s));\n",
+                return String.format("        d.put(\"%s%s\", Integer.valueOf(%s));\n",
                                      prefix, getName(), getValue());
             case FLOAT:
-                return String.format("        d.put(\"%s%s\", new Float(%sf));\n",
+                return String.format("        d.put(\"%s%s\", Float.valueOf(%sf));\n",
                                      prefix, getName(), getValue());
             case DOUBLE:
-                return String.format("        d.put(\"%s%s\", new Double(%s));\n",
+                return String.format("        d.put(\"%s%s\", Double.valueOf(%s));\n",
                                      prefix, getName(), getValue());
             case COLOR:
                 return String.format("        addColor(d, \"%s%s\", %s);\n",
--- a/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/make/src/classes/build/tools/module/GenModuleInfoSource.java	Wed Jul 05 21:39:33 2017 +0200
@@ -52,7 +52,7 @@
         "Usage: GenModuleInfoSource [option] -o <output file> <module-info-java>\n" +
         "Options are:\n" +
         "  -exports  <package-name>\n" +
-        "  -exports  <package-name>/<module-name>\n" +
+        "  -exports  <package-name>[/<module-name>]\n" +
         "  -uses     <service>\n" +
         "  -provides <service>/<provider-impl-classname>\n";
 
--- a/jdk/src/java.base/share/classes/java/lang/String.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/String.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2015, 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
@@ -78,14 +78,8 @@
  * <p>
  * The Java language provides special support for the string
  * concatenation operator (&nbsp;+&nbsp;), and for conversion of
- * other objects to strings. String concatenation is implemented
- * through the {@code StringBuilder}(or {@code StringBuffer})
- * class and its {@code append} method.
- * String conversions are implemented through the method
- * {@code toString}, defined by {@code Object} and
- * inherited by all classes in Java. For additional information on
- * string concatenation and conversion, see Gosling, Joy, and Steele,
- * <i>The Java Language Specification</i>.
+ * other objects to strings. For additional information on string
+ * concatenation and conversion, see <i>The Java&trade; Language Specification</i>.
  *
  * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
  * or method in this class will cause a {@link NullPointerException} to be
@@ -106,6 +100,14 @@
  * into account.  The {@link java.text.Collator} class provides methods for
  * finer-grain, locale-sensitive String comparison.
  *
+ * @implNote The implementation of the string concatenation operator is left to
+ * the discretion of a Java compiler, as long as the compiler ultimately conforms
+ * to <i>The Java&trade; Language Specification</i>. For example, the {@code javac} compiler
+ * may implement the operator with {@code StringBuffer}, {@code StringBuilder},
+ * or {@code java.lang.invoke.StringConcatFactory} depending on the JDK version. The
+ * implementation of string conversion is typically through the method {@code toString},
+ * defined by {@code Object} and inherited by all classes in Java.
+ *
  * @author  Lee Boynton
  * @author  Arthur van Hoff
  * @author  Martin Buchholz
@@ -115,6 +117,7 @@
  * @see     java.lang.StringBuilder
  * @see     java.nio.charset.Charset
  * @since   1.0
+ * @jls     15.18.1 String Concatenation Operator +
  */
 
 public final class String
@@ -2977,6 +2980,7 @@
      *
      * @return  a string that has the same contents as this string, but is
      *          guaranteed to be from a pool of unique strings.
+     * @jls 3.10.5 String Literals
      */
     public native String intern();
 
--- a/jdk/src/java.base/share/classes/java/lang/System.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/System.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1155,8 +1155,9 @@
          * @param level the log message level.
          * @param msg the string message (or a key in the message catalog, if
          * this logger is a {@link
-         * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class)
-         * localized logger}); can be {@code null}.
+         * LoggerFinder#getLocalizedLogger(java.lang.String,
+         * java.util.ResourceBundle, java.lang.reflect.Module) localized logger});
+         * can be {@code null}.
          *
          * @throws NullPointerException if {@code level} is {@code null}.
          */
@@ -1222,8 +1223,9 @@
          * @param level the log message level.
          * @param msg the string message (or a key in the message catalog, if
          * this logger is a {@link
-         * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class)
-         * localized logger}); can be {@code null}.
+         * LoggerFinder#getLocalizedLogger(java.lang.String,
+         * java.util.ResourceBundle, java.lang.reflect.Module) localized logger});
+         * can be {@code null}.
          * @param thrown a {@code Throwable} associated with the log message;
          *        can be {@code null}.
          *
@@ -1270,8 +1272,9 @@
          * @param format the string message format in {@link
          * java.text.MessageFormat} format, (or a key in the message
          * catalog, if this logger is a {@link
-         * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class)
-         * localized logger}); can be {@code null}.
+         * LoggerFinder#getLocalizedLogger(java.lang.String,
+         * java.util.ResourceBundle, java.lang.reflect.Module) localized logger});
+         * can be {@code null}.
          * @param params an optional list of parameters to the message (may be
          * none).
          *
@@ -1453,30 +1456,30 @@
 
         /**
          * Returns an instance of {@link Logger Logger}
-         * for the given {@code caller}.
+         * for the given {@code module}.
          *
          * @param name the name of the logger.
-         * @param caller the class for which the logger is being requested.
+         * @param module the module for which the logger is being requested.
          *
-         * @return a {@link Logger logger} suitable for the given caller's
-         *         use.
+         * @return a {@link Logger logger} suitable for use within the given
+         *         module.
          * @throws NullPointerException if {@code name} is {@code null} or
-         *        {@code caller} is {@code null}.
+         *        {@code module} is {@code null}.
          * @throws SecurityException if a security manager is present and its
          *         {@code checkPermission} method doesn't allow the
          *         {@code RuntimePermission("loggerFinder")}.
          */
-        public abstract Logger getLogger(String name, /* Module */ Class<?> caller);
+        public abstract Logger getLogger(String name, Module module);
 
         /**
          * Returns a localizable instance of {@link Logger Logger}
-         * for the given {@code caller}.
+         * for the given {@code module}.
          * The returned logger will use the provided resource bundle for
          * message localization.
          *
          * @implSpec By default, this method calls {@link
-         * #getLogger(java.lang.String, java.lang.Class)
-         * this.getLogger(name, caller)} to obtain a logger, then wraps that
+         * #getLogger(java.lang.String, java.lang.reflect.Module)
+         * this.getLogger(name, module)} to obtain a logger, then wraps that
          * logger in a {@link Logger} instance where all methods that do not
          * take a {@link ResourceBundle} as parameter are redirected to one
          * which does - passing the given {@code bundle} for
@@ -1499,19 +1502,19 @@
          *
          * @param name    the name of the logger.
          * @param bundle  a resource bundle; can be {@code null}.
-         * @param caller the class for which the logger is being requested.
+         * @param module  the module for which the logger is being requested.
          * @return an instance of {@link Logger Logger}  which will use the
          * provided resource bundle for message localization.
          *
          * @throws NullPointerException if {@code name} is {@code null} or
-         *         {@code caller} is {@code null}.
+         *         {@code module} is {@code null}.
          * @throws SecurityException if a security manager is present and its
          *         {@code checkPermission} method doesn't allow the
          *         {@code RuntimePermission("loggerFinder")}.
          */
         public Logger getLocalizedLogger(String name, ResourceBundle bundle,
-                                          /* Module */ Class<?> caller) {
-            return new LocalizedLoggerWrapper<>(getLogger(name, caller), bundle);
+                                         Module module) {
+            return new LocalizedLoggerWrapper<>(getLogger(name, module), bundle);
         }
 
         /**
@@ -1558,12 +1561,13 @@
      *
      * @implSpec
      * Instances returned by this method route messages to loggers
-     * obtained by calling {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class)
-     * LoggerFinder.getLogger(name, caller)}.
+     * obtained by calling {@link LoggerFinder#getLogger(java.lang.String,
+     * java.lang.reflect.Module) LoggerFinder.getLogger(name, module)}, where
+     * {@code module} is the caller's module.
      *
      * @apiNote
      * This method may defer calling the {@link
-     * LoggerFinder#getLogger(java.lang.String, java.lang.Class)
+     * LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module)
      * LoggerFinder.getLogger} method to create an actual logger supplied by
      * the logging backend, for instance, to allow loggers to be obtained during
      * the system initialization time.
@@ -1579,7 +1583,7 @@
     public static Logger getLogger(String name) {
         Objects.requireNonNull(name);
         final Class<?> caller = Reflection.getCallerClass();
-        return LazyLoggers.getLogger(name, caller);
+        return LazyLoggers.getLogger(name, caller.getModule());
     }
 
     /**
@@ -1591,8 +1595,9 @@
      * @implSpec
      * The returned logger will perform message localization as specified
      * by {@link LoggerFinder#getLocalizedLogger(java.lang.String,
-     * java.util.ResourceBundle, java.lang.Class)
-     * LoggerFinder.getLocalizedLogger(name, bundle, caller}.
+     * java.util.ResourceBundle, java.lang.reflect.Module)
+     * LoggerFinder.getLocalizedLogger(name, bundle, module}, where
+     * {@code module} is the caller's module.
      *
      * @apiNote
      * This method is intended to be used after the system is fully initialized.
@@ -1624,12 +1629,14 @@
         // Bootstrap sensitive classes in the JDK do not use resource bundles
         // when logging. This could be revisited later, if it needs to.
         if (sm != null) {
-            return AccessController.doPrivileged((PrivilegedAction<Logger>)
-                    () -> LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller),
-                    null,
-                    LoggerFinder.LOGGERFINDER_PERMISSION);
+            final PrivilegedAction<Logger> pa =
+                    () -> LoggerFinder.accessProvider()
+                            .getLocalizedLogger(name, rb, caller.getModule());
+            return AccessController.doPrivileged(pa, null,
+                                         LoggerFinder.LOGGERFINDER_PERMISSION);
         }
-        return LoggerFinder.accessProvider().getLocalizedLogger(name, rb, caller);
+        return LoggerFinder.accessProvider()
+                .getLocalizedLogger(name, rb, caller.getModule());
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -25,6 +25,7 @@
 
 package java.lang.invoke;
 
+import java.lang.reflect.Array;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
@@ -1892,7 +1893,8 @@
             MH_tryFinallyExec        = 12,
             MH_tryFinallyVoidExec    = 13,
             MH_decrementCounter      = 14,
-            MH_LIMIT                 = 15;
+            MH_Array_newInstance     = 15,
+            MH_LIMIT                 = 16;
 
     static MethodHandle getConstantHandle(int idx) {
         MethodHandle handle = HANDLES[idx];
@@ -1965,6 +1967,9 @@
                 case MH_decrementCounter:
                     return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, "decrementCounter",
                             MethodType.methodType(int.class, int.class));
+                case MH_Array_newInstance:
+                    return IMPL_LOOKUP.findStatic(Array.class, "newInstance",
+                            MethodType.methodType(Object.class, Class.class, int.class));
             }
         } catch (ReflectiveOperationException ex) {
             throw newInternalError(ex);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Wed Jul 05 21:39:33 2017 +0200
@@ -25,34 +25,38 @@
 
 package java.lang.invoke;
 
-import java.lang.reflect.*;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.reflect.CallerSensitive;
+import jdk.internal.reflect.Reflection;
+import sun.invoke.util.ValueConversions;
+import sun.invoke.util.VerifyAccess;
+import sun.invoke.util.Wrapper;
+import sun.reflect.misc.ReflectUtil;
+import sun.security.util.SecurityConstants;
+
+import java.lang.invoke.LambdaForm.BasicType;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ReflectPermission;
+import java.nio.ByteOrder;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Arrays;
 import java.util.Objects;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import sun.invoke.util.ValueConversions;
-import sun.invoke.util.VerifyAccess;
-import sun.invoke.util.Wrapper;
-import jdk.internal.reflect.CallerSensitive;
-import jdk.internal.reflect.Reflection;
-import sun.reflect.misc.ReflectUtil;
-import sun.security.util.SecurityConstants;
-import java.lang.invoke.LambdaForm.BasicType;
-
-import static java.lang.invoke.MethodHandleImpl.Intrinsic;
-import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
+import static java.lang.invoke.MethodHandleImpl.Intrinsic;
+import static java.lang.invoke.MethodHandleNatives.Constants.*;
 import static java.lang.invoke.MethodHandleStatics.newIllegalArgumentException;
 import static java.lang.invoke.MethodType.methodType;
 
@@ -741,10 +745,13 @@
             if (name.startsWith("java.lang.invoke."))
                 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
 
-            // For caller-sensitive MethodHandles.lookup()
-            // disallow lookup more restricted packages
+            // For caller-sensitive MethodHandles.lookup() disallow lookup from
+            // restricted packages.  This a fragile and blunt approach.
+            // TODO replace with a more formal and less fragile mechanism
+            // that does not bluntly restrict classes under packages within
+            // java.base from looking up MethodHandles or VarHandles.
             if (allowedModes == ALL_MODES && lookupClass.getClassLoader() == null) {
-                if (name.startsWith("java.") ||
+                if ((name.startsWith("java.") && !name.startsWith("java.util.concurrent.")) ||
                         (name.startsWith("sun.") && !name.startsWith("sun.invoke."))) {
                     throw newIllegalArgumentException("illegal lookupClass: " + lookupClass);
                 }
@@ -1003,6 +1010,9 @@
          * @throws NullPointerException if any argument is null
          */
         public MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException {
+            if (refc.isArray()) {
+                throw new NoSuchMethodException("no constructor for array class: " + refc.getName());
+            }
             String name = "<init>";
             MemberName ctor = resolveOrFail(REF_newInvokeSpecial, refc, name, type);
             return getDirectConstructor(refc, ctor);
@@ -2214,6 +2224,27 @@
     }
 
     /**
+     * Produces a method handle constructing arrays of a desired type.
+     * The return type of the method handle will be the array type.
+     * The type of its sole argument will be {@code int}, which specifies the size of the array.
+     * @param arrayClass an array type
+     * @return a method handle which can create arrays of the given type
+     * @throws NullPointerException if the argument is {@code null}
+     * @throws IllegalArgumentException if {@code arrayClass} is not an array type
+     * @see java.lang.reflect.Array#newInstance(Class, int)
+     * @since 9
+     */
+    public static
+    MethodHandle arrayConstructor(Class<?> arrayClass) throws IllegalArgumentException {
+        if (!arrayClass.isArray()) {
+            throw newIllegalArgumentException("not an array class: " + arrayClass.getName());
+        }
+        MethodHandle ani = MethodHandleImpl.getConstantHandle(MethodHandleImpl.MH_Array_newInstance).
+                bindTo(arrayClass.getComponentType());
+        return ani.asType(ani.type().changeReturnType(arrayClass));
+    }
+
+    /**
      * Produces a method handle giving read access to elements of an array.
      * The type of the method handle will have a return type of the array's
      * element type.  Its first argument will be the array type,
@@ -2337,13 +2368,12 @@
      *
      * @param viewArrayClass the view array class, with a component type of
      * type {@code T}
-     * @param bigEndian true if the endianness of the view array elements, as
-     * stored in the underlying {@code byte} array, is big endian, otherwise
-     * little endian
+     * @param byteOrder the endianness of the view array elements, as
+     * stored in the underlying {@code byte} array
      * @return a VarHandle giving access to elements of a {@code byte[]} array
      * viewed as if elements corresponding to the components type of the view
      * array class
-     * @throws NullPointerException if viewArrayClass is null
+     * @throws NullPointerException if viewArrayClass or byteOrder is null
      * @throws IllegalArgumentException if viewArrayClass is not an array type
      * @throws UnsupportedOperationException if the component type of
      * viewArrayClass is not supported as a variable type
@@ -2351,8 +2381,10 @@
      */
     public static
     VarHandle byteArrayViewVarHandle(Class<?> viewArrayClass,
-                                     boolean bigEndian) throws IllegalArgumentException {
-        return VarHandles.byteArrayViewHandle(viewArrayClass, bigEndian);
+                                     ByteOrder byteOrder) throws IllegalArgumentException {
+        Objects.requireNonNull(byteOrder);
+        return VarHandles.byteArrayViewHandle(viewArrayClass,
+                                              byteOrder == ByteOrder.BIG_ENDIAN);
     }
 
     /**
@@ -2422,14 +2454,13 @@
      *
      * @param viewArrayClass the view array class, with a component type of
      * type {@code T}
-     * @param bigEndian true if the endianness of the view array elements, as
-     * stored in the underlying {@code ByteBuffer}, is big endian, otherwise
-     * little endian (Note this overrides the endianness of a
-     * {@code ByteBuffer})
+     * @param byteOrder the endianness of the view array elements, as
+     * stored in the underlying {@code ByteBuffer} (Note this overrides the
+     * endianness of a {@code ByteBuffer})
      * @return a VarHandle giving access to elements of a {@code ByteBuffer}
      * viewed as if elements corresponding to the components type of the view
      * array class
-     * @throws NullPointerException if viewArrayClass is null
+     * @throws NullPointerException if viewArrayClass or byteOrder is null
      * @throws IllegalArgumentException if viewArrayClass is not an array type
      * @throws UnsupportedOperationException if the component type of
      * viewArrayClass is not supported as a variable type
@@ -2437,8 +2468,10 @@
      */
     public static
     VarHandle byteBufferViewVarHandle(Class<?> viewArrayClass,
-                                      boolean bigEndian) throws IllegalArgumentException {
-        return VarHandles.makeByteBufferViewHandle(viewArrayClass, bigEndian);
+                                      ByteOrder byteOrder) throws IllegalArgumentException {
+        Objects.requireNonNull(byteOrder);
+        return VarHandles.makeByteBufferViewHandle(viewArrayClass,
+                                                   byteOrder == ByteOrder.BIG_ENDIAN);
     }
 
 
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java	Wed Jul 05 21:39:33 2017 +0200
@@ -123,7 +123,7 @@
      * Concatenation strategy to use. See {@link Strategy} for possible options.
      * This option is controllable with -Djava.lang.invoke.stringConcat JDK option.
      */
-    private static final Strategy STRATEGY;
+    private static Strategy STRATEGY;
 
     /**
      * Default strategy to use for concatenation.
@@ -187,6 +187,16 @@
     private static final ProxyClassesDumper DUMPER;
 
     static {
+        // In case we need to double-back onto the StringConcatFactory during this
+        // static initialization, make sure we have the reasonable defaults to complete
+        // the static initialization properly. After that, actual users would use the
+        // the proper values we have read from the the properties.
+        STRATEGY = DEFAULT_STRATEGY;
+        // CACHE_ENABLE = false; // implied
+        // CACHE = null;         // implied
+        // DEBUG = false;        // implied
+        // DUMPER = null;        // implied
+
         Properties props = GetPropertyAction.getProperties();
         final String strategy =
                 props.getProperty("java.lang.invoke.stringConcat");
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java	Wed Jul 05 21:39:33 2017 +0200
@@ -136,6 +136,7 @@
  * consists of the methods
  * {@link #compareAndSet compareAndSet},
  * {@link #weakCompareAndSet weakCompareAndSet},
+ * {@link #weakCompareAndSetVolatile weakCompareAndSetVolatile},
  * {@link #weakCompareAndSetAcquire weakCompareAndSetAcquire},
  * {@link #weakCompareAndSetRelease weakCompareAndSetRelease},
  * {@link #compareAndExchangeAcquire compareAndExchangeAcquire},
@@ -458,7 +459,7 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code get}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.get)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET)} on this VarHandle.
      *
      * <p>This access mode is supported by all VarHandle instances and never
      * throws {@code UnsupportedOperationException}.
@@ -488,7 +489,7 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code set}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.set)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.SET)} on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T newValue)}
@@ -516,7 +517,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code getVolatile}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.getVolatile)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET_VOLATILE)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT)}
@@ -544,7 +546,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code setVolatile}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.setVolatile)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.SET_VOLATILE)} on this
+     * VarHandle.
      *
      * @apiNote
      * Ignoring the many semantic differences from C and C++, this method has
@@ -574,7 +577,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code getOpaque}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.getOpaque)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET_OPAQUE)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT)}
@@ -603,7 +607,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code setOpaque}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.setOpaque)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.SET_OPAQUE)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T newValue)}
@@ -631,7 +636,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code getAcquire}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.getAcquire)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET_ACQUIRE)} on this
+     * VarHandle.
      *
      * @apiNote
      * Ignoring the many semantic differences from C and C++, this method has
@@ -664,7 +670,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code setRelease}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.setRelease)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.SET_RELEASE)} on this
+     * VarHandle.
      *
      * @apiNote
      * Ignoring the many semantic differences from C and C++, this method has
@@ -700,7 +707,7 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code
      * compareAndSet} must match the access mode type that is the result of
-     * calling {@code accessModeType(VarHandle.AccessMode.compareAndSet)} on
+     * calling {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_SET)} on
      * this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
@@ -734,7 +741,7 @@
      * <p>The symbolic type descriptor at the call site of {@code
      * compareAndExchangeVolatile}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeVolatile)}
+     * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_VOLATILE)}
      * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
@@ -769,7 +776,7 @@
      * <p>The symbolic type descriptor at the call site of {@code
      * compareAndExchangeAcquire}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeAcquire)} on
+     * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE)} on
      * this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
@@ -804,7 +811,8 @@
      * <p>The symbolic type descriptor at the call site of {@code
      * compareAndExchangeRelease}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.compareAndExchangeRelease)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE)}
+     * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T expectedValue, T newValue)}
@@ -836,14 +844,14 @@
      * {@link #get}.
      *
      * <p>This operation may fail spuriously (typically, due to memory
-     * contention) even if the current value does match the expected value.
+     * contention) even if the witness value does match the expected value.
      *
      * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
      *
      * <p>The symbolic type descriptor at the call site of {@code
      * weakCompareAndSet} must match the access mode type that is the result of
-     * calling {@code accessModeType(VarHandle.AccessMode.weakCompareAndSet)} on
-     * this VarHandle.
+     * calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET)}
+     * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T expectedValue, T newValue)}
@@ -867,20 +875,58 @@
 
     /**
      * Possibly atomically sets the value of a variable to the {@code newValue}
+     * with the memory semantics of {@link #setVolatile} if the variable's
+     * current value, referred to as the <em>witness value</em>, {@code ==} the
+     * {@code expectedValue}, as accessed with the memory semantics of
+     * {@link #getVolatile}.
+     *
+     * <p>This operation may fail spuriously (typically, due to memory
+     * contention) even if the witness value does match the expected value.
+     *
+     * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
+     *
+     * <p>The symbolic type descriptor at the call site of {@code
+     * weakCompareAndSetVolatile} must match the access mode type that is the
+     * result of calling {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE)}
+     * on this VarHandle.
+     *
+     * @param args the signature-polymorphic parameter list of the form
+     * {@code (CT, T expectedValue, T newValue)}
+     * , statically represented using varargs.
+     * @return {@code true} if successful, otherwise {@code false} if the
+     * witness value was not the same as the {@code expectedValue} or if this
+     * operation spuriously failed.
+     * @throws UnsupportedOperationException if the access mode is unsupported
+     * for this VarHandle.
+     * @throws WrongMethodTypeException if the access mode type is not
+     * compatible with the caller's symbolic type descriptor.
+     * @throws ClassCastException if the access mode type is compatible with the
+     * caller's symbolic type descriptor, but a reference cast fails.
+     * @see #setVolatile(Object...)
+     * @see #getVolatile(Object...)
+     */
+    public final native
+    @MethodHandle.PolymorphicSignature
+    @HotSpotIntrinsicCandidate
+    boolean weakCompareAndSetVolatile(Object... args);
+
+    /**
+     * Possibly atomically sets the value of a variable to the {@code newValue}
      * with the semantics of {@link #set} if the variable's current value,
      * referred to as the <em>witness value</em>, {@code ==} the
      * {@code expectedValue}, as accessed with the memory semantics of
      * {@link #getAcquire}.
      *
      * <p>This operation may fail spuriously (typically, due to memory
-     * contention) even if the current value does match the expected value.
+     * contention) even if the witness value does match the expected value.
      *
      * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
      *
      * <p>The symbolic type descriptor at the call site of {@code
      * weakCompareAndSetAcquire}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetAcquire)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE)}
+     * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T expectedValue, T newValue)}
@@ -910,14 +956,15 @@
      * {@link #get}.
      *
      * <p>This operation may fail spuriously (typically, due to memory
-     * contention) even if the current value does match the expected value.
+     * contention) even if the witness value does match the expected value.
      *
      * <p>The method signature is of the form {@code (CT, T expectedValue, T newValue)boolean}.
      *
      * <p>The symbolic type descriptor at the call site of {@code
      * weakCompareAndSetRelease}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.weakCompareAndSetRelease)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE)}
+     * on this VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T expectedValue, T newValue)}
@@ -949,7 +996,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code getAndSet}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.getAndSet)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET_AND_SET)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T newValue)}
@@ -985,7 +1033,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code getAndAdd}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.getAndAdd)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.GET_AND_ADD)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T value)}
@@ -1017,7 +1066,8 @@
      *
      * <p>The symbolic type descriptor at the call site of {@code addAndGet}
      * must match the access mode type that is the result of calling
-     * {@code accessModeType(VarHandle.AccessMode.addAndGet)} on this VarHandle.
+     * {@code accessModeType(VarHandle.AccessMode.ADD_AND_GET)} on this
+     * VarHandle.
      *
      * @param args the signature-polymorphic parameter list of the form
      * {@code (CT, T value)}
@@ -1083,109 +1133,115 @@
          * method
          * {@link VarHandle#get VarHandle.get}
          */
-        GET("get", AccessType.GET, Object.class),   // 0
+        GET("get", AccessType.GET, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#set VarHandle.set}
          */
-        SET("set", AccessType.SET, void.class),     // 1
+        SET("set", AccessType.SET, void.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#getVolatile VarHandle.getVolatile}
          */
-        GET_VOLATILE("getVolatile", AccessType.GET, Object.class),  // 2
+        GET_VOLATILE("getVolatile", AccessType.GET, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#setVolatile VarHandle.setVolatile}
          */
-        SET_VOLATILE("setVolatile", AccessType.SET, void.class),    // 3
+        SET_VOLATILE("setVolatile", AccessType.SET, void.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#getAcquire VarHandle.getAcquire}
          */
-        GET_ACQUIRE("getAcquire", AccessType.GET, Object.class),   // 4
+        GET_ACQUIRE("getAcquire", AccessType.GET, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#setRelease VarHandle.setRelease}
          */
-        SET_RELEASE("setRelease", AccessType.SET, void.class),     // 5
+        SET_RELEASE("setRelease", AccessType.SET, void.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#getOpaque VarHandle.getOpaque}
          */
-        GET_OPAQUE("getOpaque", AccessType.GET, Object.class),    // 6
+        GET_OPAQUE("getOpaque", AccessType.GET, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#setOpaque VarHandle.setOpaque}
          */
-        SET_OPAQUE("setOpaque", AccessType.SET, void.class),      // 7
+        SET_OPAQUE("setOpaque", AccessType.SET, void.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#compareAndSet VarHandle.compareAndSet}
          */
-        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),    // 8
+        COMPARE_AND_SET("compareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#compareAndExchangeVolatile VarHandle.compareAndExchangeVolatile}
          */
-        COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class), // 9
+        COMPARE_AND_EXCHANGE_VOLATILE("compareAndExchangeVolatile", AccessType.COMPARE_AND_EXCHANGE, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#compareAndExchangeAcquire VarHandle.compareAndExchangeAcquire}
          */
-        COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class),  // 10
+        COMPARE_AND_EXCHANGE_ACQUIRE("compareAndExchangeAcquire", AccessType.COMPARE_AND_EXCHANGE, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#compareAndExchangeRelease VarHandle.compareAndExchangeRelease}
          */
-        COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class),  // 11
+        COMPARE_AND_EXCHANGE_RELEASE("compareAndExchangeRelease", AccessType.COMPARE_AND_EXCHANGE, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSet VarHandle.weakCompareAndSet}
          */
-        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),        // 12
+        WEAK_COMPARE_AND_SET("weakCompareAndSet", AccessType.COMPARE_AND_SWAP, boolean.class),
+        /**
+         * The access mode whose access is specified by the corresponding
+         * method
+         * {@link VarHandle#weakCompareAndSetVolatile VarHandle.weakCompareAndSetVolatile}
+         */
+        WEAK_COMPARE_AND_SET_VOLATILE("weakCompareAndSetVolatile", AccessType.COMPARE_AND_SWAP, boolean.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetAcquire VarHandle.weakCompareAndSetAcquire}
          */
-        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class), // 13
+        WEAK_COMPARE_AND_SET_ACQUIRE("weakCompareAndSetAcquire", AccessType.COMPARE_AND_SWAP, boolean.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#weakCompareAndSetRelease VarHandle.weakCompareAndSetRelease}
          */
-        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class), // 14
+        WEAK_COMPARE_AND_SET_RELEASE("weakCompareAndSetRelease", AccessType.COMPARE_AND_SWAP, boolean.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#getAndSet VarHandle.getAndSet}
          */
-        GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class),   // 15
+        GET_AND_SET("getAndSet", AccessType.GET_AND_UPDATE, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#getAndAdd VarHandle.getAndAdd}
          */
-        GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class),   // 16
+        GET_AND_ADD("getAndAdd", AccessType.GET_AND_UPDATE, Object.class),
         /**
          * The access mode whose access is specified by the corresponding
          * method
          * {@link VarHandle#addAndGet VarHandle.addAndGet}
          */
-        ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class),   // 17
+        ADD_AND_GET("addAndGet", AccessType.GET_AND_UPDATE, Object.class),
         ;
 
         static final Map<String, AccessMode> methodNameToAccessMode;
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -155,6 +155,15 @@
         }
 
         @ForceInline
+        static boolean weakCompareAndSetVolatile(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
+            // TODO defer to strong form until new Unsafe method is added
+            return UNSAFE.compareAndSwap$Type$(Objects.requireNonNull(handle.receiverType.cast(holder)),
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
         static boolean weakCompareAndSetAcquire(FieldInstanceReadWrite handle, Object holder, $type$ expected, $type$ value) {
             return UNSAFE.weakCompareAndSwap$Type$Acquire(Objects.requireNonNull(handle.receiverType.cast(holder)),
                                                handle.fieldOffset,
@@ -319,6 +328,15 @@
         }
 
         @ForceInline
+        static boolean weakCompareAndSetVolatile(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
+            // TODO defer to strong form until new Unsafe method is added
+            return UNSAFE.compareAndSwap$Type$(handle.base,
+                                               handle.fieldOffset,
+                                               {#if[Object]?handle.fieldType.cast(expected):expected},
+                                               {#if[Object]?handle.fieldType.cast(value):value});
+        }
+
+        @ForceInline
         static boolean weakCompareAndSetAcquire(FieldStaticReadWrite handle, $type$ expected, $type$ value) {
             return UNSAFE.weakCompareAndSwap$Type$Acquire(handle.base,
                                                handle.fieldOffset,
@@ -535,6 +553,20 @@
         }
 
         @ForceInline
+        static boolean weakCompareAndSetVolatile(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
+#if[Object]
+            Object[] array = (Object[]) handle.arrayType.cast(oarray);
+#else[Object]
+            $type$[] array = ($type$[]) oarray;
+#end[Object]
+            // TODO defer to strong form until new Unsafe method is added
+            return UNSAFE.compareAndSwap$Type$(array,
+                    (((long) Objects.checkIndex(index, array.length, AIOOBE_SUPPLIER)) << handle.ashift) + handle.abase,
+                    {#if[Object]?handle.componentType.cast(expected):expected},
+                    {#if[Object]?handle.componentType.cast(value):value});
+        }
+
+        @ForceInline
         static boolean weakCompareAndSetAcquire(Array handle, Object oarray, int index, $type$ expected, $type$ value) {
 #if[Object]
             Object[] array = (Object[]) handle.arrayType.cast(oarray);
--- a/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -228,6 +228,16 @@
         }
 
         @ForceInline
+        static boolean weakCompareAndSetVolatile(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
+            byte[] ba = (byte[]) oba;
+            // TODO defer to strong form until new Unsafe method is added
+            return UNSAFE.compareAndSwap$RawType$(
+                    ba,
+                    address(ba, index(ba, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
         static boolean weakCompareAndSetAcquire(ArrayHandle handle, Object oba, int index, $type$ expected, $type$ value) {
             byte[] ba = (byte[]) oba;
             return UNSAFE.weakCompareAndSwap$RawType$Acquire(
@@ -444,6 +454,16 @@
         }
 
         @ForceInline
+        static boolean weakCompareAndSetVolatile(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
+            ByteBuffer bb = (ByteBuffer) obb;
+            // TODO defer to strong form until new Unsafe method is added
+            return UNSAFE.compareAndSwap$RawType$(
+                    UNSAFE.getObject(bb, BYTE_BUFFER_HB),
+                    address(bb, indexRO(bb, index)),
+                    convEndian(handle.be, expected), convEndian(handle.be, value));
+        }
+
+        @ForceInline
         static boolean weakCompareAndSetAcquire(ByteBufferHandle handle, Object obb, int index, $type$ expected, $type$ value) {
             ByteBuffer bb = (ByteBuffer) obb;
             return UNSAFE.weakCompareAndSwap$RawType$Acquire(
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Arrays.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -4403,6 +4403,35 @@
         public void sort(Comparator<? super E> c) {
             Arrays.sort(a, c);
         }
+
+        @Override
+        public Iterator<E> iterator() {
+            return new ArrayItr<>(a);
+        }
+    }
+
+    private static class ArrayItr<E> implements Iterator<E> {
+        private int cursor;
+        private final E[] a;
+
+        ArrayItr(E[] a) {
+            this.a = a;
+        }
+
+        @Override
+        public boolean hasNext() {
+            return cursor < a.length;
+        }
+
+        @Override
+        public E next() {
+            int i = cursor;
+            if (i >= a.length) {
+                throw new NoSuchElementException();
+            }
+            cursor = i + 1;
+            return a[i];
+        }
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/Observable.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Observable.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2012, 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
@@ -58,7 +58,19 @@
  * @see     java.util.Observer
  * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)
  * @since   1.0
+ *
+ * @deprecated
+ * This class and the {@link Observer} interface have been deprecated.
+ * The event model supported by {@code Observer} and {@code Observable}
+ * is quite limited, the order of notifications delivered by
+ * {@code Observable} is unspecified, and state changes are not in
+ * one-for-one correspondence with notifications.
+ * For a richer event model, consider using the
+ * {@link java.beans} package.  For reliable and ordered
+ * messaging among threads, consider using one of the concurrent data
+ * structures in the {@link java.util.concurrent} package.
  */
+@Deprecated(since="9")
 public class Observable {
     private boolean changed = false;
     private Vector<Observer> obs;
--- a/jdk/src/java.base/share/classes/java/util/Observer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/Observer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 1998, 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
@@ -31,7 +31,12 @@
  * @author  Chris Warth
  * @see     java.util.Observable
  * @since   1.0
+ *
+ * @deprecated
+ * This interface has been deprecated. See the {@link Observable}
+ * class for further information.
  */
+@Deprecated(since="9")
 public interface Observer {
     /**
      * This method is called whenever the observed object is changed. An
--- a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -167,6 +167,19 @@
         return Nodes.doubleBuilder(exactSizeIfKnown);
     }
 
+    private <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper, int opFlags) {
+        return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE, opFlags) {
+            @Override
+            Sink<Double> opWrapSink(int flags, Sink<U> sink) {
+                return new Sink.ChainedDouble<U>(sink) {
+                    @Override
+                    public void accept(double t) {
+                        downstream.accept(mapper.apply(t));
+                    }
+                };
+            }
+        };
+    }
 
     // DoubleStream
 
@@ -184,7 +197,7 @@
 
     @Override
     public final Stream<Double> boxed() {
-        return mapToObj(Double::valueOf);
+        return mapToObj(Double::valueOf, 0);
     }
 
     @Override
@@ -207,18 +220,7 @@
     @Override
     public final <U> Stream<U> mapToObj(DoubleFunction<? extends U> mapper) {
         Objects.requireNonNull(mapper);
-        return new ReferencePipeline.StatelessOp<Double, U>(this, StreamShape.DOUBLE_VALUE,
-                                                            StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
-            @Override
-            Sink<Double> opWrapSink(int flags, Sink<U> sink) {
-                return new Sink.ChainedDouble<U>(sink) {
-                    @Override
-                    public void accept(double t) {
-                        downstream.accept(mapper.apply(t));
-                    }
-                };
-            }
-        };
+        return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -170,6 +170,19 @@
         return Nodes.intBuilder(exactSizeIfKnown);
     }
 
+    private <U> Stream<U> mapToObj(IntFunction<? extends U> mapper, int opFlags) {
+        return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE, opFlags) {
+            @Override
+            Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
+                return new Sink.ChainedInt<U>(sink) {
+                    @Override
+                    public void accept(int t) {
+                        downstream.accept(mapper.apply(t));
+                    }
+                };
+            }
+        };
+    }
 
     // IntStream
 
@@ -187,8 +200,7 @@
 
     @Override
     public final LongStream asLongStream() {
-        return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
-                                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+        return new LongPipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
             @Override
             Sink<Integer> opWrapSink(int flags, Sink<Long> sink) {
                 return new Sink.ChainedInt<Long>(sink) {
@@ -203,8 +215,7 @@
 
     @Override
     public final DoubleStream asDoubleStream() {
-        return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE,
-                                                       StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+        return new DoublePipeline.StatelessOp<Integer>(this, StreamShape.INT_VALUE, 0) {
             @Override
             Sink<Integer> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedInt<Double>(sink) {
@@ -219,7 +230,7 @@
 
     @Override
     public final Stream<Integer> boxed() {
-        return mapToObj(Integer::valueOf);
+        return mapToObj(Integer::valueOf, 0);
     }
 
     @Override
@@ -242,18 +253,7 @@
     @Override
     public final <U> Stream<U> mapToObj(IntFunction<? extends U> mapper) {
         Objects.requireNonNull(mapper);
-        return new ReferencePipeline.StatelessOp<Integer, U>(this, StreamShape.INT_VALUE,
-                                                             StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
-            @Override
-            Sink<Integer> opWrapSink(int flags, Sink<U> sink) {
-                return new Sink.ChainedInt<U>(sink) {
-                    @Override
-                    public void accept(int t) {
-                        downstream.accept(mapper.apply(t));
-                    }
-                };
-            }
-        };
+        return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -167,6 +167,19 @@
         return Nodes.longBuilder(exactSizeIfKnown);
     }
 
+    private <U> Stream<U> mapToObj(LongFunction<? extends U> mapper, int opFlags) {
+        return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE, opFlags) {
+            @Override
+            Sink<Long> opWrapSink(int flags, Sink<U> sink) {
+                return new Sink.ChainedLong<U>(sink) {
+                    @Override
+                    public void accept(long t) {
+                        downstream.accept(mapper.apply(t));
+                    }
+                };
+            }
+        };
+    }
 
     // LongStream
 
@@ -184,8 +197,7 @@
 
     @Override
     public final DoubleStream asDoubleStream() {
-        return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE,
-                                                    StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
+        return new DoublePipeline.StatelessOp<Long>(this, StreamShape.LONG_VALUE, StreamOpFlag.NOT_DISTINCT) {
             @Override
             Sink<Long> opWrapSink(int flags, Sink<Double> sink) {
                 return new Sink.ChainedLong<Double>(sink) {
@@ -200,7 +212,7 @@
 
     @Override
     public final Stream<Long> boxed() {
-        return mapToObj(Long::valueOf);
+        return mapToObj(Long::valueOf, 0);
     }
 
     @Override
@@ -223,18 +235,7 @@
     @Override
     public final <U> Stream<U> mapToObj(LongFunction<? extends U> mapper) {
         Objects.requireNonNull(mapper);
-        return new ReferencePipeline.StatelessOp<Long, U>(this, StreamShape.LONG_VALUE,
-                                                          StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
-            @Override
-            Sink<Long> opWrapSink(int flags, Sink<U> sink) {
-                return new Sink.ChainedLong<U>(sink) {
-                    @Override
-                    public void accept(long t) {
-                        downstream.accept(mapper.apply(t));
-                    }
-                };
-            }
-        };
+        return mapToObj(mapper, StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT);
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,6 +28,7 @@
 import java.util.Objects;
 import java.util.Spliterator;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.BooleanSupplier;
 import java.util.function.Consumer;
@@ -905,6 +906,7 @@
         // The spliterator to slice
         protected final T_SPLITR s;
         protected final boolean unlimited;
+        protected final int chunkSize;
         private final long skipThreshold;
         private final AtomicLong permits;
 
@@ -912,6 +914,8 @@
             this.s = s;
             this.unlimited = limit < 0;
             this.skipThreshold = limit >= 0 ? limit : 0;
+            this.chunkSize = limit >= 0 ? (int)Math.min(CHUNK_SIZE,
+                ((skip + limit) / AbstractTask.LEAF_TARGET) + 1) : CHUNK_SIZE;
             this.permits = new AtomicLong(limit >= 0 ? skip + limit : skip);
         }
 
@@ -921,6 +925,7 @@
             this.unlimited = parent.unlimited;
             this.permits = parent.permits;
             this.skipThreshold = parent.skipThreshold;
+            this.chunkSize = parent.chunkSize;
         }
 
         /**
@@ -1029,13 +1034,13 @@
                 PermitStatus permitStatus;
                 while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
                     if (permitStatus == PermitStatus.MAYBE_MORE) {
-                        // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+                        // Optimistically traverse elements up to a threshold of chunkSize
                         if (sb == null)
-                            sb = new ArrayBuffer.OfRef<>(CHUNK_SIZE);
+                            sb = new ArrayBuffer.OfRef<>(chunkSize);
                         else
                             sb.reset();
                         long permitsRequested = 0;
-                        do { } while (s.tryAdvance(sb) && ++permitsRequested < CHUNK_SIZE);
+                        do { } while (s.tryAdvance(sb) && ++permitsRequested < chunkSize);
                         if (permitsRequested == 0)
                             return;
                         sb.forEach(action, acquirePermits(permitsRequested));
@@ -1102,15 +1107,15 @@
                 PermitStatus permitStatus;
                 while ((permitStatus = permitStatus()) != PermitStatus.NO_MORE) {
                     if (permitStatus == PermitStatus.MAYBE_MORE) {
-                        // Optimistically traverse elements up to a threshold of CHUNK_SIZE
+                        // Optimistically traverse elements up to a threshold of chunkSize
                         if (sb == null)
-                            sb = bufferCreate(CHUNK_SIZE);
+                            sb = bufferCreate(chunkSize);
                         else
                             sb.reset();
                         @SuppressWarnings("unchecked")
                         T_CONS sbc = (T_CONS) sb;
                         long permitsRequested = 0;
-                        do { } while (s.tryAdvance(sbc) && ++permitsRequested < CHUNK_SIZE);
+                        do { } while (s.tryAdvance(sbc) && ++permitsRequested < chunkSize);
                         if (permitsRequested == 0)
                             return;
                         sb.forEach(action, acquirePermits(permitsRequested));
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/DefaultLoggerFinder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -33,6 +33,9 @@
 import java.lang.System.LoggerFinder;
 import java.lang.System.Logger;
 import java.lang.ref.ReferenceQueue;
+import java.lang.reflect.Module;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Collection;
 import java.util.ResourceBundle;
 
@@ -129,41 +132,49 @@
             return w;
         }
 
-
         final static SharedLoggers system = new SharedLoggers();
         final static SharedLoggers application = new SharedLoggers();
     }
 
+    public static boolean isSystem(Module m) {
+        ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<>() {
+            @Override
+            public ClassLoader run() {
+                return m.getClassLoader();
+            }
+        });
+        return cl == null;
+    }
+
     @Override
-    public final Logger getLogger(String name,  /* Module */ Class<?> caller) {
+    public final Logger getLogger(String name,  Module module) {
         checkPermission();
-        return demandLoggerFor(name, caller);
+        return demandLoggerFor(name, module);
     }
 
     @Override
     public final Logger getLocalizedLogger(String name, ResourceBundle bundle,
-                                           /* Module */  Class<?> caller) {
-        return super.getLocalizedLogger(name, bundle, caller);
+                                           Module module) {
+        return super.getLocalizedLogger(name, bundle, module);
     }
 
-
-
     /**
-     * Returns a {@link Logger logger} suitable for the caller usage.
+     * Returns a {@link Logger logger} suitable for use within the
+     * given {@code module}.
      *
      * @implSpec The default implementation for this method is to return a
      *    simple logger that will print all messages of INFO level and above
      *    to the console. That simple logger is not configurable.
      *
      * @param name The name of the logger.
-     * @param caller The class on behalf of which the logger is created.
+     * @param module The module on behalf of which the logger is created.
      * @return A {@link Logger logger} suitable for the application usage.
      * @throws SecurityException if the calling code does not have the
      * {@code RuntimePermission("loggerFinder")}.
      */
-    protected Logger demandLoggerFor(String name, /* Module */ Class<?> caller) {
+    protected Logger demandLoggerFor(String name, Module module) {
         checkPermission();
-        if (caller.getClassLoader() == null) {
+        if (isSystem(module)) {
             return SharedLoggers.system.get(SimpleConsoleLogger::makeSimpleLogger, name);
         } else {
             return SharedLoggers.application.get(SimpleConsoleLogger::makeSimpleLogger, name);
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LazyLoggers.java	Wed Jul 05 21:39:33 2017 +0200
@@ -31,6 +31,7 @@
 import java.lang.System.LoggerFinder;
 import java.lang.System.Logger;
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Module;
 import java.util.Objects;
 import jdk.internal.misc.VM;
 import sun.util.logging.PlatformLogger;
@@ -59,15 +60,15 @@
          * A factory method to create an SPI logger.
          * Usually, this will be something like LazyLoggers::getSystemLogger.
          */
-        final BiFunction<String, Class<?>, L> loggerSupplier;
+        final BiFunction<String, Module, L> loggerSupplier;
 
 
-        public LazyLoggerFactories(BiFunction<String, Class<?>, L> loggerSupplier) {
+        public LazyLoggerFactories(BiFunction<String, Module, L> loggerSupplier) {
             this(Objects.requireNonNull(loggerSupplier),
                  (Void)null);
         }
 
-        private LazyLoggerFactories(BiFunction<String, Class<?>, L> loggerSupplier,
+        private LazyLoggerFactories(BiFunction<String, Module, L> loggerSupplier,
                           Void unused) {
             this.loggerSupplier = loggerSupplier;
         }
@@ -107,8 +108,8 @@
         // The factories that will be used to create the logger lazyly
         final LazyLoggerFactories<? extends Logger> factories;
 
-        // We need to pass the actual caller when creating the logger.
-        private final WeakReference<Class<?>> callerRef;
+        // We need to pass the actual caller module when creating the logger.
+        private final WeakReference<Module> moduleRef;
 
         // The name of the logger that will be created lazyly
         final String name;
@@ -121,17 +122,17 @@
 
         private LazyLoggerAccessor(String name,
                                    LazyLoggerFactories<? extends Logger> factories,
-                                   Class<?> caller) {
+                                   Module module) {
             this(Objects.requireNonNull(name), Objects.requireNonNull(factories),
-                    Objects.requireNonNull(caller), null);
+                    Objects.requireNonNull(module), null);
         }
 
         private LazyLoggerAccessor(String name,
                                    LazyLoggerFactories<? extends Logger> factories,
-                                   Class<?> caller, Void unused) {
+                                   Module module, Void unused) {
             this.name = name;
             this.factories = factories;
-            this.callerRef = new WeakReference<Class<?>>(caller);
+            this.moduleRef = new WeakReference<>(module);
         }
 
         /**
@@ -270,12 +271,12 @@
 
         // Creates the wrapped logger by invoking the SPI.
         Logger createLogger() {
-            final Class<?> caller = callerRef.get();
-            if (caller == null) {
-                throw new IllegalStateException("The class for which this logger"
+            final Module module = moduleRef.get();
+            if (module == null) {
+                throw new IllegalStateException("The module for which this logger"
                         + " was created has been garbage collected");
             }
-            return this.factories.loggerSupplier.apply(name, caller);
+            return this.factories.loggerSupplier.apply(name, module);
         }
 
         /**
@@ -289,8 +290,8 @@
          * @return A new LazyLoggerAccessor.
          */
         public static LazyLoggerAccessor makeAccessor(String name,
-                LazyLoggerFactories<? extends Logger> factories, Class<?> caller) {
-                return new LazyLoggerAccessor(name, factories, caller);
+                LazyLoggerFactories<? extends Logger> factories, Module module) {
+                return new LazyLoggerAccessor(name, factories, module);
         }
 
     }
@@ -346,11 +347,11 @@
 
     // Avoid using lambda here as lazy loggers could be created early
     // in the bootstrap sequence...
-    private static final BiFunction<String, Class<?>, Logger> loggerSupplier =
+    private static final BiFunction<String, Module, Logger> loggerSupplier =
            new BiFunction<>() {
         @Override
-        public Logger apply(String name, Class<?> caller) {
-            return LazyLoggers.getLoggerFromFinder(name, caller);
+        public Logger apply(String name, Module module) {
+            return LazyLoggers.getLoggerFromFinder(name, module);
         }
     };
 
@@ -367,8 +368,8 @@
     // logger provider until the VM has finished booting.
     //
     private static final class JdkLazyLogger extends LazyLoggerWrapper {
-        JdkLazyLogger(String name, Class<?> caller) {
-            this(LazyLoggerAccessor.makeAccessor(name, factories, caller),
+        JdkLazyLogger(String name, Module module) {
+            this(LazyLoggerAccessor.makeAccessor(name, factories, module),
                  (Void)null);
         }
         private JdkLazyLogger(LazyLoggerAccessor holder, Void unused) {
@@ -380,16 +381,16 @@
      * Gets a logger from the LoggerFinder. Creates the actual concrete
      * logger.
      * @param name    name of the logger
-     * @param caller  class on behalf of which the logger is created
+     * @param module  module on behalf of which the logger is created
      * @return  The logger returned by the LoggerFinder.
      */
-    static Logger getLoggerFromFinder(String name, Class<?> caller) {
+    static Logger getLoggerFromFinder(String name, Module module) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
-            return accessLoggerFinder().getLogger(name, caller);
+            return accessLoggerFinder().getLogger(name, module);
         } else {
             return AccessController.doPrivileged((PrivilegedAction<Logger>)
-                    () -> {return accessLoggerFinder().getLogger(name, caller);},
+                    () -> {return accessLoggerFinder().getLogger(name, module);},
                     null, LOGGERFINDER_PERMISSION);
         }
     }
@@ -398,22 +399,22 @@
      * Returns a (possibly lazy) Logger for the caller.
      *
      * @param name the logger name
-     * @param caller The class on behalf of which the logger is created.
-     *               If the caller is not loaded from the Boot ClassLoader,
+     * @param module The module on behalf of which the logger is created.
+     *               If the module is not loaded from the Boot ClassLoader,
      *               the LoggerFinder is accessed and the logger returned
-     *               by {@link LoggerFinder#getLogger(java.lang.String, java.lang.Class)}
+     *               by {@link LoggerFinder#getLogger(java.lang.String, java.lang.reflect.Module)}
      *               is returned to the caller directly.
      *               Otherwise, the logger returned by
-     *               {@link #getLazyLogger(java.lang.String, java.lang.Class)}
+     *               {@link #getLazyLogger(java.lang.String, java.lang.reflect.Module)}
      *               is returned to the caller.
      *
      * @return  a (possibly lazy) Logger instance.
      */
-    public static final Logger getLogger(String name, Class<?> caller) {
-        if (caller.getClassLoader() == null) {
-            return getLazyLogger(name, caller);
+    public static final Logger getLogger(String name, Module module) {
+        if (DefaultLoggerFinder.isSystem(module)) {
+            return getLazyLogger(name, module);
         } else {
-            return getLoggerFromFinder(name, caller);
+            return getLoggerFromFinder(name, module);
         }
     }
 
@@ -423,10 +424,10 @@
      * returned by {@link BootstrapLogger#useLazyLoggers()}.
      *
      * @param name the logger name
-     * @param caller the class on behalf of which the logger is created.
+     * @param module the module on behalf of which the logger is created.
      * @return  a (possibly lazy) Logger instance.
      */
-    public static final Logger getLazyLogger(String name, Class<?> caller) {
+    public static final Logger getLazyLogger(String name, Module module) {
 
         // BootstrapLogger has the logic to determine whether a LazyLogger
         // should be used. Usually, it is worth it only if:
@@ -438,10 +439,10 @@
         // configuration, we're not going to delay the creation of loggers...
         final boolean useLazyLogger = BootstrapLogger.useLazyLoggers();
         if (useLazyLogger) {
-            return new JdkLazyLogger(name, caller);
+            return new JdkLazyLogger(name, module);
         } else {
             // Directly invoke the LoggerFinder.
-            return getLoggerFromFinder(name, caller);
+            return getLoggerFromFinder(name, module);
         }
     }
 
--- a/jdk/src/java.base/share/classes/jdk/net/ExtendedSocketOptions.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.net;
-
-import java.net.SocketOption;
-
-/**
- * Defines extended socket options, beyond those defined in
- * {@link java.net.StandardSocketOptions}. These options may be platform
- * specific.
- *
- * @since 1.8
- */
-public final class ExtendedSocketOptions {
-
-    private static class ExtSocketOption<T> implements SocketOption<T> {
-        private final String name;
-        private final Class<T> type;
-        ExtSocketOption(String name, Class<T> type) {
-            this.name = name;
-            this.type = type;
-        }
-        @Override public String name() { return name; }
-        @Override public Class<T> type() { return type; }
-        @Override public String toString() { return name; }
-    }
-
-    private ExtendedSocketOptions() {}
-
-    /**
-     * Service level properties. When a security manager is installed,
-     * setting or getting this option requires a {@link NetworkPermission}
-     * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
-     * respectively.
-     */
-    public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
-        ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
-}
--- a/jdk/src/java.base/share/classes/jdk/net/NetworkPermission.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.net;
-
-import java.security.BasicPermission;
-
-/**
- * Represents permission to access the extended networking capabilities
- * defined in the jdk.net package. These permissions contain a target
- * name, but no actions list. Callers either possess the permission or not.
- * <p>
- * The following targets are defined:
- *
- * <table border=1 cellpadding=5 summary="permission target name,
- *  what the target allows,and associated risks">
- * <tr>
- *   <th>Permission Target Name</th>
- *   <th>What the Permission Allows</th>
- *   <th>Risks of Allowing this Permission</th>
- * </tr>
- * <tr>
- *   <td>setOption.SO_FLOW_SLA</td>
- *   <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option
- *       on any socket that supports it</td>
- *   <td>allows caller to set a higher priority or bandwidth allocation
- *       to sockets it creates, than they might otherwise be allowed.</td>
- * </tr>
- * <tr>
- *   <td>getOption.SO_FLOW_SLA</td>
- *   <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA}
- *       setting from any socket that supports the option</td>
- *   <td>allows caller access to SLA information that it might not
- *       otherwise have</td>
- * </tr></table>
- *
- * @see jdk.net.ExtendedSocketOptions
- *
- * @since 1.8
- */
-
-public final class NetworkPermission extends BasicPermission {
-
-    private static final long serialVersionUID = -2012939586906722291L;
-
-    /**
-     * Creates a NetworkPermission with the given target name.
-     *
-     * @param name the permission target name
-     * @throws NullPointerException if {@code name} is {@code null}.
-     * @throws IllegalArgumentException if {@code name} is empty.
-     */
-    public NetworkPermission(String name)
-    {
-        super(name);
-    }
-
-    /**
-     * Creates a NetworkPermission with the given target name.
-     *
-     * @param name the permission target name
-     * @param actions should be {@code null}. Is ignored if not.
-     * @throws NullPointerException if {@code name} is {@code null}.
-     * @throws IllegalArgumentException if {@code name} is empty.
-     */
-    public NetworkPermission(String name, String actions)
-    {
-        super(name, actions);
-    }
-}
--- a/jdk/src/java.base/share/classes/jdk/net/SocketFlow.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.net;
-
-import java.lang.annotation.Native;
-
-/**
- * Represents the service level properties for the platform specific socket
- * option {@link ExtendedSocketOptions#SO_FLOW_SLA}.
- * <p>
- * The priority and bandwidth parameters must be set before
- * setting the socket option.
- * <p>
- * When the {@code SO_FLOW_SLA} option is set then it may not take effect
- * immediately. If the value of the socket option is obtained with
- * {@code getOption()} then the status may be returned as {@code INPROGRESS}
- * until it takes effect. The priority and bandwidth values are only valid when
- * the status is returned as OK.
- * <p>
- * When a security manager is installed, a {@link NetworkPermission}
- * is required to set or get this option.
- *
- * @since 1.8
- */
-public class SocketFlow {
-
-    private static final int UNSET = -1;
-    @Native public static final int NORMAL_PRIORITY = 1;
-    @Native public static final int HIGH_PRIORITY = 2;
-
-    private int priority = NORMAL_PRIORITY;
-
-    private long bandwidth = UNSET;
-
-    private Status status = Status.NO_STATUS;
-
-    private SocketFlow() {}
-
-    /**
-     * Enumeration of the return values from the SO_FLOW_SLA
-     * socket option. Both setting and getting the option return
-     * one of these statuses, which reflect the state of socket's
-     * flow.
-     *
-     * @since 1.8
-     */
-    public enum Status {
-        /**
-         * Set or get socket option has not been called yet. Status
-         * values can only be retrieved after calling set or get.
-         */
-        NO_STATUS,
-        /**
-         * Flow successfully created.
-         */
-        OK,
-        /**
-         * Caller has no permission to create flow.
-         */
-        NO_PERMISSION,
-        /**
-         * Flow can not be created because socket is not connected.
-         */
-        NOT_CONNECTED,
-        /**
-         * Flow creation not supported for this socket.
-         */
-        NOT_SUPPORTED,
-        /**
-         * A flow already exists with identical attributes.
-         */
-        ALREADY_CREATED,
-        /**
-         * A flow is being created.
-         */
-        IN_PROGRESS,
-        /**
-         * Some other unspecified error.
-         */
-        OTHER
-    }
-
-    /**
-     * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
-     * socket option and create a socket flow.
-     */
-    public static SocketFlow create() {
-        return new SocketFlow();
-    }
-
-    /**
-     * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
-     * HIGH_PRIORITY. If not set, a flow's priority is normal.
-     *
-     * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or
-     *         HIGH_PRIORITY.
-     */
-    public SocketFlow priority(int priority) {
-        if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY) {
-            throw new IllegalArgumentException("invalid priority");
-        }
-        this.priority = priority;
-        return this;
-    }
-
-    /**
-     * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero.
-     * A value of zero drops all packets for the socket.
-     *
-     * @throws IllegalArgumentException if bandwidth is less than zero.
-     */
-    public SocketFlow bandwidth(long bandwidth) {
-        if (bandwidth < 0) {
-            throw new IllegalArgumentException("invalid bandwidth");
-        } else {
-            this.bandwidth = bandwidth;
-        }
-        return this;
-    }
-
-    /**
-     * Returns this SocketFlow's priority.
-     */
-    public int priority() {
-        return priority;
-    }
-
-    /**
-     * Returns this SocketFlow's bandwidth.
-     *
-     * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK.
-     */
-    public long bandwidth() {
-        return bandwidth;
-    }
-
-    /**
-     * Returns the Status value of this SocketFlow. NO_STATUS is returned
-     * if the object was not used in a call to set or get the option.
-     */
-    public Status status() {
-        return status;
-    }
-}
--- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.net;
-
-import java.net.*;
-import java.io.IOException;
-import java.io.FileDescriptor;
-import java.security.PrivilegedAction;
-import java.security.AccessController;
-import java.lang.reflect.Field;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Collections;
-import sun.net.ExtendedOptionsImpl;
-
-/**
- * Defines static methods to set and get socket options defined by the
- * {@link java.net.SocketOption} interface. All of the standard options defined
- * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and
- * {@link java.net.DatagramSocket} can be set this way, as well as additional
- * or platform specific options supported by each socket type.
- * <p>
- * The {@link #supportedOptions(Class)} method can be called to determine
- * the complete set of options available (per socket type) on the
- * current system.
- * <p>
- * When a security manager is installed, some non-standard socket options
- * may require a security permission before being set or get.
- * The details are specified in {@link ExtendedSocketOptions}. No permission
- * is required for {@link java.net.StandardSocketOptions}.
- *
- * @see java.nio.channels.NetworkChannel
- */
-public class Sockets {
-
-    private static final HashMap<Class<?>,Set<SocketOption<?>>>
-        options = new HashMap<>();
-
-    static {
-        initOptionSets();
-    }
-
-    private Sockets() {}
-
-    /**
-     * Sets the value of a socket option on a {@link java.net.Socket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     * @param value The value of the socket option. May be null for some
-     *              options.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IllegalArgumentException if the value is not valid for
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs, or socket is closed.
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException
-    {
-        s.setOption(name, value);
-    }
-
-    /**
-     * Returns the value of a socket option from a {@link java.net.Socket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     *
-     * @return The value of the socket option.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException
-    {
-        return s.getOption(name);
-    }
-
-    /**
-     * Sets the value of a socket option on a {@link java.net.ServerSocket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     * @param value The value of the socket option.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IllegalArgumentException if the value is not valid for
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException
-    {
-        s.setOption(name, value);
-    }
-
-    /**
-     * Returns the value of a socket option from a {@link java.net.ServerSocket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     *
-     * @return The value of the socket option.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException
-    {
-        return s.getOption(name);
-    }
-
-    /**
-     * Sets the value of a socket option on a {@link java.net.DatagramSocket}
-     * or {@link java.net.MulticastSocket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     * @param value The value of the socket option.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IllegalArgumentException if the value is not valid for
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException
-    {
-        s.setOption(name, value);
-    }
-
-    /**
-     * Returns the value of a socket option from a
-     * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket}
-     *
-     * @param s the socket
-     * @param name The socket option
-     *
-     * @return The value of the socket option.
-     *
-     * @throws UnsupportedOperationException if the socket does not support
-     *         the option.
-     *
-     * @throws IOException if an I/O error occurs
-     *
-     * @throws NullPointerException if name is null
-     *
-     * @throws SecurityException if a security manager is set and the
-     *         caller does not have any required permission.
-     *
-     * @see java.net.StandardSocketOptions
-     */
-    public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException
-    {
-        return s.getOption(name);
-    }
-
-    /**
-     * Returns a set of {@link java.net.SocketOption}s supported by the
-     * given socket type. This set may include standard options and also
-     * non standard extended options.
-     *
-     * @param socketType the type of java.net socket
-     *
-     * @throws IllegalArgumentException if socketType is not a valid
-     *         socket type from the java.net package.
-     */
-    public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) {
-        Set<SocketOption<?>> set = options.get(socketType);
-        if (set == null) {
-            throw new IllegalArgumentException("unknown socket type");
-        }
-        return set;
-    }
-
-    private static void checkValueType(Object value, Class<?> type) {
-        if (!type.isAssignableFrom(value.getClass())) {
-            String s = "Found: " + value.getClass().toString() + " Expected: "
-                        + type.toString();
-            throw new IllegalArgumentException(s);
-        }
-    }
-
-    private static volatile boolean checkedReusePort;
-    private static volatile boolean isReusePortAvailable;
-
-    /**
-     * Tells whether SO_REUSEPORT is supported.
-     */
-    static boolean isReusePortAvailable() {
-        if (!checkedReusePort) {
-            isReusePortAvailable = isReusePortAvailable0();
-            checkedReusePort = true;
-        }
-        return isReusePortAvailable;
-    }
-
-    private static void initOptionSets() {
-        boolean flowsupported = ExtendedOptionsImpl.flowSupported();
-        boolean reuseportsupported = isReusePortAvailable();
-        // Socket
-
-        Set<SocketOption<?>> set = new HashSet<>();
-        set.add(StandardSocketOptions.SO_KEEPALIVE);
-        set.add(StandardSocketOptions.SO_SNDBUF);
-        set.add(StandardSocketOptions.SO_RCVBUF);
-        set.add(StandardSocketOptions.SO_REUSEADDR);
-        if (reuseportsupported) {
-            set.add(StandardSocketOptions.SO_REUSEPORT);
-        }
-        set.add(StandardSocketOptions.SO_LINGER);
-        set.add(StandardSocketOptions.IP_TOS);
-        set.add(StandardSocketOptions.TCP_NODELAY);
-        if (flowsupported) {
-            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
-        }
-        set = Collections.unmodifiableSet(set);
-        options.put(Socket.class, set);
-
-        // ServerSocket
-
-        set = new HashSet<>();
-        set.add(StandardSocketOptions.SO_RCVBUF);
-        set.add(StandardSocketOptions.SO_REUSEADDR);
-        if (reuseportsupported) {
-            set.add(StandardSocketOptions.SO_REUSEPORT);
-        }
-        set.add(StandardSocketOptions.IP_TOS);
-        set = Collections.unmodifiableSet(set);
-        options.put(ServerSocket.class, set);
-
-        // DatagramSocket
-
-        set = new HashSet<>();
-        set.add(StandardSocketOptions.SO_SNDBUF);
-        set.add(StandardSocketOptions.SO_RCVBUF);
-        set.add(StandardSocketOptions.SO_REUSEADDR);
-        if (reuseportsupported) {
-            set.add(StandardSocketOptions.SO_REUSEPORT);
-        }
-        set.add(StandardSocketOptions.IP_TOS);
-        if (flowsupported) {
-            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
-        }
-        set = Collections.unmodifiableSet(set);
-        options.put(DatagramSocket.class, set);
-
-        // MulticastSocket
-
-        set = new HashSet<>();
-        set.add(StandardSocketOptions.SO_SNDBUF);
-        set.add(StandardSocketOptions.SO_RCVBUF);
-        set.add(StandardSocketOptions.SO_REUSEADDR);
-        if (reuseportsupported) {
-            set.add(StandardSocketOptions.SO_REUSEPORT);
-        }
-        set.add(StandardSocketOptions.IP_TOS);
-        set.add(StandardSocketOptions.IP_MULTICAST_IF);
-        set.add(StandardSocketOptions.IP_MULTICAST_TTL);
-        set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
-        if (flowsupported) {
-            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
-        }
-        set = Collections.unmodifiableSet(set);
-        options.put(MulticastSocket.class, set);
-    }
-
-    private static native boolean isReusePortAvailable0();
-}
--- a/jdk/src/java.base/share/classes/jdk/net/package-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Platform specific socket options for the {@code java.net} and {@code java.nio.channels}
- * socket classes.
- *
- * @since 1.8
- */
-
-package jdk.net;
--- a/jdk/src/java.base/share/classes/module-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -83,8 +83,6 @@
 
     // see JDK-8144062
     exports jdk;
-    // see JDK-8044773
-    exports jdk.net;
 
 
     // the service types defined by the APIs in this module
@@ -168,6 +166,7 @@
         java.sql,
         java.xml,
         jdk.charsets,
+        jdk.net,
         jdk.scripting.nashorn,
         jdk.unsupported,
         jdk.vm.ci;
@@ -194,6 +193,8 @@
         jdk.jvmstat;
     exports sun.net to
         java.httpclient;
+    exports sun.net.ext to
+        jdk.net;
     exports sun.net.dns to
         java.security.jgss,
         jdk.naming.dns;
--- a/jdk/src/java.base/share/classes/sun/net/ExtendedOptionsImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net;
-
-import java.net.*;
-import jdk.net.*;
-import java.io.IOException;
-import java.io.FileDescriptor;
-import java.security.PrivilegedAction;
-import java.security.AccessController;
-import java.lang.reflect.Field;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.HashMap;
-import java.util.Collections;
-
-/**
- * Contains the native implementation for extended socket options
- * together with some other static utilities
- */
-public class ExtendedOptionsImpl {
-
-    static {
-        AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
-            System.loadLibrary("net");
-            return null;
-        });
-        init();
-    }
-
-    private ExtendedOptionsImpl() {}
-
-    public static void checkSetOptionPermission(SocketOption<?> option) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm == null) {
-            return;
-        }
-        String check = "setOption." + option.name();
-        sm.checkPermission(new NetworkPermission(check));
-    }
-
-    public static void checkGetOptionPermission(SocketOption<?> option) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm == null) {
-            return;
-        }
-        String check = "getOption." + option.name();
-        sm.checkPermission(new NetworkPermission(check));
-    }
-
-    public static void checkValueType(Object value, Class<?> type) {
-        if (!type.isAssignableFrom(value.getClass())) {
-            String s = "Found: " + value.getClass().toString() + " Expected: "
-                        + type.toString();
-            throw new IllegalArgumentException(s);
-        }
-    }
-
-    private static native void init();
-
-    /*
-     * Extension native implementations
-     *
-     * SO_FLOW_SLA
-     */
-    public static native void setFlowOption(FileDescriptor fd, SocketFlow f);
-    public static native void getFlowOption(FileDescriptor fd, SocketFlow f);
-    public static native boolean flowSupported();
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/net/ext/ExtendedSocketOptions.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.net.ext;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Defines the infrastructure to support extended socket options, beyond those
+ * defined in {@link java.net.StandardSocketOptions}.
+ *
+ * Extended socket options are accessed through the jdk.net API, which is in
+ * the jdk.net module.
+ */
+public abstract class ExtendedSocketOptions {
+
+    private final Set<SocketOption<?>> options;
+
+    /** Tells whether or not the option is supported. */
+    public final boolean isOptionSupported(SocketOption<?> option) {
+        return options().contains(option);
+    }
+
+    /** Return the, possibly empty, set of extended socket options available. */
+    public final Set<SocketOption<?>> options() { return options; }
+
+    /** Sets the value of a socket option, for the given socket. */
+    public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
+            throws SocketException;
+
+    /** Returns the value of a socket option, for the given socket. */
+    public abstract Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException;
+
+    protected ExtendedSocketOptions(Set<SocketOption<?>> options) {
+        this.options = options;
+    }
+
+    private static volatile ExtendedSocketOptions instance;
+
+    public static final ExtendedSocketOptions getInstance() { return instance; }
+
+    /** Registers support for extended socket options. Invoked by the jdk.net module. */
+    public static final void register(ExtendedSocketOptions extOptions) {
+        if (instance != null)
+            throw new InternalError("Attempting to reregister extended options");
+
+        instance = extOptions;
+    }
+
+    static {
+        try {
+            // If the class is present, it will be initialized which
+            // triggers registration of the extended socket options.
+            Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
+        } catch (ClassNotFoundException e) {
+            // the jdk.net module is not present => no extended socket options
+            instance = new NoExtendedSocketOptions();
+        }
+    }
+
+    static final class NoExtendedSocketOptions extends ExtendedSocketOptions {
+
+        NoExtendedSocketOptions() {
+            super(Collections.<SocketOption<?>>emptySet());
+        }
+
+        @Override
+        public void setOption(FileDescriptor fd, SocketOption<?> option, Object value)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no extended options: " + option.name());
+        }
+
+        @Override
+        public Object getOption(FileDescriptor fd, SocketOption<?> option)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException(
+                    "no extended options: " + option.name());
+        }
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AbstractPollSelectorImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
-import sun.misc.*;
 
 
 /**
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -39,7 +39,7 @@
 import java.util.concurrent.*;
 import java.util.concurrent.locks.*;
 import sun.net.NetHooks;
-import sun.net.ExtendedOptionsImpl;
+import sun.net.ext.ExtendedSocketOptions;
 
 /**
  * Base implementation of AsynchronousSocketChannel
@@ -512,9 +512,9 @@
                 set.add(StandardSocketOptions.SO_REUSEPORT);
             }
             set.add(StandardSocketOptions.TCP_NODELAY);
-            if (ExtendedOptionsImpl.flowSupported()) {
-                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
-            }
+            ExtendedSocketOptions extendedOptions =
+                    ExtendedSocketOptions.getInstance();
+            set.addAll(extendedOptions.options());
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -33,7 +33,7 @@
 import java.nio.channels.spi.*;
 import java.util.*;
 import sun.net.ResourceManager;
-import sun.net.ExtendedOptionsImpl;
+import sun.net.ext.ExtendedSocketOptions;
 
 /**
  * An implementation of DatagramChannels.
@@ -306,9 +306,9 @@
             set.add(StandardSocketOptions.IP_MULTICAST_IF);
             set.add(StandardSocketOptions.IP_MULTICAST_TTL);
             set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
-            if (ExtendedOptionsImpl.flowSupported()) {
-                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
-            }
+            ExtendedSocketOptions extendedOptions =
+                    ExtendedSocketOptions.getInstance();
+            set.addAll(extendedOptions.options());
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Wed Jul 05 21:39:33 2017 +0200
@@ -27,15 +27,13 @@
 
 import java.io.*;
 import java.net.*;
-import jdk.net.*;
 import java.nio.channels.*;
 import java.util.*;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import sun.net.ExtendedOptionsImpl;
+import sun.net.ext.ExtendedSocketOptions;
 import sun.security.action.GetPropertyAction;
 
-
 public class Net {
 
     private Net() { }
@@ -281,6 +279,9 @@
 
     // -- Socket options
 
+    static final ExtendedSocketOptions extendedOptions =
+            ExtendedSocketOptions.getInstance();
+
     static void setSocketOption(FileDescriptor fd, ProtocolFamily family,
                                 SocketOption<?> name, Object value)
         throws IOException
@@ -291,12 +292,8 @@
         // only simple values supported by this method
         Class<?> type = name.type();
 
-        if (type == SocketFlow.class) {
-            SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                sm.checkPermission(new NetworkPermission("setOption.SO_FLOW_SLA"));
-            }
-            ExtendedOptionsImpl.setFlowOption(fd, (SocketFlow)value);
+        if (extendedOptions.isOptionSupported(name)) {
+            extendedOptions.setOption(fd, name, value);
             return;
         }
 
@@ -353,14 +350,8 @@
     {
         Class<?> type = name.type();
 
-        if (type == SocketFlow.class) {
-            SecurityManager sm = System.getSecurityManager();
-            if (sm != null) {
-                sm.checkPermission(new NetworkPermission("getOption.SO_FLOW_SLA"));
-            }
-            SocketFlow flow = SocketFlow.create();
-            ExtendedOptionsImpl.getFlowOption(fd, flow);
-            return flow;
+        if (extendedOptions.isOptionSupported(name)) {
+            return extendedOptions.getOption(fd, name);
         }
 
         // only simple values supported by this method
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -33,8 +33,7 @@
 import java.nio.channels.spi.*;
 import java.util.*;
 import sun.net.NetHooks;
-import sun.net.ExtendedOptionsImpl;
-
+import sun.net.ext.ExtendedSocketOptions;
 
 /**
  * An implementation of SocketChannels
@@ -242,9 +241,9 @@
             // additional options required by socket adaptor
             set.add(StandardSocketOptions.IP_TOS);
             set.add(ExtendedSocketOption.SO_OOBINLINE);
-            if (ExtendedOptionsImpl.flowSupported()) {
-                set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
-            }
+            ExtendedSocketOptions extendedOptions =
+                    ExtendedSocketOptions.getInstance();
+            set.addAll(extendedOptions.options());
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.action;
-
-import java.security.Security;
-
-/**
- * A convenience class for retrieving the boolean value of a security property
- * as a privileged action.
- *
- * <p>An instance of this class can be used as the argument of
- * <code>AccessController.doPrivileged</code>.
- *
- * <p>The following code retrieves the boolean value of the security
- * property named <code>"prop"</code> as a privileged action:
- *
- * <pre>
- * boolean b = java.security.AccessController.doPrivileged
- *              (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
- * </pre>
- *
- */
-public class GetBooleanSecurityPropertyAction
-        implements java.security.PrivilegedAction<Boolean> {
-    private String theProp;
-
-    /**
-     * Constructor that takes the name of the security property whose boolean
-     * value needs to be determined.
-     *
-     * @param theProp the name of the security property
-     */
-    public GetBooleanSecurityPropertyAction(String theProp) {
-        this.theProp = theProp;
-    }
-
-    /**
-     * Determines the boolean value of the security property whose name was
-     * specified in the constructor.
-     *
-     * @return the <code>Boolean</code> value of the security property.
-     */
-    public Boolean run() {
-        boolean b = false;
-        try {
-            String value = Security.getProperty(theProp);
-            b = (value != null) && value.equalsIgnoreCase("true");
-        } catch (NullPointerException e) {}
-        return b;
-    }
-}
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,10 @@
 import java.util.Collections;
 import java.util.Set;
 import java.util.EnumSet;
-import java.util.HashSet;
 import java.math.BigInteger;
 import java.security.PublicKey;
 import java.security.KeyFactory;
 import java.security.AlgorithmParameters;
-import java.security.NoSuchAlgorithmException;
 import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
 import java.security.cert.X509CRL;
@@ -48,10 +46,13 @@
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CertPathValidatorException.BasicReason;
 import java.security.cert.PKIXReason;
-import java.io.IOException;
-import java.security.interfaces.*;
-import java.security.spec.*;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
 
+import sun.security.util.AnchorCertificates;
+import sun.security.util.CertConstraintParameters;
+import sun.security.util.Debug;
 import sun.security.util.DisabledAlgorithmConstraints;
 import sun.security.x509.X509CertImpl;
 import sun.security.x509.X509CRLImpl;
@@ -69,6 +70,7 @@
  * @see PKIXParameters
  */
 public final class AlgorithmChecker extends PKIXCertPathChecker {
+    private static final Debug debug = Debug.getInstance("certpath");
 
     private final AlgorithmConstraints constraints;
     private final PublicKey trustedPubKey;
@@ -88,6 +90,14 @@
         certPathDefaultConstraints = new DisabledAlgorithmConstraints(
             DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
 
+    // If there is no "cacerts" keyword, then disable anchor checking
+    private static final boolean publicCALimits =
+            certPathDefaultConstraints.checkProperty("jdkCA");
+
+    // If anchor checking enabled, this will be true if the trust anchor
+    // has a match in the cacerts file
+    private boolean trustedMatch = false;
+
     /**
      * Create a new <code>AlgorithmChecker</code> with the algorithm
      * constraints specified in security property
@@ -136,6 +146,11 @@
 
         if (anchor.getTrustedCert() != null) {
             this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
+            // Check for anchor certificate restrictions
+            trustedMatch = checkFingerprint(anchor.getTrustedCert());
+            if (trustedMatch && debug != null) {
+                debug.println("trustedMatch = true");
+            }
         } else {
             this.trustedPubKey = anchor.getCAPublicKey();
         }
@@ -144,6 +159,19 @@
         this.constraints = constraints;
     }
 
+    // Check this 'cert' for restrictions in the AnchorCertificates
+    // trusted certificates list
+    private static boolean checkFingerprint(X509Certificate cert) {
+        if (!publicCALimits) {
+            return false;
+        }
+
+        if (debug != null) {
+            debug.println("AlgorithmChecker.contains: " + cert.getSigAlgName());
+        }
+        return AnchorCertificates.contains(cert);
+    }
+
     @Override
     public void init(boolean forward) throws CertPathValidatorException {
         //  Note that this class does not support forward mode.
@@ -181,36 +209,8 @@
             return;
         }
 
-        X509CertImpl x509Cert = null;
-        try {
-            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
-        } catch (CertificateException ce) {
-            throw new CertPathValidatorException(ce);
-        }
-
-        PublicKey currPubKey = x509Cert.getPublicKey();
-        String currSigAlg = x509Cert.getSigAlgName();
-
-        AlgorithmId algorithmId = null;
-        try {
-            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
-        } catch (CertificateException ce) {
-            throw new CertPathValidatorException(ce);
-        }
-
-        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
-
-        // Check the current signature algorithm
-        if (!constraints.permits(
-                SIGNATURE_PRIMITIVE_SET,
-                currSigAlg, currSigAlgParams)) {
-            throw new CertPathValidatorException(
-                "Algorithm constraints check failed: " + currSigAlg,
-                null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
-        }
-
         // check the key usage and key size
-        boolean[] keyUsage = x509Cert.getKeyUsage();
+        boolean[] keyUsage = ((X509Certificate) cert).getKeyUsage();
         if (keyUsage != null && keyUsage.length < 9) {
             throw new CertPathValidatorException(
                 "incorrect KeyUsage extension",
@@ -248,27 +248,67 @@
 
             if (primitives.isEmpty()) {
                 throw new CertPathValidatorException(
-                    "incorrect KeyUsage extension",
+                    "incorrect KeyUsage extension bits",
                     null, null, -1, PKIXReason.INVALID_KEY_USAGE);
             }
         }
 
-        if (!constraints.permits(primitives, currPubKey)) {
-            throw new CertPathValidatorException(
-                "algorithm constraints check failed",
-                null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+        PublicKey currPubKey = cert.getPublicKey();
+
+        // Check against DisabledAlgorithmConstraints certpath constraints.
+        // permits() will throw exception on failure.
+        certPathDefaultConstraints.permits(primitives,
+                new CertConstraintParameters((X509Certificate)cert,
+                        trustedMatch));
+                // new CertConstraintParameters(x509Cert, trustedMatch));
+        // If there is no previous key, set one and exit
+        if (prevPubKey == null) {
+            prevPubKey = currPubKey;
+            return;
+        }
+
+        X509CertImpl x509Cert;
+        AlgorithmId algorithmId;
+        try {
+            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+            algorithmId = (AlgorithmId)x509Cert.get(X509CertImpl.SIG_ALG);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        AlgorithmParameters currSigAlgParams = algorithmId.getParameters();
+        String currSigAlg = x509Cert.getSigAlgName();
+
+        // If 'constraints' is not of DisabledAlgorithmConstraints, check all
+        // everything individually
+        if (!(constraints instanceof DisabledAlgorithmConstraints)) {
+            // Check the current signature algorithm
+            if (!constraints.permits(
+                    SIGNATURE_PRIMITIVE_SET,
+                    currSigAlg, currSigAlgParams)) {
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on signature " +
+                                "algorithm: " + currSigAlg, null, null, -1,
+                        BasicReason.ALGORITHM_CONSTRAINED);
+            }
+
+            if (!constraints.permits(primitives, currPubKey)) {
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on keysize: " +
+                                sun.security.util.KeyUtil.getKeySize(currPubKey),
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
         }
 
         // Check with previous cert for signature algorithm and public key
         if (prevPubKey != null) {
-            if (currSigAlg != null) {
-                if (!constraints.permits(
-                        SIGNATURE_PRIMITIVE_SET,
-                        currSigAlg, prevPubKey, currSigAlgParams)) {
-                    throw new CertPathValidatorException(
-                        "Algorithm constraints check failed: " + currSigAlg,
-                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
-                }
+            if (!constraints.permits(
+                    SIGNATURE_PRIMITIVE_SET,
+                    currSigAlg, prevPubKey, currSigAlgParams)) {
+                throw new CertPathValidatorException(
+                    "Algorithm constraints check failed on " +
+                            "signature algorithm: " + currSigAlg,
+                    null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
             }
 
             // Inherit key parameters from previous key
@@ -282,7 +322,7 @@
                 DSAParams params = ((DSAPublicKey)prevPubKey).getParams();
                 if (params == null) {
                     throw new CertPathValidatorException(
-                                    "Key parameters missing");
+                        "Key parameters missing from public key.");
                 }
 
                 try {
@@ -330,6 +370,11 @@
             // Don't bother to change the trustedPubKey.
             if (anchor.getTrustedCert() != null) {
                 prevPubKey = anchor.getTrustedCert().getPublicKey();
+                // Check for anchor certificate restrictions
+                trustedMatch = checkFingerprint(anchor.getTrustedCert());
+                if (trustedMatch && debug != null) {
+                    debug.println("trustedMatch = true");
+                }
             } else {
                 prevPubKey = anchor.getCAPublicKey();
             }
@@ -370,7 +415,8 @@
         if (!certPathDefaultConstraints.permits(
                 SIGNATURE_PRIMITIVE_SET, sigAlgName, key, sigAlgParams)) {
             throw new CertPathValidatorException(
-                "algorithm check failed: " + sigAlgName + " is disabled",
+                "Algorithm constraints check failed on signature algorithm: " +
+                sigAlgName + " is disabled",
                 null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java	Wed Jul 05 21:39:33 2017 +0200
@@ -131,8 +131,8 @@
 
                 } catch (CertPathValidatorException cpve) {
                     throw new CertPathValidatorException(cpve.getMessage(),
-                        cpve.getCause(), cpOriginal, cpSize - (i + 1),
-                        cpve.getReason());
+                        (cpve.getCause() != null) ? cpve.getCause() : cpve,
+                            cpOriginal, cpSize - (i + 1), cpve.getReason());
                 }
             }
 
--- a/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/AbstractAlgorithmConstraints.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.security.AlgorithmConstraints;
 import java.security.PrivilegedAction;
 import java.security.Security;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -45,8 +44,7 @@
     }
 
     // Get algorithm constraints from the specified security property.
-    private static void loadAlgorithmsMap(Map<String, String[]> algorithmsMap,
-            String propertyName) {
+    static String[] getAlgorithms(String propertyName) {
         String property = AccessController.doPrivileged(
                 (PrivilegedAction<String>) () -> Security.getProperty(
                         propertyName));
@@ -68,18 +66,7 @@
         if (algorithmsInProperty == null) {
             algorithmsInProperty = new String[0];
         }
-        algorithmsMap.put(propertyName, algorithmsInProperty);
-    }
-
-    static String[] getAlgorithms(Map<String, String[]> algorithmsMap,
-            String propertyName) {
-        synchronized (algorithmsMap) {
-            if (!algorithmsMap.containsKey(propertyName)) {
-                loadAlgorithmsMap(algorithmsMap, propertyName);
-            }
-
-            return algorithmsMap.get(propertyName);
-        }
+        return algorithmsInProperty;
     }
 
     static boolean checkAlgorithm(String[] algorithms, String algorithm,
--- a/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/AlgorithmDecomposer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,19 +40,7 @@
     private static final Pattern pattern =
             Pattern.compile("with|and|(?<!padd)in", Pattern.CASE_INSENSITIVE);
 
-    /**
-     * Decompose the standard algorithm name into sub-elements.
-     * <p>
-     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
-     * so that we can check the "SHA1" and "RSA" algorithm constraints
-     * separately.
-     * <p>
-     * Please override the method if need to support more name pattern.
-     */
-    public Set<String> decompose(String algorithm) {
-        if (algorithm == null || algorithm.length() == 0) {
-            return new HashSet<>();
-        }
+    private static Set<String> decomposeImpl(String algorithm) {
 
         // algorithm/mode/padding
         String[] transTockens = transPattern.split(algorithm);
@@ -79,6 +67,24 @@
                 elements.add(token);
             }
         }
+        return elements;
+    }
+
+    /**
+     * Decompose the standard algorithm name into sub-elements.
+     * <p>
+     * For example, we need to decompose "SHA1WithRSA" into "SHA1" and "RSA"
+     * so that we can check the "SHA1" and "RSA" algorithm constraints
+     * separately.
+     * <p>
+     * Please override the method if need to support more name pattern.
+     */
+    public Set<String> decompose(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<>();
+        }
+
+        Set<String> elements = decomposeImpl(algorithm);
 
         // In Java standard algorithm name specification, for different
         // purpose, the SHA-1 and SHA-2 algorithm names are different. For
@@ -130,4 +136,40 @@
         return elements;
     }
 
+    private static void hasLoop(Set<String> elements, String find, String replace) {
+        if (elements.contains(find)) {
+            if (!elements.contains(replace)) {
+                elements.add(replace);
+            }
+            elements.remove(find);
+        }
+    }
+
+    /*
+     * This decomposes a standard name into sub-elements with a consistent
+     * message digest algorithm name to avoid overly complicated checking.
+     */
+    public static Set<String> decomposeOneHash(String algorithm) {
+        if (algorithm == null || algorithm.length() == 0) {
+            return new HashSet<>();
+        }
+
+        Set<String> elements = decomposeImpl(algorithm);
+
+        hasLoop(elements, "SHA-1", "SHA1");
+        hasLoop(elements, "SHA-224", "SHA224");
+        hasLoop(elements, "SHA-256", "SHA256");
+        hasLoop(elements, "SHA-384", "SHA384");
+        hasLoop(elements, "SHA-512", "SHA512");
+
+        return elements;
+    }
+
+    /*
+     * The provided message digest algorithm name will return a consistent
+     * naming scheme.
+     */
+    public static String hashName(String algorithm) {
+        return algorithm.replace("-", "");
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/AnchorCertificates.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.security.AccessController;
+import java.security.KeyStore;
+import java.security.PrivilegedAction;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import java.util.HashSet;
+
+import sun.security.x509.X509CertImpl;
+
+/**
+ * The purpose of this class is to determine the trust anchor certificates is in
+ * the cacerts file.  This is used for PKIX CertPath checking.
+ */
+public class AnchorCertificates {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+    private static final String HASH = "SHA-256";
+    private static HashSet<String> certs;
+
+    static  {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                File f = new File(System.getProperty("java.home"),
+                        "lib/security/cacerts");
+                KeyStore cacerts;
+                try {
+                    cacerts = KeyStore.getInstance("JKS");
+                    try (FileInputStream fis = new FileInputStream(f)) {
+                        cacerts.load(fis, "changeit".toCharArray());
+                        certs = new HashSet<>();
+                        Enumeration<String> list = cacerts.aliases();
+                        String alias;
+                        while (list.hasMoreElements()) {
+                            alias = list.nextElement();
+                            // Check if this cert is labeled a trust anchor.
+                            if (alias.contains(" [jdk")) {
+                                X509Certificate cert = (X509Certificate) cacerts
+                                        .getCertificate(alias);
+                                certs.add(X509CertImpl.getFingerprint(HASH, cert));
+                            }
+                        }
+                    }
+                } catch (Exception e) {
+                    if (debug != null) {
+                        debug.println("Error parsing cacerts");
+                    }
+                    e.printStackTrace();
+                }
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Checks if a certificate is a trust anchor.
+     *
+     * @param cert the certificate to check
+     * @return true if the certificate is trusted.
+     */
+    public static boolean contains(X509Certificate cert) {
+        String key = X509CertImpl.getFingerprint(HASH, cert);
+        boolean result = certs.contains(key);
+        if (result && debug != null) {
+            debug.println("AnchorCertificate.contains: matched " +
+                    cert.getSubjectDN());
+        }
+        return result;
+    }
+
+    private AnchorCertificates() {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/sun/security/util/CertConstraintParameters.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+ */
+
+package sun.security.util;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This class is a wrapper for keeping state and passing objects between PKIX,
+ * AlgorithmChecker, and DisabledAlgorithmConstraints.
+ */
+public class CertConstraintParameters {
+    // A certificate being passed to check against constraints.
+    private final X509Certificate cert;
+
+    // This is true if the trust anchor in the certificate chain matches a cert
+    // in AnchorCertificates
+    private final boolean trustedMatch;
+
+    public CertConstraintParameters(X509Certificate c, boolean match) {
+        cert = c;
+        trustedMatch = match;
+    }
+
+    public CertConstraintParameters(X509Certificate c) {
+        this(c, false);
+    }
+
+    // Returns if the trust anchor has a match if anchor checking is enabled.
+    public boolean isTrustedMatch() {
+        return trustedMatch;
+    }
+
+    public X509Certificate getCertificate() {
+        return cert;
+    }
+}
--- a/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/DisabledAlgorithmConstraints.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,14 @@
 import java.security.CryptoPrimitive;
 import java.security.AlgorithmParameters;
 import java.security.Key;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.HashMap;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 
@@ -44,6 +46,7 @@
  * for the syntax of the disabled algorithm string.
  */
 public class DisabledAlgorithmConstraints extends AbstractAlgorithmConstraints {
+    private static final Debug debug = Debug.getInstance("certpath");
 
     // the known security property, jdk.certpath.disabledAlgorithms
     public static final String PROPERTY_CERTPATH_DISABLED_ALGS =
@@ -53,13 +56,8 @@
     public static final String PROPERTY_TLS_DISABLED_ALGS =
             "jdk.tls.disabledAlgorithms";
 
-    private static final Map<String, String[]> disabledAlgorithmsMap =
-                                                            new HashMap<>();
-    private static final Map<String, KeySizeConstraints> keySizeConstraintsMap =
-                                                            new HashMap<>();
-
     private final String[] disabledAlgorithms;
-    private final KeySizeConstraints keySizeConstraints;
+    private final Constraints algorithmConstraints;
 
     /**
      * Initialize algorithm constraints with the specified security property.
@@ -74,11 +72,14 @@
     public DisabledAlgorithmConstraints(String propertyName,
             AlgorithmDecomposer decomposer) {
         super(decomposer);
-        disabledAlgorithms = getAlgorithms(disabledAlgorithmsMap, propertyName);
-        keySizeConstraints = getKeySizeConstraints(disabledAlgorithms,
-                propertyName);
+        disabledAlgorithms = getAlgorithms(propertyName);
+        algorithmConstraints = new Constraints(disabledAlgorithms);
     }
 
+    /*
+     * This only checks if the algorithm has been completely disabled.  If
+     * there are keysize or other limit, this method allow the algorithm.
+     */
     @Override
     public final boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, AlgorithmParameters parameters) {
@@ -91,11 +92,19 @@
         return checkAlgorithm(disabledAlgorithms, algorithm, decomposer);
     }
 
+    /*
+     * Checks if the key algorithm has been disabled or constraints have been
+     * placed on the key.
+     */
     @Override
     public final boolean permits(Set<CryptoPrimitive> primitives, Key key) {
         return checkConstraints(primitives, "", key, null);
     }
 
+    /*
+     * Checks if the key algorithm has been disabled or if constraints have
+     * been placed on the key.
+     */
     @Override
     public final boolean permits(Set<CryptoPrimitive> primitives,
             String algorithm, Key key, AlgorithmParameters parameters) {
@@ -107,7 +116,39 @@
         return checkConstraints(primitives, algorithm, key, parameters);
     }
 
-    // Check algorithm constraints
+    /*
+     * Check if a x509Certificate object is permitted.  Check if all
+     * algorithms are allowed, certificate constraints, and the
+     * public key against key constraints.
+     *
+     * Uses new style permit() which throws exceptions.
+     */
+    public final void permits(Set<CryptoPrimitive> primitives,
+            CertConstraintParameters cp) throws CertPathValidatorException {
+        checkConstraints(primitives, cp);
+    }
+
+    /*
+     * Check if Certificate object is within the constraints.
+     * Uses new style permit() which throws exceptions.
+     */
+    public final void permits(Set<CryptoPrimitive> primitives,
+            X509Certificate cert) throws CertPathValidatorException {
+        checkConstraints(primitives, new CertConstraintParameters(cert));
+    }
+
+    // Check if a string is contained inside the property
+    public boolean checkProperty(String param) {
+        param = param.toLowerCase(Locale.ENGLISH);
+        for (String block : disabledAlgorithms) {
+            if (block.toLowerCase(Locale.ENGLISH).indexOf(param) >= 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // Check algorithm constraints with key and algorithm
     private boolean checkConstraints(Set<CryptoPrimitive> primitives,
             String algorithm, Key key, AlgorithmParameters parameters) {
 
@@ -116,7 +157,7 @@
             throw new IllegalArgumentException("The key cannot be null");
         }
 
-        // check the target algorithm
+        // check the signature algorithm
         if (algorithm != null && algorithm.length() != 0) {
             if (!permits(primitives, algorithm, parameters)) {
                 return false;
@@ -129,97 +170,203 @@
         }
 
         // check the key constraints
-        if (keySizeConstraints.disables(key)) {
-            return false;
-        }
-
-        return true;
+        return algorithmConstraints.permits(key);
     }
 
-    private static KeySizeConstraints getKeySizeConstraints(
-            String[] disabledAlgorithms, String propertyName) {
-        synchronized (keySizeConstraintsMap) {
-            if(!keySizeConstraintsMap.containsKey(propertyName)) {
-                // map the key constraints
-                KeySizeConstraints keySizeConstraints =
-                        new KeySizeConstraints(disabledAlgorithms);
-                keySizeConstraintsMap.put(propertyName, keySizeConstraints);
-            }
+    /*
+     * Check algorithm constraints with Certificate
+     * Uses new style permit() which throws exceptions.
+     */
+    private void checkConstraints(Set<CryptoPrimitive> primitives,
+            CertConstraintParameters cp) throws CertPathValidatorException {
+
+        X509Certificate cert = cp.getCertificate();
+        String algorithm = cert.getSigAlgName();
 
-            return keySizeConstraintsMap.get(propertyName);
+        // Check signature algorithm is not disabled
+        if (!permits(primitives, algorithm, null)) {
+            throw new CertPathValidatorException(
+                    "Algorithm constraints check failed on disabled "+
+                            "signature algorithm: " + algorithm,
+                    null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
         }
+
+        // Check key algorithm is not disabled
+        if (!permits(primitives, cert.getPublicKey().getAlgorithm(), null)) {
+            throw new CertPathValidatorException(
+                    "Algorithm constraints check failed on disabled "+
+                            "public key algorithm: " + algorithm,
+                    null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+        }
+
+        // Check the certificate and key constraints
+        algorithmConstraints.permits(cp);
+
     }
 
     /**
-     * key constraints
+     * Key and Certificate Constraints
+     *
+     * The complete disabling of an algorithm is not handled by Constraints or
+     * Constraint classes.  That is addressed with
+     *   permit(Set<CryptoPrimitive>, String, AlgorithmParameters)
+     *
+     * When passing a Key to permit(), the boolean return values follow the
+     * same as the interface class AlgorithmConstraints.permit().  This is to
+     * maintain compatibility:
+     * 'true' means the operation is allowed.
+     * 'false' means it failed the constraints and is disallowed.
+     *
+     * When passing CertConstraintParameters through permit(), an exception
+     * will be thrown on a failure to better identify why the operation was
+     * disallowed.
      */
-    private static class KeySizeConstraints {
-        private static final Pattern pattern = Pattern.compile(
-                "(\\S+)\\s+keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
 
-        private Map<String, Set<KeySizeConstraint>> constraintsMap =
-            Collections.synchronizedMap(
-                        new HashMap<String, Set<KeySizeConstraint>>());
+    private static class Constraints {
+        private Map<String, Set<Constraint>> constraintsMap = new HashMap<>();
+        private static final Pattern keySizePattern = Pattern.compile(
+                "keySize\\s*(<=|<|==|!=|>|>=)\\s*(\\d+)");
 
-        public KeySizeConstraints(String[] restrictions) {
-            for (String restriction : restrictions) {
-                if (restriction == null || restriction.isEmpty()) {
+        public Constraints(String[] constraintArray) {
+            for (String constraintEntry : constraintArray) {
+                if (constraintEntry == null || constraintEntry.isEmpty()) {
                     continue;
                 }
 
-                Matcher matcher = pattern.matcher(restriction);
-                if (matcher.matches()) {
-                    String algorithm = matcher.group(1);
+                constraintEntry = constraintEntry.trim();
+                if (debug != null) {
+                    debug.println("Constraints: " + constraintEntry);
+                }
 
-                    KeySizeConstraint.Operator operator =
-                             KeySizeConstraint.Operator.of(matcher.group(2));
-                    int length = Integer.parseInt(matcher.group(3));
+                // Check if constraint is a complete disabling of an
+                // algorithm or has conditions.
+                String algorithm;
+                String policy;
+                int space = constraintEntry.indexOf(' ');
+                if (space > 0) {
+                    algorithm = AlgorithmDecomposer.hashName(
+                            constraintEntry.substring(0, space).
+                                    toUpperCase(Locale.ENGLISH));
+                    policy = constraintEntry.substring(space + 1);
+                } else {
+                    constraintsMap.computeIfAbsent(
+                            constraintEntry.toUpperCase(Locale.ENGLISH),
+                            k -> new HashSet<>());
+                    continue;
+                }
 
-                    algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+                // Convert constraint conditions into Constraint classes
+                Constraint c, lastConstraint = null;
+                // Allow only one jdkCA entry per constraint entry
+                boolean jdkCALimit = false;
+
+                for (String entry : policy.split("&")) {
+                    entry = entry.trim();
 
-                    synchronized (constraintsMap) {
-                        if (!constraintsMap.containsKey(algorithm)) {
-                            constraintsMap.put(algorithm,
-                                new HashSet<KeySizeConstraint>());
+                    Matcher matcher = keySizePattern.matcher(entry);
+                    if (matcher.matches()) {
+                        if (debug != null) {
+                            debug.println("Constraints set to keySize: " +
+                                    entry);
                         }
+                        c = new KeySizeConstraint(algorithm,
+                                KeySizeConstraint.Operator.of(matcher.group(1)),
+                                Integer.parseInt(matcher.group(2)));
 
-                        Set<KeySizeConstraint> constraintSet =
-                            constraintsMap.get(algorithm);
-                        KeySizeConstraint constraint =
-                            new KeySizeConstraint(operator, length);
-                        constraintSet.add(constraint);
+                    } else if (entry.equalsIgnoreCase("jdkCA")) {
+                        if (debug != null) {
+                            debug.println("Constraints set to jdkCA.");
+                        }
+                        if (jdkCALimit) {
+                            throw new IllegalArgumentException("Only one " +
+                                    "jdkCA entry allowed in property. " +
+                                    "Constraint: " + constraintEntry);
+                        }
+                        c = new jdkCAConstraint(algorithm);
+                        jdkCALimit = true;
+                    } else {
+                        throw new IllegalArgumentException("Error in security" +
+                                " property. Constraint unknown: " + entry);
                     }
+
+                    // Link multiple conditions for a single constraint
+                    // into a linked list.
+                    if (lastConstraint == null) {
+                        if (!constraintsMap.containsKey(algorithm)) {
+                            constraintsMap.putIfAbsent(algorithm,
+                                    new HashSet<>());
+                        }
+                        constraintsMap.get(algorithm).add(c);
+                    } else {
+                        lastConstraint.nextConstraint = c;
+                    }
+                    lastConstraint = c;
                 }
             }
         }
 
-        // Does this KeySizeConstraints disable the specified key?
-        public boolean disables(Key key) {
-            String algorithm = key.getAlgorithm().toLowerCase(Locale.ENGLISH);
-            synchronized (constraintsMap) {
-                if (constraintsMap.containsKey(algorithm)) {
-                    Set<KeySizeConstraint> constraintSet =
-                                        constraintsMap.get(algorithm);
-                    for (KeySizeConstraint constraint : constraintSet) {
-                        if (constraint.disables(key)) {
-                            return true;
-                        }
+        // Get applicable constraints based off the signature algorithm
+        private Set<Constraint> getConstraints(String algorithm) {
+            return constraintsMap.get(algorithm);
+        }
+
+        // Check if KeySizeConstraints permit the specified key
+        public boolean permits(Key key) {
+            Set<Constraint> set = getConstraints(key.getAlgorithm());
+            if (set == null) {
+                return true;
+            }
+            for (Constraint constraint : set) {
+                if (!constraint.permits(key)) {
+                    if (debug != null) {
+                        debug.println("keySizeConstraint: failed key " +
+                                "constraint check " + KeyUtil.getKeySize(key));
                     }
+                    return false;
                 }
             }
+            return true;
+        }
 
-            return false;
+        // Check if constraints permit this cert.
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            X509Certificate cert = cp.getCertificate();
+
+            if (debug != null) {
+                debug.println("Constraints.permits(): " + cert.getSigAlgName());
+            }
+
+            // Get all signature algorithms to check for constraints
+            Set<String> algorithms =
+                    AlgorithmDecomposer.decomposeOneHash(cert.getSigAlgName());
+            if (algorithms == null || algorithms.isEmpty()) {
+                return;
+            }
+
+            // Attempt to add the public key algorithm to the set
+            algorithms.add(cert.getPublicKey().getAlgorithm());
+
+            // Check all applicable constraints
+            for (String algorithm : algorithms) {
+                Set<Constraint> set = getConstraints(algorithm);
+                if (set == null) {
+                    continue;
+                }
+                for (Constraint constraint : set) {
+                    constraint.permits(cp);
+                }
+            }
         }
     }
 
-    /**
-     * Key size constraint.
-     *
-     * e.g.  "keysize <= 1024"
-     */
-    private static class KeySizeConstraint {
+    // Abstract class for algorithm constraint checking
+    private abstract static class Constraint {
+        String algorithm;
+        Constraint nextConstraint = null;
+
         // operator
-        static enum Operator {
+        enum Operator {
             EQ,         // "=="
             NE,         // "!="
             LT,         // "<"
@@ -243,16 +390,77 @@
                         return GE;
                 }
 
-                throw new IllegalArgumentException(
-                        s + " is not a legal Operator");
+                throw new IllegalArgumentException("Error in security " +
+                        "property. " + s + " is not a legal Operator");
             }
         }
 
+        /**
+         * Check if an algorithm constraint permit this key to be used.
+         * @param key Public key
+         * @return true if constraints do not match
+         */
+        public boolean permits(Key key) {
+            return true;
+        }
+
+        /**
+         * Check if an algorithm constraint is permit this certificate to
+         * be used.
+         * @param cp CertificateParameter containing certificate and state info
+         * @return true if constraints do not match
+         */
+        public abstract void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException;
+    }
+
+    /*
+     * This class contains constraints dealing with the certificate chain
+     * of the certificate.
+     */
+    private static class jdkCAConstraint extends Constraint {
+        jdkCAConstraint(String algo) {
+            algorithm = algo;
+        }
+
+        /*
+         * Check if each constraint fails and check if there is a linked
+         * constraint  Any permitted constraint will exit the linked list
+         * to allow the operation.
+         */
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            if (debug != null) {
+                debug.println("jdkCAConstraints.permits(): " + algorithm);
+            }
+
+            // Return false if the chain has a trust anchor in cacerts
+            if (cp.isTrustedMatch()) {
+                if (nextConstraint != null) {
+                    nextConstraint.permits(cp);
+                    return;
+                }
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on certificate " +
+                                "anchor limits",
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
+        }
+    }
+
+
+    /*
+     * This class contains constraints dealing with the key size
+     * support limits per algorithm.   e.g.  "keySize <= 1024"
+     */
+    private static class KeySizeConstraint extends Constraint {
+
         private int minSize;            // the minimal available key size
         private int maxSize;            // the maximal available key size
         private int prohibitedSize = -1;    // unavailable key sizes
 
-        public KeySizeConstraint(Operator operator, int length) {
+        public KeySizeConstraint(String algo, Operator operator, int length) {
+            algorithm = algo;
             switch (operator) {
                 case EQ:      // an unavailable key size
                     this.minSize = 0;
@@ -286,21 +494,59 @@
             }
         }
 
-        // Does this key constraint disable the specified key?
-        public boolean disables(Key key) {
-            int size = KeyUtil.getKeySize(key);
+        /*
+         * If we are passed a certificate, extract the public key and use it.
+         *
+         * Check if each constraint fails and check if there is a linked
+         * constraint  Any permitted constraint will exit the linked list
+         * to allow the operation.
+         */
+        public void permits(CertConstraintParameters cp)
+                throws CertPathValidatorException {
+            if (!permitsImpl(cp.getCertificate().getPublicKey())) {
+                if (nextConstraint != null) {
+                    nextConstraint.permits(cp);
+                    return;
+                }
+                throw new CertPathValidatorException(
+                        "Algorithm constraints check failed on keysize limits",
+                        null, null, -1, BasicReason.ALGORITHM_CONSTRAINED);
+            }
+        }
+
 
+        // Check if key constraint disable the specified key
+        // Uses old style permit()
+        public boolean permits(Key key) {
+            // If we recursively find a constraint that permits us to use
+            // this key, return true and skip any other constraint checks.
+            if (nextConstraint != null && nextConstraint.permits(key)) {
+                return true;
+            }
+            if (debug != null) {
+                debug.println("KeySizeConstraints.permits(): " + algorithm);
+            }
+
+            return permitsImpl(key);
+        }
+
+        private boolean permitsImpl(Key key) {
+            // Verify this constraint is for this public key algorithm
+            if (algorithm.compareToIgnoreCase(key.getAlgorithm()) != 0) {
+                return true;
+            }
+
+            int size = KeyUtil.getKeySize(key);
             if (size == 0) {
-                return true;    // we don't allow any key of size 0.
+                return false;    // we don't allow any key of size 0.
             } else if (size > 0) {
-                return ((size < minSize) || (size > maxSize) ||
+                return !((size < minSize) || (size > maxSize) ||
                     (prohibitedSize == size));
             }   // Otherwise, the key size is not accessible. Conservatively,
                 // please don't disable such keys.
 
-            return false;
+            return true;
         }
     }
-
 }
 
--- a/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/util/LegacyAlgorithmConstraints.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,8 +28,6 @@
 import java.security.AlgorithmParameters;
 import java.security.CryptoPrimitive;
 import java.security.Key;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Set;
 import static sun.security.util.AbstractAlgorithmConstraints.getAlgorithms;
 
@@ -42,15 +40,12 @@
     public static final String PROPERTY_TLS_LEGACY_ALGS =
             "jdk.tls.legacyAlgorithms";
 
-    private static final Map<String, String[]> legacyAlgorithmsMap =
-                                                          new HashMap<>();
-
     private final String[] legacyAlgorithms;
 
     public LegacyAlgorithmConstraints(String propertyName,
             AlgorithmDecomposer decomposer) {
         super(decomposer);
-        legacyAlgorithms = getAlgorithms(legacyAlgorithmsMap, propertyName);
+        legacyAlgorithms = getAlgorithms(propertyName);
     }
 
     @Override
--- a/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/security/x509/X509CertImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -1924,17 +1924,18 @@
 
     public String getFingerprint(String algorithm) {
         return fingerprints.computeIfAbsent(algorithm,
-                x -> getCertificateFingerPrint(x));
+            x -> getFingerprint(x, this));
     }
 
     /**
      * Gets the requested finger print of the certificate. The result
      * only contains 0-9 and A-F. No small case, no colon.
      */
-    private String getCertificateFingerPrint(String mdAlg) {
+    public static String getFingerprint(String algorithm,
+            X509Certificate cert) {
         try {
-            byte[] encCertInfo = getEncoded();
-            MessageDigest md = MessageDigest.getInstance(mdAlg);
+            byte[] encCertInfo = cert.getEncoded();
+            MessageDigest md = MessageDigest.getInstance(algorithm);
             byte[] digest = md.digest(encCertInfo);
             StringBuilder sb = new StringBuilder(digest.length * 2);
             for (int i = 0; i < digest.length; i++) {
--- a/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 21:39:33 2017 +0200
@@ -286,12 +286,15 @@
         }
         if (log == null) {
             log = new PlatformLogger(PlatformLogger.Bridge.convert(
-                    // We pass PlatformLogger.class rather than the actual caller
+                    // We pass PlatformLogger.class.getModule() (java.base)
+                    // rather than the actual module of the caller
                     // because we want PlatformLoggers to be system loggers: we
                     // won't need to resolve any resource bundles anyway.
                     // Note: Many unit tests depend on the fact that
-                    //       PlatformLogger.getLoggerFromFinder is not caller sensitive.
-                    LazyLoggers.getLazyLogger(name, PlatformLogger.class)));
+                    //       PlatformLogger.getLoggerFromFinder is not caller
+                    //       sensitive, and this strategy ensure that the tests
+                    //       still pass.
+                    LazyLoggers.getLazyLogger(name, PlatformLogger.class.getModule())));
             loggers.put(name, new WeakReference<>(log));
         }
         return log;
--- a/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/share/conf/security/java.security	Wed Jul 05 21:39:33 2017 +0200
@@ -497,13 +497,13 @@
 #       " DisabledAlgorithm { , DisabledAlgorithm } "
 #
 #   DisabledAlgorithm:
-#       AlgorithmName [Constraint]
+#       AlgorithmName [Constraint] { '&' Constraint }
 #
 #   AlgorithmName:
 #       (see below)
 #
 #   Constraint:
-#       KeySizeConstraint
+#       KeySizeConstraint, CertConstraint
 #
 #   KeySizeConstraint:
 #       keySize Operator DecimalInteger
@@ -520,6 +520,9 @@
 #   DecimalDigit: one of
 #       1 2 3 4 5 6 7 8 9 0
 #
+#   CertConstraint
+#       jdkCA
+#
 # The "AlgorithmName" is the standard algorithm name of the disabled
 # algorithm. See "Java Cryptography Architecture Standard Algorithm Name
 # Documentation" for information about Standard Algorithm Names.  Matching
@@ -542,6 +545,29 @@
 # be disabled. Note that the "KeySizeConstraint" only makes sense to key
 # algorithms.
 #
+# "CertConstraint" specifies additional constraints for
+# certificates that contain algorithms that are restricted:
+#
+#   "jdkCA" prohibits the specified algorithm only if the algorithm is used
+#     in a certificate chain that terminates at a marked trust anchor in the
+#     lib/security/cacerts keystore.  All other chains are not affected.
+#     If the jdkCA constraint is not set, then all chains using the
+#     specified algorithm are restricted.  jdkCA may only be used once in
+#     a DisabledAlgorithm expression.
+#     Example:  To apply this constraint to SHA-1 certificates, include
+#     the following:  "SHA1 jdkCA"
+#
+# When an algorithm must satisfy more than one constraint, it must be
+# delimited by an ampersand '&'.  For example, to restrict certificates in a
+# chain that terminate at a distribution provided trust anchor and contain
+# RSA keys that are less than or equal to 1024 bits, add the following
+# constraint:  "RSA keySize <= 1024 & jdkCA".
+#
+# All DisabledAlgorithms expressions are processed in the order defined in the
+# property.  This requires lower keysize constraints to be specified
+# before larger keysize constraints of the same algorithm.  For example:
+# "RSA keySize < 1024 & jdkCA, RSA keySize < 2048".
+#
 # Note: This property is currently used by Oracle's PKIX implementation. It
 # is not guaranteed to be examined and used by other implementations.
 #
--- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -27,9 +27,7 @@
 import java.io.IOException;
 import java.util.Set;
 import java.util.HashSet;
-import java.util.Collections;
-import jdk.net.*;
-import static sun.net.ExtendedOptionsImpl.*;
+import sun.net.ext.ExtendedSocketOptions;
 
 /*
  * On Unix systems we simply delegate to native methods.
@@ -43,8 +41,11 @@
         init();
     }
 
+    static final ExtendedSocketOptions extendedOptions =
+            ExtendedSocketOptions.getInstance();
+
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
-        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+        if (!extendedOptions.isOptionSupported(name)) {
             if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
                 super.setOption(name, value);
             } else {
@@ -55,21 +56,16 @@
                }
             }
         } else {
-            if (!flowSupported()) {
-                throw new UnsupportedOperationException("unsupported option");
-            }
             if (isClosed()) {
                 throw new SocketException("Socket closed");
             }
-            checkSetOptionPermission(name);
-            checkValueType(value, SocketFlow.class);
-            setFlowOption(getFileDescriptor(), (SocketFlow)value);
+            extendedOptions.setOption(fd, name, value);
         }
     }
 
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
-        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+        if (!extendedOptions.isOptionSupported(name)) {
             if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
                 return super.getOption(name);
             } else {
@@ -79,31 +75,23 @@
                     throw new UnsupportedOperationException("unsupported option");
                 }
             }
-        }
-        if (!flowSupported()) {
-            throw new UnsupportedOperationException("unsupported option");
+        } else {
+            if (isClosed()) {
+                throw new SocketException("Socket closed");
+            }
+            return (T) extendedOptions.getOption(fd, name);
         }
-        if (isClosed()) {
-            throw new SocketException("Socket closed");
-        }
-        checkGetOptionPermission(name);
-        SocketFlow flow = SocketFlow.create();
-        getFlowOption(getFileDescriptor(), flow);
-        return (T)flow;
     }
 
     protected Set<SocketOption<?>> supportedOptions() {
-        HashSet<SocketOption<?>> options = new HashSet<>(
-            super.supportedOptions());
-
-        if (flowSupported()) {
-            options.add(ExtendedSocketOptions.SO_FLOW_SLA);
-        }
+        HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
+        options.addAll(extendedOptions.options());
         return options;
     }
 
     protected void socketSetOption(int opt, Object val) throws SocketException {
-        if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+        if (opt == SocketOptions.SO_REUSEPORT &&
+            !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
             throw new UnsupportedOperationException("unsupported option");
         }
         try {
--- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,10 +28,7 @@
 import java.io.FileDescriptor;
 import java.util.Set;
 import java.util.HashSet;
-import java.util.Collections;
-import jdk.net.*;
-
-import static sun.net.ExtendedOptionsImpl.*;
+import sun.net.ext.ExtendedSocketOptions;
 
 /*
  * On Unix systems we simply delegate to native methods.
@@ -57,8 +54,11 @@
         this.fd = fd;
     }
 
+    static final ExtendedSocketOptions extendedOptions =
+            ExtendedSocketOptions.getInstance();
+
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
-        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+        if (!extendedOptions.isOptionSupported(name)) {
             if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
                 super.setOption(name, value);
             } else {
@@ -69,21 +69,19 @@
                 }
             }
         } else {
-            if (getSocket() == null || !flowSupported()) {
+            if (getSocket() == null) {
                 throw new UnsupportedOperationException("unsupported option");
             }
             if (isClosedOrPending()) {
                 throw new SocketException("Socket closed");
             }
-            checkSetOptionPermission(name);
-            checkValueType(value, SocketFlow.class);
-            setFlowOption(getFileDescriptor(), (SocketFlow)value);
+            extendedOptions.setOption(fd, name, value);
         }
     }
 
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
-        if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
+        if (!extendedOptions.isOptionSupported(name)) {
             if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
                 return super.getOption(name);
             } else {
@@ -93,31 +91,28 @@
                     throw new UnsupportedOperationException("unsupported option");
                 }
             }
-        }
-        if (getSocket() == null || !flowSupported()) {
-            throw new UnsupportedOperationException("unsupported option");
+        } else {
+            if (getSocket() == null) {
+                throw new UnsupportedOperationException("unsupported option");
+            }
+            if (isClosedOrPending()) {
+                throw new SocketException("Socket closed");
+            }
+            return (T) extendedOptions.getOption(fd, name);
         }
-        if (isClosedOrPending()) {
-            throw new SocketException("Socket closed");
-        }
-        checkGetOptionPermission(name);
-        SocketFlow flow = SocketFlow.create();
-        getFlowOption(getFileDescriptor(), flow);
-        return (T)flow;
     }
 
     protected Set<SocketOption<?>> supportedOptions() {
-        HashSet<SocketOption<?>> options = new HashSet<>(
-            super.supportedOptions());
-
-        if (getSocket() != null && flowSupported()) {
-            options.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
+        if (getSocket() != null) {
+            options.addAll(extendedOptions.options());
         }
         return options;
     }
 
     protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
-        if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+        if (opt == SocketOptions.SO_REUSEPORT &&
+            !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
             throw new UnsupportedOperationException("unsupported option");
         }
         try {
--- a/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,6 @@
 import java.nio.channels.*;
 import java.nio.channels.spi.*;
 import java.util.*;
-import sun.misc.*;
 
 
 /**
--- a/jdk/src/java.base/unix/native/libnet/ExtendedOptionsImpl.c	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <jni.h>
-#include <string.h>
-
-#include "net_util.h"
-#include "jdk_net_SocketFlow.h"
-
-static jclass sf_status_class;          /* Status enum type */
-
-static jfieldID sf_status;
-static jfieldID sf_priority;
-static jfieldID sf_bandwidth;
-
-static jfieldID sf_fd_fdID;             /* FileDescriptor.fd */
-
-/* References to the literal enum values */
-
-static jobject sfs_NOSTATUS;
-static jobject sfs_OK;
-static jobject sfs_NOPERMISSION;
-static jobject sfs_NOTCONNECTED;
-static jobject sfs_NOTSUPPORTED;
-static jobject sfs_ALREADYCREATED;
-static jobject sfs_INPROGRESS;
-static jobject sfs_OTHER;
-
-static jobject getEnumField(JNIEnv *env, char *name);
-static void setStatus(JNIEnv *env, jobject obj, int errval);
-
-/* OS specific code is implemented in these three functions */
-
-static jboolean flowSupported0() ;
-
-/*
- * Class:     sun_net_ExtendedOptionsImpl
- * Method:    init
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
-  (JNIEnv *env, jclass UNUSED)
-{
-    static int initialized = 0;
-    jclass c;
-
-    /* Global class references */
-
-    if (initialized) {
-        return;
-    }
-
-    c = (*env)->FindClass(env, "jdk/net/SocketFlow$Status");
-    CHECK_NULL(c);
-    sf_status_class = (*env)->NewGlobalRef(env, c);
-    CHECK_NULL(sf_status_class);
-
-    /* int "fd" field of java.io.FileDescriptor  */
-
-    c = (*env)->FindClass(env, "java/io/FileDescriptor");
-    CHECK_NULL(c);
-    sf_fd_fdID = (*env)->GetFieldID(env, c, "fd", "I");
-    CHECK_NULL(sf_fd_fdID);
-
-
-    /* SocketFlow fields */
-
-    c = (*env)->FindClass(env, "jdk/net/SocketFlow");
-    CHECK_NULL(c);
-
-    /* status */
-
-    sf_status = (*env)->GetFieldID(env, c, "status",
-                                        "Ljdk/net/SocketFlow$Status;");
-    CHECK_NULL(sf_status);
-
-    /* priority */
-
-    sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
-    CHECK_NULL(sf_priority);
-
-    /* bandwidth */
-
-    sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
-    CHECK_NULL(sf_bandwidth);
-
-    /* Initialize the static enum values */
-
-    sfs_NOSTATUS = getEnumField(env, "NO_STATUS");
-    CHECK_NULL(sfs_NOSTATUS);
-    sfs_OK = getEnumField(env, "OK");
-    CHECK_NULL(sfs_OK);
-    sfs_NOPERMISSION = getEnumField(env, "NO_PERMISSION");
-    CHECK_NULL(sfs_NOPERMISSION);
-    sfs_NOTCONNECTED = getEnumField(env, "NOT_CONNECTED");
-    CHECK_NULL(sfs_NOTCONNECTED);
-    sfs_NOTSUPPORTED = getEnumField(env, "NOT_SUPPORTED");
-    CHECK_NULL(sfs_NOTSUPPORTED);
-    sfs_ALREADYCREATED = getEnumField(env, "ALREADY_CREATED");
-    CHECK_NULL(sfs_ALREADYCREATED);
-    sfs_INPROGRESS = getEnumField(env, "IN_PROGRESS");
-    CHECK_NULL(sfs_INPROGRESS);
-    sfs_OTHER = getEnumField(env, "OTHER");
-    CHECK_NULL(sfs_OTHER);
-    initialized = JNI_TRUE;
-}
-
-static jobject getEnumField(JNIEnv *env, char *name)
-{
-    jobject f;
-    jfieldID fID = (*env)->GetStaticFieldID(env, sf_status_class, name,
-        "Ljdk/net/SocketFlow$Status;");
-    CHECK_NULL_RETURN(fID, NULL);
-
-    f = (*env)->GetStaticObjectField(env, sf_status_class, fID);
-    CHECK_NULL_RETURN(f, NULL);
-    f  = (*env)->NewGlobalRef(env, f);
-    CHECK_NULL_RETURN(f, NULL);
-    return f;
-}
-
-/*
- * Retrieve the int file-descriptor from a public socket type object.
- * Gets impl, then the FileDescriptor from the impl, and then the fd
- * from that.
- */
-static int getFD(JNIEnv *env, jobject fileDesc) {
-    return (*env)->GetIntField(env, fileDesc, sf_fd_fdID);
-}
-
-/**
- * Sets the status field of a SocketFlow to one of the
- * canned enum values
- */
-static void setStatus (JNIEnv *env, jobject obj, int errval)
-{
-    switch (errval) {
-      case 0: /* OK */
-        (*env)->SetObjectField(env, obj, sf_status, sfs_OK);
-        break;
-      case EPERM:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_NOPERMISSION);
-        break;
-      case ENOTCONN:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_NOTCONNECTED);
-        break;
-      case EOPNOTSUPP:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_NOTSUPPORTED);
-        break;
-      case EALREADY:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_ALREADYCREATED);
-        break;
-      case EINPROGRESS:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_INPROGRESS);
-        break;
-      default:
-        (*env)->SetObjectField(env, obj, sf_status, sfs_OTHER);
-        break;
-    }
-}
-
-#ifdef __solaris__
-
-/*
- * Class:     sun_net_ExtendedOptionsImpl
- * Method:    setFlowOption
- * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
- */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    int fd = getFD(env, fileDesc);
-
-    if (fd < 0) {
-        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
-        return;
-    } else {
-        sock_flow_props_t props;
-        jlong bandwidth;
-        int rv;
-
-        jint priority = (*env)->GetIntField(env, flow, sf_priority);
-        memset(&props, 0, sizeof(props));
-        props.sfp_version = SOCK_FLOW_PROP_VERSION1;
-
-        if (priority != jdk_net_SocketFlow_UNSET) {
-            props.sfp_mask |= SFP_PRIORITY;
-            props.sfp_priority = priority;
-        }
-        bandwidth = (*env)->GetLongField(env, flow, sf_bandwidth);
-        if (bandwidth > -1)  {
-            props.sfp_mask |= SFP_MAXBW;
-            props.sfp_maxbw = (uint64_t) bandwidth;
-        }
-        rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
-        if (rv < 0) {
-            if (errno == ENOPROTOOPT) {
-                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-                        "unsupported socket option");
-            } else if (errno == EACCES || errno == EPERM) {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "Permission denied");
-            } else {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "set option SO_FLOW_SLA failed");
-            }
-            return;
-        }
-        setStatus(env, flow, props.sfp_status);
-    }
-}
-
-/*
- * Class:     sun_net_ExtendedOptionsImpl
- * Method:    getFlowOption
- * Signature: (Ljava/io/FileDescriptor;Ljdk/net/SocketFlow;)V
- */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    int fd = getFD(env, fileDesc);
-
-    if (fd < 0) {
-        NET_ERROR(env, JNU_JAVANETPKG "SocketException", "socket closed");
-        return;
-    } else {
-        sock_flow_props_t props;
-        int status;
-        socklen_t sz = sizeof(props);
-
-        int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz);
-        if (rv < 0) {
-            if (errno == ENOPROTOOPT) {
-                JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-                        "unsupported socket option");
-            } else if (errno == EACCES || errno == EPERM) {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "Permission denied");
-            } else {
-                NET_ERROR(env, JNU_JAVANETPKG "SocketException",
-                                "set option SO_FLOW_SLA failed");
-            }
-            return;
-        }
-        /* first check status to see if flow exists */
-        status = props.sfp_status;
-        setStatus(env, flow, status);
-        if (status == 0) { /* OK */
-            /* can set the other fields now */
-            if (props.sfp_mask & SFP_PRIORITY) {
-                (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority);
-            }
-            if (props.sfp_mask & SFP_MAXBW) {
-                (*env)->SetLongField(env, flow, sf_bandwidth,
-                                        (jlong)props.sfp_maxbw);
-            }
-        }
-    }
-}
-
-static jboolean flowsupported;
-static jboolean flowsupported_set = JNI_FALSE;
-
-static jboolean flowSupported0()
-{
-    /* Do a simple dummy call, and try to figure out from that */
-    sock_flow_props_t props;
-    int rv, s;
-    if (flowsupported_set) {
-        return flowsupported;
-    }
-    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    if (s < 0) {
-        flowsupported = JNI_FALSE;
-        flowsupported_set = JNI_TRUE;
-        return JNI_FALSE;
-    }
-    memset(&props, 0, sizeof(props));
-    props.sfp_version = SOCK_FLOW_PROP_VERSION1;
-    props.sfp_mask |= SFP_PRIORITY;
-    props.sfp_priority = SFP_PRIO_NORMAL;
-    rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
-    if (rv != 0 && errno == ENOPROTOOPT) {
-        rv = JNI_FALSE;
-    } else {
-        rv = JNI_TRUE;
-    }
-    close(s);
-    flowsupported = rv;
-    flowsupported_set = JNI_TRUE;
-    return flowsupported;
-}
-
-#else /* __solaris__ */
-
-/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
-
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-        "unsupported socket option");
-}
-
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-        "unsupported socket option");
-}
-
-static jboolean flowSupported0()  {
-    return JNI_FALSE;
-}
-
-#endif /* __solaris__ */
-
-JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
-  (JNIEnv *env, jclass UNUSED)
-{
-    return flowSupported0();
-}
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h	Wed Jul 05 21:39:33 2017 +0200
@@ -120,47 +120,6 @@
 
 #ifdef __solaris__
 int net_getParam(char *driver, char *param);
-
-#ifndef SO_FLOW_SLA
-#define SO_FLOW_SLA 0x1018
-
-#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
-#pragma pack(4)
 #endif
 
-/*
- * Used with the setsockopt(SO_FLOW_SLA, ...) call to set
- * per socket service level properties.
- * When the application uses per-socket API, we will enforce the properties
- * on both outbound and inbound packets.
- *
- * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1.
- */
-typedef struct sock_flow_props_s {
-        int             sfp_version;
-        uint32_t        sfp_mask;
-        int             sfp_priority;   /* flow priority */
-        uint64_t        sfp_maxbw;      /* bandwidth limit in bps */
-        int             sfp_status;     /* flow create status for getsockopt */
-} sock_flow_props_t;
-
-#define SOCK_FLOW_PROP_VERSION1 1
-
-/* bit mask values for sfp_mask */
-#define SFP_MAXBW       0x00000001      /* Flow Bandwidth Limit */
-#define SFP_PRIORITY    0x00000008      /* Flow priority */
-
-/* possible values for sfp_priority */
-#define SFP_PRIO_NORMAL 1
-#define SFP_PRIO_HIGH   2
-
-#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
-#pragma pack()
-#endif /* _LONG_LONG_ALIGNMENT */
-
-#endif /* SO_FLOW_SLA */
-#endif /* __solaris__ */
-
-JNIEXPORT jboolean JNICALL NET_IsFlowSupported();
-
 #endif /* NET_UTILS_MD_H */
--- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java	Wed Jul 05 21:39:33 2017 +0200
@@ -113,6 +113,10 @@
         // completion key (used to map I/O completion to WatchKey)
         private int completionKey;
 
+        // flag indicates that ReadDirectoryChangesW failed
+        // and overlapped I/O operation wasn't started
+        private boolean errorStartingOverlapped;
+
         WindowsWatchKey(Path dir,
                         AbstractWatchService watcher,
                         FileKey fileKey)
@@ -175,6 +179,14 @@
             return completionKey;
         }
 
+        void setErrorStartingOverlapped(boolean value) {
+            errorStartingOverlapped = value;
+        }
+
+        boolean isErrorStartingOverlapped() {
+            return errorStartingOverlapped;
+        }
+
         // Invalidate the key, assumes that resources have been released
         void invalidate() {
             ((WindowsWatchService)watcher()).poller.releaseResources(this);
@@ -182,6 +194,7 @@
             buffer = null;
             countAddress = 0;
             overlappedAddress = 0;
+            errorStartingOverlapped = false;
         }
 
         @Override
@@ -455,11 +468,13 @@
          * resources.
          */
         private void releaseResources(WindowsWatchKey key) {
-            try {
-                CancelIo(key.handle());
-                GetOverlappedResult(key.handle(), key.overlappedAddress());
-            } catch (WindowsException expected) {
-                // expected as I/O operation has been cancelled
+            if (!key.isErrorStartingOverlapped()) {
+                try {
+                    CancelIo(key.handle());
+                    GetOverlappedResult(key.handle(), key.overlappedAddress());
+                } catch (WindowsException expected) {
+                    // expected as I/O operation has been cancelled
+                }
             }
             CloseHandle(key.handle());
             closeAttachedEvent(key.overlappedAddress());
@@ -628,6 +643,7 @@
                     } catch (WindowsException x) {
                         // no choice but to cancel key
                         criticalError = true;
+                        key.setErrorStartingOverlapped(true);
                     }
                 }
                 if (criticalError) {
--- a/jdk/src/java.base/windows/native/libnet/ExtendedOptionsImpl.c	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <jni.h>
-#include <string.h>
-
-#include "net_util.h"
-
-/*
- * Class:     sun_net_ExtendedOptionsImpl
- * Method:    init
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_init
-  (JNIEnv *env, jclass UNUSED)
-{
-}
-
-/* Non Solaris. Functionality is not supported. So, throw UnsupportedOpExc */
-
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_setFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-        "unsupported socket option");
-}
-
-JNIEXPORT void JNICALL Java_sun_net_ExtendedOptionsImpl_getFlowOption
-  (JNIEnv *env, jclass UNUSED, jobject fileDesc, jobject flow)
-{
-    JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
-        "unsupported socket option");
-}
-
-static jboolean flowSupported0()  {
-    return JNI_FALSE;
-}
-
-JNIEXPORT jboolean JNICALL Java_sun_net_ExtendedOptionsImpl_flowSupported
-  (JNIEnv *env, jclass UNUSED)
-{
-    return JNI_FALSE;
-}
--- a/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/eawt/_AppMenuBarHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -83,7 +83,7 @@
 
         // if we have no foreground frames, then we have to "kick" the menubar
         final JFrame pingFrame = new JFrame();
-        pingFrame.getRootPane().putClientProperty("Window.alpha", new Float(0.0f));
+        pingFrame.getRootPane().putClientProperty("Window.alpha", Float.valueOf(0.0f));
         pingFrame.setUndecorated(true);
         pingFrame.setVisible(true);
         pingFrame.toFront();
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaComboBoxPopup.java	Wed Jul 05 21:39:33 2017 +0200
@@ -58,7 +58,7 @@
         updateContents(false);
 
         // TODO: CPlatformWindow?
-        putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, new Integer(150));
+        putClientProperty(CPlatformWindow.WINDOW_FADE_OUT, Integer.valueOf(150));
     }
 
     public void updateContents(final boolean remove) {
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFramePaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -91,7 +91,7 @@
     JComponent getDock() {
         if (fDock == null) {
             fDock = new Dock(desktop);
-            desktop.add(fDock, new Integer(399)); // Just below the DRAG_LAYER
+            desktop.add(fDock, Integer.valueOf(399)); // Just below the DRAG_LAYER
         }
         return fDock;
     }
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaLookAndFeel.java	Wed Jul 05 21:39:33 2017 +0200
@@ -416,7 +416,7 @@
             "Button.select", selected,
             "Button.border",(LazyValue) t -> AquaButtonBorder.getDynamicButtonBorder(),
             "Button.font", controlFont,
-            "Button.textIconGap", new Integer(4),
+            "Button.textIconGap", Integer.valueOf(4),
             "Button.textShiftOffset", zero, // radar 3308129 - aqua doesn't move images when pressed.
             "Button.focusInputMap", controlFocusInputMap,
             "Button.margin", new InsetsUIResource(0, 2, 0, 2),
@@ -635,8 +635,8 @@
             //"Menu.checkIcon", emptyCheckIcon, // A non-drawing GlyphIcon to make the spacing consistent
             "Menu.arrowIcon",(LazyValue) t -> AquaImageFactory.getMenuArrowIcon(),
             "Menu.consumesTabs", Boolean.TRUE,
-            "Menu.menuPopupOffsetY", new Integer(1),
-            "Menu.submenuPopupOffsetY", new Integer(-4),
+            "Menu.menuPopupOffsetY", Integer.valueOf(1),
+            "Menu.submenuPopupOffsetY", Integer.valueOf(-4),
 
             "MenuBar.font", menuFont,
             "MenuBar.background", menuBackgroundColor, // not a menu item, not selected
@@ -694,7 +694,7 @@
             "OptionPane.informationSound", null, // Info and Plain
             "OptionPane.questionSound", null,
             "OptionPane.warningSound", null,
-            "OptionPane.buttonClickThreshhold", new Integer(500),
+            "OptionPane.buttonClickThreshhold", Integer.valueOf(500),
             "OptionPane.yesButtonMnemonic", "",
             "OptionPane.noButtonMnemonic", "",
             "OptionPane.okButtonMnemonic", "",
@@ -717,7 +717,7 @@
             "PasswordField.caretBlinkRate", textCaretBlinkRate,
             "PasswordField.border", textFieldBorder,
             "PasswordField.margin", zeroInsets,
-            "PasswordField.echoChar", new Character((char)0x25CF),
+            "PasswordField.echoChar", Character.valueOf((char)0x25CF),
             "PasswordField.capsLockIconColor", textPasswordFieldCapsLockIconColor,
 
             "PopupMenu.font", menuFont,
@@ -736,7 +736,7 @@
             "ProgressBar.selectionForeground", black,
             "ProgressBar.selectionBackground", white,
             "ProgressBar.border", new BorderUIResource(BorderFactory.createEmptyBorder()),
-            "ProgressBar.repaintInterval", new Integer(20),
+            "ProgressBar.repaintInterval", Integer.valueOf(20),
 
             "RadioButton.background", controlBackgroundColor,
             "RadioButton.foreground", black,
@@ -772,7 +772,7 @@
             "ScrollBar.border", null,
             "ScrollBar.focusInputMap", aquaKeyBindings.getScrollBarInputMap(),
             "ScrollBar.focusInputMap.RightToLeft", aquaKeyBindings.getScrollBarRightToLeftInputMap(),
-            "ScrollBar.width", new Integer(16),
+            "ScrollBar.width", Integer.valueOf(16),
             "ScrollBar.background", white,
             "ScrollBar.foreground", black,
 
@@ -816,7 +816,7 @@
             //"SplitPane.shadow", table.get("controlShadow"),
             "SplitPane.background", panelBackgroundColor,
             "SplitPane.border", scollListBorder,
-            "SplitPane.dividerSize", new Integer(9), //$
+            "SplitPane.dividerSize", Integer.valueOf(9), //$
             "SplitPaneDivider.border", null, // AquaSplitPaneDividerUI draws it
             "SplitPaneDivider.horizontalGradientVariant",(LazyValue) t -> AquaSplitPaneDividerUI.getHorizontalSplitDividerGradientVariant(),
 
@@ -833,7 +833,7 @@
             //"TabbedPane.darkShadow", table.get("controlDkShadow"),
             //"TabbedPane.focus", table.get("controlText"),
             "TabbedPane.opaque", useOpaqueComponents,
-            "TabbedPane.textIconGap", new Integer(4),
+            "TabbedPane.textIconGap", Integer.valueOf(4),
             "TabbedPane.tabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right)
             //"TabbedPane.rightTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab (top, left, bottom, right)
             "TabbedPane.leftTabInsets", new InsetsUIResource(0, 10, 3, 10), // Label within tab
@@ -973,9 +973,9 @@
             "Tree.selectionBorderColor", selectionBackground, // match the background so it looks like we don't draw anything
             "Tree.editorBorderSelectionColor", null, // The EditTextFrame provides its own border
             // "Tree.editorBorder", textFieldBorder, // If you still have Sun bug 4376328 in DefaultTreeCellEditor, it has to have the same insets as TextField.border
-            "Tree.leftChildIndent", new Integer(7),//$
-            "Tree.rightChildIndent", new Integer(13),//$
-            "Tree.rowHeight", new Integer(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching
+            "Tree.leftChildIndent", Integer.valueOf(7),//$
+            "Tree.rightChildIndent", Integer.valueOf(13),//$
+            "Tree.rowHeight", Integer.valueOf(19),// iconHeight + 3, to match finder - a zero would have the renderer decide, except that leaves the icons touching
             "Tree.scrollsOnExpand", Boolean.FALSE,
             "Tree.openIcon",(LazyValue) t -> AquaImageFactory.getTreeOpenFolderIcon(), // Open folder icon
             "Tree.closedIcon",(LazyValue) t -> AquaImageFactory.getTreeFolderIcon(), // Closed folder icon
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -521,7 +521,7 @@
         }
         // [2165820] Mac OS X change: mnemonics need to be triggered with ctrl-option, not just option.
         mnemonicInputMap.put(KeyStroke.getKeyStroke(mnemonic, Event.ALT_MASK | Event.CTRL_MASK), "setSelectedIndex");
-        mnemonicToIndexMap.put(new Integer(mnemonic), new Integer(index));
+        mnemonicToIndexMap.put(Integer.valueOf(mnemonic), Integer.valueOf(index));
     }
 
     /**
@@ -2084,7 +2084,7 @@
                     if (mnemonic >= 'a' && mnemonic <= 'z') {
                         mnemonic -= ('a' - 'A');
                     }
-                    final Integer index = ui.mnemonicToIndexMap.get(new Integer(mnemonic));
+                    final Integer index = ui.mnemonicToIndexMap.get(Integer.valueOf(mnemonic));
                     if (index != null && pane.isEnabledAt(index.intValue())) {
                         pane.setSelectedIndex(index.intValue());
                     }
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaUtilControlSize.java	Wed Jul 05 21:39:33 2017 +0200
@@ -268,7 +268,7 @@
 
         public SizeVariant alterFontSize(final float newSize) {
             final float oldSize = fontSize == null ? 0.0f : fontSize.floatValue();
-            fontSize = new Float(newSize + oldSize);
+            fontSize = newSize + oldSize;
             return this;
         }
 
--- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/ScreenPopupFactory.java	Wed Jul 05 21:39:33 2017 +0200
@@ -32,8 +32,8 @@
 import sun.swing.SwingAccessor;
 
 class ScreenPopupFactory extends PopupFactory {
-    static final Float TRANSLUCENT = new Float(248f/255f);
-    static final Float OPAQUE = new Float(1.0f);
+    static final Float TRANSLUCENT = 248f/255f;
+    static final Float OPAQUE = 1.0f;
 
     boolean fIsActive = true;
 
--- a/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/font/CStrike.java	Wed Jul 05 21:39:33 2017 +0200
@@ -386,7 +386,7 @@
             if (generalCache == null) {
                 return 0L;
             }
-            final Long value = generalCache.get(new Integer(index));
+            final Long value = generalCache.get(Integer.valueOf(index));
             if (value == null) {
                 return 0L;
             }
@@ -415,7 +415,7 @@
                 generalCache = new HashMap<Integer, Long>();
             }
 
-            generalCache.put(new Integer(index), Long.valueOf(value));
+            generalCache.put(Integer.valueOf(index), Long.valueOf(value));
         }
 
         public synchronized void dispose() {
@@ -526,7 +526,7 @@
             }
 
             if (generalCache == null) return 0;
-            final Float value = generalCache.get(new Integer(index));
+            final Float value = generalCache.get(Integer.valueOf(index));
             if (value == null) return 0;
             return value.floatValue();
         }
@@ -553,7 +553,7 @@
                 generalCache = new HashMap<Integer, Float>();
             }
 
-            generalCache.put(new Integer(index), new Float(value));
+            generalCache.put(Integer.valueOf(index), Float.valueOf(value));
         }
 
         private static class SparseBitShiftingTwoLayerArray {
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -903,7 +903,7 @@
     @Override
     public boolean requestFocus(Component lightweightChild, boolean temporary,
                                 boolean focusedWindowChangeAllowed, long time,
-                                CausedFocusEvent.Cause cause)
+                                FocusEvent.Cause cause)
     {
         if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
             focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
@@ -1278,7 +1278,7 @@
         assert (e.getSource() == target);
 
         if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
-            LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
+            LWKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
         }
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,8 +31,8 @@
 import java.awt.Rectangle;
 import java.awt.Window;
 import java.awt.dnd.DropTarget;
+import java.awt.event.FocusEvent;
 
-import sun.awt.CausedFocusEvent;
 import sun.awt.LightweightFrame;
 import sun.swing.JLightweightFrame;
 import sun.swing.SwingAccessor;
@@ -60,7 +60,7 @@
     }
 
     @Override
-    public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+    public boolean requestWindowFocus(FocusEvent.Cause cause) {
         if (!focusAllowedFor()) {
             return false;
         }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWToolkit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -404,6 +404,10 @@
     public final PrintJob getPrintJob(Frame frame, String doctitle,
                                       JobAttributes jobAttributes,
                                       PageAttributes pageAttributes) {
+        if (frame == null) {
+            throw new NullPointerException("frame must not be null");
+        }
+
         if (GraphicsEnvironment.isHeadless()) {
             throw new IllegalArgumentException();
         }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -256,14 +256,14 @@
                 if (!getTarget().isAutoRequestFocus()) {
                     return;
                 } else {
-                    requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION);
+                    requestWindowFocus(FocusEvent.Cause.ACTIVATION);
                 }
             // Focus the owner in case this window is focused.
             } else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) {
                 // Transfer focus to the owner.
                 LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this);
                 if (owner != null) {
-                    owner.requestWindowFocus(CausedFocusEvent.Cause.ACTIVATION);
+                    owner.requestWindowFocus(FocusEvent.Cause.ACTIVATION);
                 }
             }
         }
@@ -295,7 +295,7 @@
         if (f == null) {
             f = DEFAULT_FONT;
         }
-        return platformWindow.transformGraphics(new SunGraphics2D(getSurfaceData(), fg, bg, f));
+        return new SunGraphics2D(getSurfaceData(), fg, bg, f);
     }
 
     @Override
@@ -848,7 +848,7 @@
                 // 2. An active but not focused owner frame/dialog is clicked.
                 // The mouse event then will trigger a focus request "in window" to the component, so the window
                 // should gain focus before.
-                requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
+                requestWindowFocus(FocusEvent.Cause.MOUSE_EVENT);
 
                 mouseDownTarget[targetIdx] = targetPeer;
             } else if (id == MouseEvent.MOUSE_DRAGGED) {
@@ -1199,7 +1199,7 @@
      * Requests platform to set native focus on a frame/dialog.
      * In case of a simple window, triggers appropriate java focus change.
      */
-    public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+    public boolean requestWindowFocus(FocusEvent.Cause cause) {
         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
             focusLog.fine("requesting native focus to " + this);
         }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/PlatformWindow.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,8 +26,8 @@
 package sun.lwawt;
 
 import java.awt.*;
+import java.awt.event.FocusEvent;
 
-import sun.awt.CausedFocusEvent;
 import sun.java2d.SurfaceData;
 
 // TODO Is it worth to generify this interface, like that:
@@ -114,7 +114,7 @@
 
     public void updateFocusableWindowState();
 
-    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause);
+    public boolean rejectFocusRequest(FocusEvent.Cause cause);
 
     public boolean requestWindowFocus();
 
@@ -130,12 +130,6 @@
      */
     public void setSizeConstraints(int minW, int minH, int maxW, int maxH);
 
-    /**
-     * Transforms the given Graphics object according to the native
-     * implementation traits (insets, etc.).
-     */
-    public Graphics transformGraphics(Graphics g);
-
     /*
      * Installs the images for particular window.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/AccessibilityEventMonitor.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,253 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.accessibility.Accessible;
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+import javax.swing.event.EventListenerList;
+
+/**
+ * <P>{@code AccessibilityEventMonitor} implements a PropertyChange listener
+ * on every UI object that implements interface {@code Accessible} in the Java
+ * Virtual Machine.  The events captured by these listeners are made available
+ * through listeners supported by {@code AccessibilityEventMonitor}.
+ * With this, all the individual events on each of the UI object
+ * instances are funneled into one set of PropertyChange listeners.
+ *
+ * This code is a subset of com.sun.java.accessibility.util.AccessibilityEventMonitor
+ * which resides in module jdk.accessibility.  Due to modularization the code in
+ * this package, java.desktop, can not be dependent on code in jdk.accessibility.
+ */
+
+class AccessibilityEventMonitor {
+
+    /**
+     * The current list of registered {@link java.beans.PropertyChangeListener
+     * PropertyChangeListener} classes.
+     *
+     * @see #addPropertyChangeListener
+     */
+    private static final EventListenerList listenerList =
+        new EventListenerList();
+
+
+    /**
+     * The actual listener that is installed on the component instances.
+     * This listener calls the other registered listeners when an event
+     * occurs.  By doing things this way, the actual number of listeners
+     * installed on a component instance is drastically reduced.
+     */
+    private static final AccessibilityEventListener accessibilityListener =
+        new AccessibilityEventListener();
+
+    /**
+     * Adds the specified listener to receive all PropertyChange events on
+     * each UI object instance in the Java Virtual Machine as they occur.
+     * <P>Note: This listener is automatically added to all component
+     * instances created after this method is called.  In addition, it
+     * is only added to UI object instances that support this listener type.
+     *
+     * @param l the listener to add
+     * @param a  the Accessible object to add the PropertyChangeListener to
+     */
+
+    static void addPropertyChangeListener(PropertyChangeListener l, Accessible a) {
+        if (listenerList.getListenerCount(PropertyChangeListener.class) == 0) {
+            accessibilityListener.installListeners(a);
+        }
+        listenerList.add(PropertyChangeListener.class, l);
+    }
+
+    /**
+     * AccessibilityEventListener is the class that does all the work for
+     * AccessibilityEventMonitor.  It is not intended for use by any other
+     * class except AccessibilityEventMonitor.
+     */
+
+    private static class AccessibilityEventListener implements PropertyChangeListener {
+
+        /**
+         * Installs PropertyChange listeners to the Accessible object, and its
+         * children (so long as the object isn't of TRANSIENT state).
+         *
+         * @param a the Accessible object to add listeners to
+         */
+        private void installListeners(Accessible a) {
+            installListeners(a.getAccessibleContext());
+        }
+
+        /**
+         * Installs PropertyChange listeners to the AccessibleContext object,
+         * and its * children (so long as the object isn't of TRANSIENT state).
+         *
+         * @param ac the AccessibleContext to add listeners to
+         */
+        private void installListeners(AccessibleContext ac) {
+
+            if (ac != null) {
+                AccessibleStateSet states = ac.getAccessibleStateSet();
+                if (!states.contains(AccessibleState.TRANSIENT)) {
+                    ac.addPropertyChangeListener(this);
+                    /*
+                     * Don't add listeners to transient children. Components
+                     * with transient children should return an AccessibleStateSet
+                     * containing AccessibleState.MANAGES_DESCENDANTS. Components
+                     * may not explicitly return the MANAGES_DESCENDANTS state.
+                     * In this case, don't add listeners to the children of
+                     * lists, tables and trees.
+                     */
+                    AccessibleStateSet set = ac.getAccessibleStateSet();
+                    if (set.contains(AccessibleState.MANAGES_DESCENDANTS)) {
+                        return;
+                    }
+                    AccessibleRole role = ac.getAccessibleRole();
+                    if ( role == AccessibleRole.LIST ||
+                         role == AccessibleRole.TREE ) {
+                        return;
+                    }
+                    if (role == AccessibleRole.TABLE) {
+                        // handle Oracle tables containing tables
+                        Accessible child = ac.getAccessibleChild(0);
+                        if (child != null) {
+                            AccessibleContext ac2 = child.getAccessibleContext();
+                            if (ac2 != null) {
+                                role = ac2.getAccessibleRole();
+                                if (role != null && role != AccessibleRole.TABLE) {
+                                    return;
+                                }
+                            }
+                        }
+                    }
+                    int count = ac.getAccessibleChildrenCount();
+                    for (int i = 0; i < count; i++) {
+                        Accessible child = ac.getAccessibleChild(i);
+                        if (child != null) {
+                            installListeners(child);
+                        }
+                    }
+                }
+            }
+        }
+
+        /**
+         * Removes PropertyChange listeners for the given Accessible object,
+         * its children (so long as the object isn't of TRANSIENT state).
+         *
+         * @param a the Accessible object to remove listeners from
+         */
+        private void removeListeners(Accessible a) {
+            removeListeners(a.getAccessibleContext());
+        }
+
+        /**
+         * Removes PropertyChange listeners for the given AccessibleContext
+         * object, its children (so long as the object isn't of TRANSIENT
+         * state).
+         *
+         * @param a the Accessible object to remove listeners from
+         */
+        private void removeListeners(AccessibleContext ac) {
+
+            if (ac != null) {
+                // Listeners are not added to transient components.
+                AccessibleStateSet states = ac.getAccessibleStateSet();
+                if (!states.contains(AccessibleState.TRANSIENT)) {
+                    ac.removePropertyChangeListener(this);
+                    /*
+                     * Listeners are not added to transient children. Components
+                     * with transient children should return an AccessibleStateSet
+                     * containing AccessibleState.MANAGES_DESCENDANTS. Components
+                     * may not explicitly return the MANAGES_DESCENDANTS state.
+                     * In this case, don't remove listeners from the children of
+                     * lists, tables and trees.
+                     */
+                    if (states.contains(AccessibleState.MANAGES_DESCENDANTS)) {
+                        return;
+                    }
+                    AccessibleRole role = ac.getAccessibleRole();
+                    if ( role == AccessibleRole.LIST ||
+                         role == AccessibleRole.TABLE ||
+                         role == AccessibleRole.TREE ) {
+                        return;
+                    }
+                    int count = ac.getAccessibleChildrenCount();
+                    for (int i = 0; i < count; i++) {
+                        Accessible child = ac.getAccessibleChild(i);
+                        if (child != null) {
+                            removeListeners(child);
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void propertyChange(PropertyChangeEvent e) {
+            // propogate the event
+            Object[] listeners =
+                AccessibilityEventMonitor.listenerList.getListenerList();
+            for (int i = listeners.length-2; i>=0; i-=2) {
+                if (listeners[i]==PropertyChangeListener.class) {
+                    ((PropertyChangeListener)listeners[i+1]).propertyChange(e);
+                }
+            }
+
+            // handle childbirth/death
+            String name = e.getPropertyName();
+            if (name.compareTo(AccessibleContext.ACCESSIBLE_CHILD_PROPERTY) == 0) {
+                Object oldValue = e.getOldValue();
+                Object newValue = e.getNewValue();
+
+                if ((oldValue == null) ^ (newValue == null)) { // one null, not both
+                    if (oldValue != null) {
+                        // this Accessible is a child that's going away
+                        if (oldValue instanceof Accessible) {
+                            Accessible a = (Accessible) oldValue;
+                            removeListeners(a.getAccessibleContext());
+                        } else if (oldValue instanceof AccessibleContext) {
+                            removeListeners((AccessibleContext) oldValue);
+                        }
+                    } else if (newValue != null) {
+                        // this Accessible is a child was just born
+                        if (newValue instanceof Accessible) {
+                            Accessible a = (Accessible) newValue;
+                            installListeners(a.getAccessibleContext());
+                        } else if (newValue instanceof AccessibleContext) {
+                            installListeners((AccessibleContext) newValue);
+                        }
+                    }
+                } else {
+                    System.out.println("ERROR in usage of PropertyChangeEvents for: " + e.toString());
+                }
+            }
+        }
+    }
+}
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CAccessible.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,20 +26,18 @@
 package sun.lwawt.macosx;
 
 import java.awt.Component;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
 import java.lang.reflect.Field;
 
 import javax.accessibility.Accessible;
 import javax.accessibility.AccessibleContext;
 import javax.swing.JProgressBar;
 import javax.swing.JSlider;
-import javax.swing.event.CaretEvent;
-import javax.swing.event.CaretListener;
 import javax.swing.event.ChangeEvent;
 import javax.swing.event.ChangeListener;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import javax.swing.text.JTextComponent;
 
+import sun.lwawt.macosx.CFRetainedResource;
 
 class CAccessible extends CFRetainedResource implements Accessible {
     static Field getNativeAXResourceField() {
@@ -99,13 +97,10 @@
         return accessible.getAccessibleContext();
     }
 
-    // currently only supports text components
     public void addNotificationListeners(Component c) {
-        if (c instanceof JTextComponent) {
-            JTextComponent tc = (JTextComponent) c;
-            AXTextChangeNotifier listener = new AXTextChangeNotifier();
-            tc.getDocument().addDocumentListener(listener);
-            tc.addCaretListener(listener);
+        AXTextChangeNotifier listener = new AXTextChangeNotifier();
+        if (c instanceof Accessible) {
+            AccessibilityEventMonitor.addPropertyChangeListener(listener, (Accessible)c);
         }
         if (c instanceof JProgressBar) {
             JProgressBar pb = (JProgressBar) c;
@@ -117,29 +112,23 @@
     }
 
 
-    private class AXTextChangeNotifier implements DocumentListener, CaretListener {
-        @Override
-        public void changedUpdate(DocumentEvent e) {
-            if (ptr != 0) valueChanged(ptr);
-        }
+    private class AXTextChangeNotifier implements PropertyChangeListener {
 
         @Override
-        public void insertUpdate(DocumentEvent e) {
-            if (ptr != 0) valueChanged(ptr);
-        }
-
-        @Override
-        public void removeUpdate(DocumentEvent e) {
-            if (ptr != 0) valueChanged(ptr);
-        }
-
-        @Override
-        public void caretUpdate(CaretEvent e) {
-            if (ptr != 0) selectionChanged(ptr);
+        public void propertyChange(PropertyChangeEvent e) {
+            String name = e.getPropertyName();
+            if ( ptr != 0 ) {
+                if (name.compareTo(AccessibleContext.ACCESSIBLE_CARET_PROPERTY) == 0) {
+                    selectionChanged(ptr);
+                } else if (name.compareTo(AccessibleContext.ACCESSIBLE_TEXT_PROPERTY) == 0 ) {
+                    valueChanged(ptr);
+                }
+            }
         }
     }
 
     private class AXProgressChangeNotifier implements ChangeListener {
+        @Override
         public void stateChanged(ChangeEvent e) {
             if (ptr != 0) valueChanged(ptr);
         }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CFileDialog.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
 package sun.lwawt.macosx;
 
 import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.peer.*;
 import java.awt.BufferCapabilities.FlipContents;
 import java.awt.event.*;
@@ -34,7 +35,6 @@
 import java.util.List;
 import java.io.*;
 
-import sun.awt.CausedFocusEvent.Cause;
 import sun.awt.AWTAccessor;
 import sun.java2d.pipe.Region;
 import sun.security.action.GetBooleanAction;
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformEmbeddedFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,11 @@
 package sun.lwawt.macosx;
 
 import java.awt.*;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
+
 import sun.java2d.SurfaceData;
 import sun.java2d.opengl.CGLLayer;
 import sun.lwawt.LWWindowPeer;
-import sun.lwawt.LWWindowPeer.PeerType;
 import sun.lwawt.PlatformWindow;
 import sun.util.logging.PlatformLogger;
 
@@ -39,7 +39,8 @@
  */
 public class CPlatformEmbeddedFrame implements PlatformWindow {
 
-    private static final PlatformLogger focusLogger = PlatformLogger.getLogger("sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
+    private static final PlatformLogger focusLogger = PlatformLogger.getLogger(
+            "sun.lwawt.macosx.focus.CPlatformEmbeddedFrame");
 
     private CGLLayer windowLayer;
     private LWWindowPeer peer;
@@ -133,9 +134,9 @@
     public void updateFocusableWindowState() {}
 
     @Override
-    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+    public boolean rejectFocusRequest(FocusEvent.Cause cause) {
         // Cross-app activation requests are not allowed.
-        if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+        if (cause != FocusEvent.Cause.MOUSE_EVENT &&
             !target.isParentWindowActive())
         {
             focusLogger.fine("the embedder is inactive, so the request is rejected");
@@ -161,11 +162,6 @@
     public void setSizeConstraints(int minW, int minH, int maxW, int maxH) {}
 
     @Override
-    public Graphics transformGraphics(Graphics g) {
-        return g;
-    }
-
-    @Override
     public void updateIconImages() {}
 
     @Override
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformLWWindow.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,6 @@
 
 import java.awt.Font;
 import java.awt.FontMetrics;
-import java.awt.Graphics;
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
 import java.awt.Insets;
@@ -37,7 +36,7 @@
 import java.awt.Window;
 import sun.awt.CGraphicsDevice;
 import sun.awt.CGraphicsEnvironment;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
 import sun.awt.LightweightFrame;
 import sun.java2d.SurfaceData;
 import sun.lwawt.LWLightweightFramePeer;
@@ -134,7 +133,7 @@
     }
 
     @Override
-    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+    public boolean rejectFocusRequest(FocusEvent.Cause cause) {
         return false;
     }
 
@@ -153,11 +152,6 @@
     }
 
     @Override
-    public Graphics transformGraphics(Graphics g) {
-        return null;
-    }
-
-    @Override
     public void setAlwaysOnTop(boolean isAlwaysOnTop) {
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -706,9 +706,9 @@
     }
 
     @Override
-    public boolean rejectFocusRequest(CausedFocusEvent.Cause cause) {
+    public boolean rejectFocusRequest(FocusEvent.Cause cause) {
         // Cross-app activation requests are not allowed.
-        if (cause != CausedFocusEvent.Cause.MOUSE_EVENT &&
+        if (cause != FocusEvent.Cause.MOUSE_EVENT &&
             !((LWCToolkit)Toolkit.getDefaultToolkit()).isApplicationActive())
         {
             focusLogger.fine("the app is inactive, so the request is rejected");
@@ -741,12 +741,6 @@
     }
 
     @Override
-    public Graphics transformGraphics(Graphics g) {
-        // is this where we can inject a transform for HiDPI?
-        return g;
-    }
-
-    @Override
     public void setAlwaysOnTop(boolean isAlwaysOnTop) {
         setStyleBits(ALWAYS_ON_TOP, isAlwaysOnTop);
     }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTrayIcon.java	Wed Jul 05 21:39:33 2017 +0200
@@ -98,15 +98,26 @@
     private native long nativeCreate();
 
     //invocation from the AWTTrayIcon.m
-    public long getPopupMenuModel(){
-        if(popup == null) {
-            PopupMenu popupMenu = target.getPopupMenu();
-            if (popupMenu != null) {
-                popup = popupMenu;
+    public long getPopupMenuModel() {
+        PopupMenu newPopup = target.getPopupMenu();
+
+        if (popup == newPopup) {
+            if (popup == null) {
+                return 0L;
+            }
+        } else {
+            if (newPopup != null) {
+                if (popup != null) {
+                    popup.removeNotify();
+                    popup = newPopup;
+                } else {
+                    popup = newPopup;
+                }
             } else {
                 return 0L;
             }
         }
+
         return checkAndCreatePopupPeer().getModel();
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewEmbeddedFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -87,23 +87,22 @@
         }
     }
 
-    /*
+    /**
      * Initializes the embedded frame bounds and validates a component.
-     * Designed to be called from the main thread
-     * This method should be called once from the initialization of the SWT_AWT Bridge
+     * Designed to be called from the main thread. This method should be called
+     * once from the initialization of the SWT_AWT Bridge.
      */
-    public void validateWithBounds(final int x, final int y, final int width, final int height) {
+    public void validateWithBounds(final int x, final int y, final int width,
+                                   final int height) {
         try {
-            final LWWindowPeer peer = AWTAccessor.getComponentAccessor()
-                                                 .getPeer(this);
-            LWCToolkit.invokeAndWait(new Runnable() {
-                @Override
-                public void run() {
-                    peer.setBoundsPrivate(0, 0, width, height);
-                    validate();
-                    setVisible(true);
-                }
+            LWCToolkit.invokeAndWait(() -> {
+                final LWWindowPeer peer = AWTAccessor.getComponentAccessor()
+                                                     .getPeer(this);
+                peer.setBoundsPrivate(0, 0, width, height);
+                validate();
+                setVisible(true);
             }, this);
-        } catch (InvocationTargetException ex) {}
+        } catch (InvocationTargetException ex) {
+        }
     }
 }
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CViewPlatformEmbeddedFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,13 +27,12 @@
 
 import java.awt.Font;
 import java.awt.FontMetrics;
-import java.awt.Graphics;
 import java.awt.GraphicsDevice;
 import java.awt.Insets;
 import java.awt.MenuBar;
 import java.awt.Point;
 import java.awt.Window;
-import sun.awt.CausedFocusEvent.Cause;
+import java.awt.event.FocusEvent.Cause;
 import sun.java2d.SurfaceData;
 import sun.lwawt.LWWindowPeer;
 import sun.lwawt.PlatformWindow;
@@ -171,11 +170,6 @@
     }
 
     @Override
-    public Graphics transformGraphics(Graphics g) {
-        return g;
-    }
-
-    @Override
     public void updateIconImages() {
     }
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWarningWindow.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -364,8 +364,8 @@
             return null;
         }
 
-        return transformGraphics(new SunGraphics2D(sd, SystemColor.windowText,
-                SystemColor.window, ownerWindow.getFont()));
+        return new SunGraphics2D(sd, SystemColor.windowText, SystemColor.window,
+                                 ownerWindow.getFont());
     }
 
 
--- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -378,9 +378,9 @@
 
         // These DnD properties must be set, otherwise Swing ends up spewing NPEs
         // all over the place. The values came straight off of MToolkit.
-        desktopProperties.put("DnD.Autoscroll.initialDelay", new Integer(50));
-        desktopProperties.put("DnD.Autoscroll.interval", new Integer(50));
-        desktopProperties.put("DnD.Autoscroll.cursorHysteresis", new Integer(5));
+        desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50));
+        desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50));
+        desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5));
 
         desktopProperties.put("DnD.isDragImageSupported", Boolean.TRUE);
 
--- a/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/beans/decoder/NewElementHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -42,7 +42,7 @@
  * &lt;new class="java.lang.Long"&gt;
  *     &lt;string&gt;10&lt;/string&gt;
  * &lt;/new&gt;</pre>
- * is equivalent to {@code new Long("10")} in Java code.
+ * is equivalent to {@code Long.valueOf("10")} in Java code.
  * <p>The following attributes are supported:
  * <dl>
  * <dt>class
--- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/bmp/BMPMetadata.java	Wed Jul 05 21:39:33 2017 +0200
@@ -128,7 +128,7 @@
         addChildNode(root, "BMPVersion", bmpVersion);
         addChildNode(root, "Width", width);
         addChildNode(root, "Height", height);
-        addChildNode(root, "BitsPerPixel", new Short(bitsPerPixel));
+        addChildNode(root, "BitsPerPixel", Short.valueOf(bitsPerPixel));
         addChildNode(root, "Compression", compression);
         addChildNode(root, "ImageSize", imageSize);
 
@@ -172,12 +172,12 @@
                 red = palette[j++] & 0xff;
                 green = palette[j++] & 0xff;
                 blue = palette[j++] & 0xff;
-                addChildNode(entry, "Red", new Byte((byte)red));
-                addChildNode(entry, "Green", new Byte((byte)green));
-                addChildNode(entry, "Blue", new Byte((byte)blue));
+                addChildNode(entry, "Red", Byte.valueOf((byte)red));
+                addChildNode(entry, "Green", Byte.valueOf((byte)green));
+                addChildNode(entry, "Blue", Byte.valueOf((byte)blue));
                 if (numComps == 4)
                     addChildNode(entry, "Alpha",
-                                 new Byte((byte)(palette[j++] & 0xff)));
+                                 Byte.valueOf((byte)(palette[j++] & 0xff)));
             }
         }
 
@@ -284,9 +284,9 @@
 
     private void addXYZPoints(IIOMetadataNode root, String name, double x, double y, double z) {
         IIOMetadataNode node = addChildNode(root, name, null);
-        addChildNode(node, "X", new Double(x));
-        addChildNode(node, "Y", new Double(y));
-        addChildNode(node, "Z", new Double(z));
+        addChildNode(node, "X", Double.valueOf(x));
+        addChildNode(node, "Y", Double.valueOf(y));
+        addChildNode(node, "Z", Double.valueOf(z));
     }
 
     private IIOMetadataNode addChildNode(IIOMetadataNode root,
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKEngine.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -158,8 +158,8 @@
             int widgetType, int state, int shadowType, String detail,
             int x, int y, int width, int height, int synthState, int dir);
     private native void native_paint_slider(
-            int widgetType, int state, int shadowType, String detail,
-            int x, int y, int width, int height, int orientation);
+            int widgetType, int state, int shadowType, String detail, int x,
+            int y, int width, int height, int orientation, boolean hasFocus);
     private native void native_paint_vline(
             int widgetType, int state, String detail,
             int x, int y, int width, int height);
@@ -491,6 +491,14 @@
         int gtkState =
             GTKLookAndFeel.synthStateToGTKStateType(state).ordinal();
         int synthState = context.getComponentState();
+        Container parent = context.getComponent().getParent();
+        if(GTKLookAndFeel.is3()) {
+            if (parent != null && parent.getParent() instanceof JComboBox) {
+                if (parent.getParent().hasFocus()) {
+                    synthState |= SynthConstants.FOCUSED;
+                }
+            }
+        }
         int dir = getTextDirection(context);
         int widget = getWidgetType(context.getComponent(), id).ordinal();
         native_paint_shadow(widget, gtkState, shadowType.ordinal(), detail,
@@ -498,13 +506,13 @@
     }
 
     public void paintSlider(Graphics g, SynthContext context,
-            Region id, int state, ShadowType shadowType, String detail,
-            int x, int y, int w, int h, Orientation orientation) {
+            Region id, int state, ShadowType shadowType, String detail, int x,
+            int y, int w, int h, Orientation orientation, boolean hasFocus) {
 
         state = GTKLookAndFeel.synthStateToGTKStateType(state).ordinal();
         int widget = getWidgetType(context.getComponent(), id).ordinal();
         native_paint_slider(widget, state, shadowType.ordinal(), detail,
-                            x - x0, y - y0, w, h, orientation.ordinal());
+                         x - x0, y - y0, w, h, orientation.ordinal(), hasFocus);
     }
 
     public void paintVline(Graphics g, SynthContext context,
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,8 @@
  */
 @SuppressWarnings("serial") // Superclass not serializable
 public class GTKLookAndFeel extends SynthLookAndFeel {
-    private static final boolean IS_22;
+    private static boolean IS_22;
+    private static boolean IS_3;
 
     /**
      * Whether or not text is drawn antialiased.  This keys off the
@@ -107,17 +108,6 @@
     private static String gtkThemeName = "Default";
 
     static {
-        // Backup for specifying the version, this isn't currently documented.
-        // If you pass in anything but 2.2 you got the 2.0 colors/look.
-        String version = AccessController.doPrivileged(
-               new GetPropertyAction("swing.gtk.version"));
-        if (version != null) {
-            IS_22 = version.equals("2.2");
-        }
-        else {
-            IS_22 = true;
-        }
-
         String language = Locale.getDefault().getLanguage();
         boolean cjkLocale =
             (Locale.CHINESE.getLanguage().equals(language) ||
@@ -158,6 +148,10 @@
         return IS_22;
     }
 
+    static boolean is3() {
+        return IS_3;
+    }
+
     /**
      * Maps a swing constant to a GTK constant.
      */
@@ -385,7 +379,7 @@
         }
         Insets zeroInsets = new InsetsUIResource(0, 0, 0, 0);
 
-        Double defaultCaretAspectRatio = new Double(0.025);
+        Double defaultCaretAspectRatio = Double.valueOf(0.025);
         Color caretColor = table.getColor("caretColor");
         Color controlText = table.getColor("controlText");
 
@@ -1460,6 +1454,19 @@
             throw new InternalError("Unable to load native GTK libraries");
         }
 
+        if (UNIXToolkit.getGtkVersion() == UNIXToolkit.GtkVersions.GTK2) {
+            String version = AccessController.doPrivileged(
+                    new GetPropertyAction("jdk.gtk.version"));
+            if (version != null) {
+                IS_22 = version.equals("2.2");
+            } else {
+                IS_22 = true;
+            }
+        } else if (UNIXToolkit.getGtkVersion() ==
+                                UNIXToolkit.GtkVersions.GTK3) {
+            IS_3 = true;
+        }
+
         super.initialize();
         inInitialize = true;
         loadStyles();
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -576,12 +576,11 @@
                     ShadowType.OUT, "menu", x, y, w, h);
 
             GTKStyle style = (GTKStyle)context.getStyle();
-            int xThickness = style.getXThickness();
-            int yThickness = style.getYThickness();
+            Insets insets = style.getInsets(context, null);
             ENGINE.paintBackground(g, context, id, gtkState,
-                    style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
-                    x + xThickness, y + yThickness,
-                    w - xThickness - xThickness, h - yThickness - yThickness);
+                style.getGTKColor(context, gtkState, GTKColorType.BACKGROUND),
+                x + insets.left, y + insets.top, w - insets.left - insets.right,
+                h - insets.top - insets.bottom);
             ENGINE.finishPainting();
         }
     }
@@ -640,6 +639,34 @@
         int state = context.getComponentState();
         JComponent c = context.getComponent();
 
+        GTKStyle style = (GTKStyle) context.getStyle();
+        String detail;
+        // wide-separators are painted using box not line
+        if (style.getClassSpecificBoolValue(context,
+                                          "wide-separators", false)) {
+            Insets insets = c.getInsets();
+            x += insets.left;
+            y += insets.top;
+            if (orientation == JSeparator.HORIZONTAL) {
+                w -= (insets.left + insets.right);
+                detail = "hseparator";
+            } else {
+                h -= (insets.top + insets.bottom);
+                detail = "vseparator";
+            }
+            synchronized (UNIXToolkit.GTK_LOCK) {
+                if (! ENGINE.paintCachedImage(g, x, y, w, h, id, state,
+                            detail, orientation)) {
+                    ENGINE.startPainting(g, x, y, w, h, id, state,
+                            detail, orientation);
+                    ENGINE.paintBox(g, context, id, state,
+                            ShadowType.ETCHED_OUT, detail, x, y, w, h);
+                    ENGINE.finishPainting();
+                }
+            }
+            return;
+        }
+
         /*
          * Note: In theory, the style's x/y thickness values would determine
          * the width of the separator content.  In practice, however, some
@@ -650,7 +677,6 @@
          * the w/h values below too much, so that the full thickness of the
          * rendered line will be captured by our image caching code.
          */
-        String detail;
         if (c instanceof JToolBar.Separator) {
             /*
              * GTK renders toolbar separators differently in that an
@@ -678,7 +704,6 @@
             float pct = 0.2f;
             JToolBar.Separator sep = (JToolBar.Separator)c;
             Dimension size = sep.getSeparatorSize();
-            GTKStyle style = (GTKStyle)context.getStyle();
             if (orientation == JSeparator.HORIZONTAL) {
                 x += (int)(w * pct);
                 w -= (int)(w * pct * 2);
@@ -743,6 +768,15 @@
         // The ubuntulooks engine paints slider troughs differently depending
         // on the current slider value and its component orientation.
         JSlider slider = (JSlider)context.getComponent();
+        if (GTKLookAndFeel.is3()) {
+            if (slider.getOrientation() == JSlider.VERTICAL) {
+                y += 1;
+                h -= 2;
+            } else {
+                x += 1;
+                w -= 2;
+            }
+        }
         double value = slider.getValue();
         double min = slider.getMinimum();
         double max = slider.getMaximum();
@@ -776,15 +810,19 @@
         Region id = context.getRegion();
         int gtkState = GTKLookAndFeel.synthStateToGTKState(
                 id, context.getComponentState());
+        boolean hasFocus = GTKLookAndFeel.is3() &&
+                ((context.getComponentState() & SynthConstants.FOCUSED) != 0);
         synchronized (UNIXToolkit.GTK_LOCK) {
-            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir)) {
+            if (! ENGINE.paintCachedImage(g, x, y, w, h, id, gtkState, dir,
+                                                                    hasFocus)) {
                 Orientation orientation = (dir == JSlider.HORIZONTAL ?
                     Orientation.HORIZONTAL : Orientation.VERTICAL);
                 String detail = (dir == JSlider.HORIZONTAL ?
                     "hscale" : "vscale");
                 ENGINE.startPainting(g, x, y, w, h, id, gtkState, dir);
                 ENGINE.paintSlider(g, context, id, gtkState,
-                        ShadowType.OUT, detail, x, y, w, h, orientation);
+                        ShadowType.OUT, detail, x, y, w, h, orientation,
+                                                                     hasFocus);
                 ENGINE.finishPainting();
             }
         }
@@ -963,15 +1001,21 @@
             int yThickness = style.getYThickness();
 
             ENGINE.startPainting(g, x, y, w, h, id, state);
+            if (GTKLookAndFeel.is3()) {
+                ENGINE.paintBackground(g, context, id, gtkState, null,
+                                                                    x, y, w, h);
+            }
             ENGINE.paintShadow(g, context, id, gtkState,
                                ShadowType.IN, "entry", x, y, w, h);
-            ENGINE.paintFlatBox(g, context, id,
-                                gtkState, ShadowType.NONE, "entry_bg",
-                                x + xThickness,
-                                y + yThickness,
-                                w - (2 * xThickness),
-                                h - (2 * yThickness),
-                                ColorType.TEXT_BACKGROUND);
+            if (!GTKLookAndFeel.is3()) {
+                ENGINE.paintFlatBox(g, context, id,
+                        gtkState, ShadowType.NONE, "entry_bg",
+                        x + xThickness,
+                        y + yThickness,
+                        w - (2 * xThickness),
+                        h - (2 * yThickness),
+                        ColorType.TEXT_BACKGROUND);
+            }
 
             if (focusSize > 0 && (state & SynthConstants.FOCUSED) != 0) {
                 if (!interiorFocus) {
@@ -982,14 +1026,14 @@
                 } else {
                     if (containerParent instanceof JComboBox) {
                         x += (focusSize + 2);
-                        y += (focusSize + 1);
-                        w -= (2 * focusSize + 1);
-                        h -= (2 * focusSize + 2);
+                        y += focusSize + (GTKLookAndFeel.is3() ? 3 : 1);
+                        w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 1);
+                        h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 6 : 2);
                     } else {
-                        x += focusSize;
-                        y += focusSize;
-                        w -= 2 * focusSize;
-                        h -= 2 * focusSize;
+                        x += focusSize + (GTKLookAndFeel.is3() ? 2 : 0);
+                        y += focusSize + (GTKLookAndFeel.is3() ? 2 :0 );
+                        w -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
+                        h -= 2 * focusSize + (GTKLookAndFeel.is3() ? 4 : 0);
                     }
                 }
                 ENGINE.paintFocus(g, context, id, gtkState,
@@ -1138,8 +1182,8 @@
                 Orientation orientation = (dir == JScrollBar.HORIZONTAL ?
                     Orientation.HORIZONTAL : Orientation.VERTICAL);
                 ENGINE.setRangeValue(context, id, value, min, max, visible);
-                ENGINE.paintSlider(g, context, id, gtkState,
-                        ShadowType.OUT, "slider", x, y, w, h, orientation);
+                ENGINE.paintSlider(g, context, id, gtkState, ShadowType.OUT,
+                                      "slider", x, y, w, h, orientation, false);
                 ENGINE.finishPainting();
             }
         }
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -715,29 +715,33 @@
         if (region == Region.COMBO_BOX ||
               region == Region.DESKTOP_PANE ||
               region == Region.DESKTOP_ICON ||
-              region == Region.EDITOR_PANE ||
-              region == Region.FORMATTED_TEXT_FIELD ||
               region == Region.INTERNAL_FRAME ||
               region == Region.LIST ||
               region == Region.MENU_BAR ||
               region == Region.PANEL ||
-              region == Region.PASSWORD_FIELD ||
               region == Region.POPUP_MENU ||
               region == Region.PROGRESS_BAR ||
               region == Region.ROOT_PANE ||
               region == Region.SCROLL_PANE ||
-              region == Region.SPINNER ||
               region == Region.SPLIT_PANE_DIVIDER ||
               region == Region.TABLE ||
               region == Region.TEXT_AREA ||
-              region == Region.TEXT_FIELD ||
-              region == Region.TEXT_PANE ||
               region == Region.TOOL_BAR_DRAG_WINDOW ||
               region == Region.TOOL_TIP ||
               region == Region.TREE ||
               region == Region.VIEWPORT) {
             return true;
         }
+        if (!GTKLookAndFeel.is3()) {
+            if (region == Region.EDITOR_PANE ||
+                  region == Region.FORMATTED_TEXT_FIELD ||
+                  region == Region.PASSWORD_FIELD ||
+                  region == Region.SPINNER ||
+                  region == Region.TEXT_FIELD ||
+                  region == Region.TEXT_PANE) {
+                return true;
+            }
+        }
         Component c = context.getComponent();
         String name = c.getName();
         if (name == "ComboBox.renderer" || name == "ComboBox.listRenderer") {
@@ -776,6 +780,15 @@
         }
         else if (key == "Separator.thickness") {
             JSeparator sep = (JSeparator)context.getComponent();
+            if (getClassSpecificBoolValue(context, "wide-separators", false)) {
+                if (sep.getOrientation() == JSeparator.HORIZONTAL) {
+                    return getClassSpecificIntValue(context,
+                            "separator-height", 0);
+                } else {
+                    return getClassSpecificIntValue(context,
+                            "separator-width", 0);
+                }
+            }
             if (sep.getOrientation() == JSeparator.HORIZONTAL) {
                 return getYThickness();
             } else {
@@ -783,6 +796,12 @@
             }
         }
         else if (key == "ToolBar.separatorSize") {
+            if (getClassSpecificBoolValue(context, "wide-separators", false)) {
+                return new DimensionUIResource(
+                    getClassSpecificIntValue(context, "separator-width", 2),
+                    getClassSpecificIntValue(context, "separator-height", 2)
+                );
+            }
             int size = getClassSpecificIntValue(WidgetType.TOOL_BAR,
                                                 "space-size", 12);
             return new DimensionUIResource(size, size);
@@ -833,6 +852,8 @@
             int focusPad =
                 getClassSpecificIntValue(context, "focus-padding", 1);
             return indicatorSpacing + focusSize + focusPad;
+        } else if (GTKLookAndFeel.is3() && "ComboBox.forceOpaque".equals(key)) {
+            return true;
         }
 
         // Is it a stock icon ?
@@ -1112,6 +1133,7 @@
     static {
         CLASS_SPECIFIC_MAP = new HashMap<String,String>();
         CLASS_SPECIFIC_MAP.put("Slider.thumbHeight", "slider-width");
+        CLASS_SPECIFIC_MAP.put("Slider.thumbWidth", "slider-length");
         CLASS_SPECIFIC_MAP.put("Slider.trackBorder", "trough-border");
         CLASS_SPECIFIC_MAP.put("SplitPane.size", "handle-size");
         CLASS_SPECIFIC_MAP.put("Tree.expanderSize", "expander-size");
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java	Wed Jul 05 21:39:33 2017 +0200
@@ -185,7 +185,7 @@
                                                getIntAttr(child, "bottom", 0),
                                                getIntAttr(child, "right", 0));
                         } else if ("aspect_ratio".equals(name)) {
-                            value = new Float(getFloatAttr(child, "value", 1.0F));
+                            value = Float.valueOf(getFloatAttr(child, "value", 1.0F));
                         } else {
                             logError(themeName, "Unknown Metacity frame geometry value type: "+name);
                         }
--- a/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/AnimationController.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -37,7 +37,6 @@
 
 
 
-import sun.swing.UIClientPropertyKey;
 import com.sun.java.swing.plaf.windows.TMSchema.State;
 import static com.sun.java.swing.plaf.windows.TMSchema.State.*;
 import com.sun.java.swing.plaf.windows.TMSchema.Part;
--- a/jdk/src/java.desktop/share/classes/java/awt/Component.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/Component.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,6 @@
 import sun.awt.ConstrainableGraphics;
 import sun.awt.SubRegionShowable;
 import sun.awt.SunToolkit;
-import sun.awt.CausedFocusEvent;
 import sun.awt.EmbeddedFrame;
 import sun.awt.dnd.SunDropTargetEvent;
 import sun.awt.im.CompositionArea;
@@ -878,7 +877,7 @@
             {
                 comp.setGraphicsConfiguration(gc);
             }
-            public boolean requestFocus(Component comp, CausedFocusEvent.Cause cause) {
+            public boolean requestFocus(Component comp, FocusEvent.Cause cause) {
                 return comp.requestFocus(cause);
             }
             public boolean canBeFocusOwner(Component comp) {
@@ -7538,7 +7537,7 @@
         requestFocusHelper(false, true);
     }
 
-    boolean requestFocus(CausedFocusEvent.Cause cause) {
+    boolean requestFocus(FocusEvent.Cause cause) {
         return requestFocusHelper(false, true, cause);
     }
 
@@ -7605,7 +7604,7 @@
         return requestFocusHelper(temporary, true);
     }
 
-    boolean requestFocus(boolean temporary, CausedFocusEvent.Cause cause) {
+    boolean requestFocus(boolean temporary, FocusEvent.Cause cause) {
         return requestFocusHelper(temporary, true, cause);
     }
     /**
@@ -7656,7 +7655,7 @@
         return requestFocusHelper(false, false);
     }
 
-    boolean requestFocusInWindow(CausedFocusEvent.Cause cause) {
+    boolean requestFocusInWindow(FocusEvent.Cause cause) {
         return requestFocusHelper(false, false, cause);
     }
 
@@ -7721,18 +7720,18 @@
         return requestFocusHelper(temporary, false);
     }
 
-    boolean requestFocusInWindow(boolean temporary, CausedFocusEvent.Cause cause) {
+    boolean requestFocusInWindow(boolean temporary, FocusEvent.Cause cause) {
         return requestFocusHelper(temporary, false, cause);
     }
 
     final boolean requestFocusHelper(boolean temporary,
                                      boolean focusedWindowChangeAllowed) {
-        return requestFocusHelper(temporary, focusedWindowChangeAllowed, CausedFocusEvent.Cause.UNKNOWN);
+        return requestFocusHelper(temporary, focusedWindowChangeAllowed, FocusEvent.Cause.UNKNOWN);
     }
 
     final boolean requestFocusHelper(boolean temporary,
                                      boolean focusedWindowChangeAllowed,
-                                     CausedFocusEvent.Cause cause)
+                                     FocusEvent.Cause cause)
     {
         // 1) Check if the event being dispatched is a system-generated mouse event.
         AWTEvent currentEvent = EventQueue.getCurrentEvent();
@@ -7820,7 +7819,7 @@
 
     private boolean isRequestFocusAccepted(boolean temporary,
                                            boolean focusedWindowChangeAllowed,
-                                           CausedFocusEvent.Cause cause)
+                                           FocusEvent.Cause cause)
     {
         if (!isFocusable() || !isVisible()) {
             if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
@@ -7867,7 +7866,7 @@
             return true;
         }
 
-        if (CausedFocusEvent.Cause.ACTIVATION == cause) {
+        if (FocusEvent.Cause.ACTIVATION == cause) {
             // we shouldn't call RequestFocusController in case we are
             // in activation.  We do request focus on component which
             // has got temporary focus lost and then on component which is
@@ -7899,7 +7898,7 @@
     private static class DummyRequestFocusController implements RequestFocusController {
         public boolean acceptRequestFocus(Component from, Component to,
                                           boolean temporary, boolean focusedWindowChangeAllowed,
-                                          CausedFocusEvent.Cause cause)
+                                          FocusEvent.Cause cause)
         {
             return true;
         }
@@ -7983,7 +7982,7 @@
         Component toFocus = getNextFocusCandidate();
         boolean res = false;
         if (toFocus != null && !toFocus.isFocusOwner() && toFocus != this) {
-            res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_FORWARD);
+            res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_FORWARD);
         }
         if (clearOnFailure && !res) {
             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -8063,7 +8062,7 @@
                 toFocus = policy.getDefaultComponent(rootAncestor);
             }
             if (toFocus != null) {
-                res = toFocus.requestFocusInWindow(CausedFocusEvent.Cause.TRAVERSAL_BACKWARD);
+                res = toFocus.requestFocusInWindow(FocusEvent.Cause.TRAVERSAL_BACKWARD);
             }
         }
         if (clearOnFailure && !res) {
@@ -8108,7 +8107,7 @@
 
             KeyboardFocusManager.getCurrentKeyboardFocusManager().
                 setGlobalCurrentFocusCycleRootPriv(fcr);
-            rootAncestor.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
+            rootAncestor.requestFocus(FocusEvent.Cause.TRAVERSAL_UP);
         } else {
             Window window = getContainingWindow();
 
@@ -8118,7 +8117,7 @@
                 if (toFocus != null) {
                     KeyboardFocusManager.getCurrentKeyboardFocusManager().
                         setGlobalCurrentFocusCycleRootPriv(window);
-                    toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_UP);
+                    toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_UP);
                 }
             }
         }
--- a/jdk/src/java.desktop/share/classes/java/awt/Container.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/Container.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,7 +55,6 @@
 
 import sun.awt.AppContext;
 import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
 import sun.awt.PeerEvent;
 import sun.awt.SunToolkit;
 
@@ -3515,7 +3514,7 @@
             Component toFocus = getFocusTraversalPolicy().
                 getDefaultComponent(this);
             if (toFocus != null) {
-                toFocus.requestFocus(CausedFocusEvent.Cause.TRAVERSAL_DOWN);
+                toFocus.requestFocus(FocusEvent.Cause.TRAVERSAL_DOWN);
             }
         }
     }
--- a/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/DefaultKeyboardFocusManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, 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
@@ -40,7 +40,6 @@
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
 import sun.awt.TimedWindowEvent;
 
 /**
@@ -165,13 +164,13 @@
                                    boolean clearOnFailure)
     {
         if (toFocus != vetoedComponent && toFocus.isShowing() && toFocus.canBeFocusOwner() &&
-            toFocus.requestFocus(false, CausedFocusEvent.Cause.ROLLBACK))
+            toFocus.requestFocus(false, FocusEvent.Cause.ROLLBACK))
         {
             return true;
         } else {
             Component nextFocus = toFocus.getNextFocusCandidate();
             if (nextFocus != null && nextFocus != vetoedComponent &&
-                nextFocus.requestFocusInWindow(CausedFocusEvent.Cause.ROLLBACK))
+                nextFocus.requestFocusInWindow(FocusEvent.Cause.ROLLBACK))
             {
                 return true;
             } else if (clearOnFailure) {
@@ -431,13 +430,13 @@
                                        tempLost, toFocus);
                     }
                     if (tempLost != null) {
-                        tempLost.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
+                        tempLost.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
                     }
 
                     if (toFocus != null && toFocus != tempLost) {
                         // If there is a component which requested focus when this window
                         // was inactive it expects to receive focus after activation.
-                        toFocus.requestFocusInWindow(CausedFocusEvent.Cause.ACTIVATION);
+                        toFocus.requestFocusInWindow(FocusEvent.Cause.ACTIVATION);
                     }
                 }
 
@@ -490,8 +489,6 @@
 
             case FocusEvent.FOCUS_GAINED: {
                 FocusEvent fe = (FocusEvent)e;
-                CausedFocusEvent.Cause cause = (fe instanceof CausedFocusEvent) ?
-                    ((CausedFocusEvent)fe).getCause() : CausedFocusEvent.Cause.UNKNOWN;
                 Component oldFocusOwner = getGlobalFocusOwner();
                 Component newFocusOwner = fe.getComponent();
                 if (oldFocusOwner == newFocusOwner) {
@@ -509,10 +506,10 @@
                 if (oldFocusOwner != null) {
                     boolean isEventDispatched =
                         sendMessage(oldFocusOwner,
-                                    new CausedFocusEvent(oldFocusOwner,
+                                    new FocusEvent(oldFocusOwner,
                                                    FocusEvent.FOCUS_LOST,
                                                    fe.isTemporary(),
-                                                   newFocusOwner, cause));
+                                                   newFocusOwner, fe.getCause()));
                     // Failed to dispatch, clear by ourselves
                     if (!isEventDispatched) {
                         setGlobalFocusOwner(null);
@@ -552,7 +549,7 @@
                     // Refuse focus on a disabled component if the focus event
                     // isn't of UNKNOWN reason (i.e. not a result of a direct request
                     // but traversal, activation or system generated).
-                    (newFocusOwner.isEnabled() || cause.equals(CausedFocusEvent.Cause.UNKNOWN))))
+                    (newFocusOwner.isEnabled() || fe.getCause().equals(FocusEvent.Cause.UNKNOWN))))
                 {
                     // we should not accept focus on such component, so reject it.
                     dequeueKeyEvents(-1, newFocusOwner);
@@ -601,10 +598,10 @@
                 Component realOppositeComponent = this.realOppositeComponentWR.get();
                 if (realOppositeComponent != null &&
                     realOppositeComponent != fe.getOppositeComponent()) {
-                    fe = new CausedFocusEvent(newFocusOwner,
+                    fe = new FocusEvent(newFocusOwner,
                                         FocusEvent.FOCUS_GAINED,
                                         fe.isTemporary(),
-                                        realOppositeComponent, cause);
+                                        realOppositeComponent, fe.getCause());
                     ((AWTEvent) fe).isPosted = true;
                 }
                 return typeAheadAssertions(newFocusOwner, fe);
@@ -729,10 +726,10 @@
                         oppositeComp = oppositeWindow;
                     }
                     sendMessage(currentFocusOwner,
-                                new CausedFocusEvent(currentFocusOwner,
+                                new FocusEvent(currentFocusOwner,
                                                FocusEvent.FOCUS_LOST,
                                                true,
-                                               oppositeComp, CausedFocusEvent.Cause.ACTIVATION));
+                                               oppositeComp, FocusEvent.Cause.ACTIVATION));
                 }
 
                 setGlobalFocusedWindow(null);
--- a/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/KeyboardFocusManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, 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
@@ -57,7 +57,6 @@
 
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
-import sun.awt.CausedFocusEvent;
 import sun.awt.KeyboardFocusManagerPeerProvider;
 import sun.awt.AWTAccessor;
 
@@ -124,7 +123,7 @@
                                                    boolean temporary,
                                                    boolean focusedWindowChangeAllowed,
                                                    long time,
-                                                   CausedFocusEvent.Cause cause)
+                                                   FocusEvent.Cause cause)
                 {
                     return KeyboardFocusManager.shouldNativelyFocusHeavyweight(
                         heavyweight, descendant, temporary, focusedWindowChangeAllowed, time, cause);
@@ -2164,9 +2163,9 @@
     private static final class LightweightFocusRequest {
         final Component component;
         final boolean temporary;
-        final CausedFocusEvent.Cause cause;
+        final FocusEvent.Cause cause;
 
-        LightweightFocusRequest(Component component, boolean temporary, CausedFocusEvent.Cause cause) {
+        LightweightFocusRequest(Component component, boolean temporary, FocusEvent.Cause cause) {
             this.component = component;
             this.temporary = temporary;
             this.cause = cause;
@@ -2190,7 +2189,7 @@
         }
 
         HeavyweightFocusRequest(Component heavyweight, Component descendant,
-                                boolean temporary, CausedFocusEvent.Cause cause) {
+                                boolean temporary, FocusEvent.Cause cause) {
             if (log.isLoggable(PlatformLogger.Level.FINE)) {
                 if (heavyweight == null) {
                     log.fine("Assertion (heavyweight != null) failed");
@@ -2202,7 +2201,7 @@
             addLightweightRequest(descendant, temporary, cause);
         }
         boolean addLightweightRequest(Component descendant,
-                                      boolean temporary, CausedFocusEvent.Cause cause) {
+                                      boolean temporary, FocusEvent.Cause cause) {
             if (log.isLoggable(PlatformLogger.Level.FINE)) {
                 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
                     log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
@@ -2314,7 +2313,7 @@
 
                 hwFocusRequest =
                     new HeavyweightFocusRequest(heavyweight, descendant,
-                                                temporary, CausedFocusEvent.Cause.UNKNOWN);
+                                                temporary, FocusEvent.Cause.UNKNOWN);
                 heavyweightRequests.add(hwFocusRequest);
 
                 if (currentFocusOwner != null) {
@@ -2379,7 +2378,7 @@
      */
     static int shouldNativelyFocusHeavyweight
         (Component heavyweight, Component descendant, boolean temporary,
-         boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+         boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)
     {
         if (log.isLoggable(PlatformLogger.Level.FINE)) {
             if (heavyweight == null) {
@@ -2445,7 +2444,7 @@
 
                 if (currentFocusOwner != null) {
                     FocusEvent currentFocusOwnerEvent =
-                        new CausedFocusEvent(currentFocusOwner,
+                        new FocusEvent(currentFocusOwner,
                                        FocusEvent.FOCUS_LOST,
                                        temporary, descendant, cause);
                     // Fix 5028014. Rolled out.
@@ -2454,7 +2453,7 @@
                                          currentFocusOwnerEvent);
                 }
                 FocusEvent newFocusOwnerEvent =
-                    new CausedFocusEvent(descendant, FocusEvent.FOCUS_GAINED,
+                    new FocusEvent(descendant, FocusEvent.FOCUS_GAINED,
                                    temporary, currentFocusOwner, cause);
                 // Fix 5028014. Rolled out.
                 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
@@ -2670,13 +2669,13 @@
                      * lw requests.
                      */
                     if (currentFocusOwner != null) {
-                        currentFocusOwnerEvent = new CausedFocusEvent(currentFocusOwner,
+                        currentFocusOwnerEvent = new FocusEvent(currentFocusOwner,
                                        FocusEvent.FOCUS_LOST,
                                        lwFocusRequest.temporary,
                                        lwFocusRequest.component, lwFocusRequest.cause);
                     }
                     FocusEvent newFocusOwnerEvent =
-                        new CausedFocusEvent(lwFocusRequest.component,
+                        new FocusEvent(lwFocusRequest.component,
                                        FocusEvent.FOCUS_GAINED,
                                        lwFocusRequest.temporary,
                                        currentFocusOwner == null ? lastFocusOwner : currentFocusOwner,
@@ -2726,8 +2725,8 @@
             {
                 temporary = true;
             }
-            return new CausedFocusEvent(source, fe.getID(), temporary, opposite,
-                                        CausedFocusEvent.Cause.NATIVE_SYSTEM);
+            return new FocusEvent(source, fe.getID(), temporary, opposite,
+                                        FocusEvent.Cause.UNEXPECTED);
         }
     }
 
@@ -2802,7 +2801,7 @@
 
                 // 'opposite' will be fixed by
                 // DefaultKeyboardFocusManager.realOppositeComponent
-                return new CausedFocusEvent(newSource,
+                return new FocusEvent(newSource,
                                       FocusEvent.FOCUS_GAINED, temporary,
                                       opposite, lwFocusRequest.cause);
             }
@@ -2815,8 +2814,8 @@
                 // If it arrives as the result of activation we should skip it
                 // This event will not have appropriate request record and
                 // on arrival there will be already some focus owner set.
-                return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
-                                            null, CausedFocusEvent.Cause.ACTIVATION);
+                return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_GAINED, false,
+                                            null, FocusEvent.Cause.ACTIVATION);
             }
 
             return retargetUnexpectedFocusEvent(fe);
@@ -2839,9 +2838,9 @@
                 if (currentFocusOwner != null) {
                     // Call to KeyboardFocusManager.clearGlobalFocusOwner()
                     heavyweightRequests.removeFirst();
-                    return new CausedFocusEvent(currentFocusOwner,
+                    return new FocusEvent(currentFocusOwner,
                                                 FocusEvent.FOCUS_LOST, false, null,
-                                                CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
+                                                FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
                 }
 
                 // Otherwise, fall through to failure case below
@@ -2850,9 +2849,9 @@
             {
                 // Focus leaving application
                 if (currentFocusOwner != null) {
-                    return new CausedFocusEvent(currentFocusOwner,
+                    return new FocusEvent(currentFocusOwner,
                                                 FocusEvent.FOCUS_LOST,
-                                                true, null, CausedFocusEvent.Cause.ACTIVATION);
+                                                true, null, FocusEvent.Cause.ACTIVATION);
                 } else {
                     return fe;
                 }
@@ -2878,15 +2877,15 @@
                     ? true
                     : lwFocusRequest.temporary;
 
-                return new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
+                return new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
                                             temporary, lwFocusRequest.component, lwFocusRequest.cause);
             } else if (focusedWindowChanged(opposite, currentFocusOwner)) {
                 // If top-level changed there might be no focus request in a list
                 // But we know the opposite, we now it is temporary - dispatch the event.
                 if (!fe.isTemporary() && currentFocusOwner != null) {
                     // Create copy of the event with only difference in temporary parameter.
-                    fe = new CausedFocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
-                                              true, opposite, CausedFocusEvent.Cause.ACTIVATION);
+                    fe = new FocusEvent(currentFocusOwner, FocusEvent.FOCUS_LOST,
+                                              true, opposite, FocusEvent.Cause.ACTIVATION);
                 }
                 return fe;
             }
--- a/jdk/src/java.desktop/share/classes/java/awt/Window.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/Window.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,6 @@
 import sun.awt.AWTAccessor;
 import sun.awt.AWTPermissions;
 import sun.awt.AppContext;
-import sun.awt.CausedFocusEvent;
 import sun.awt.DebugSettings;
 import sun.awt.SunToolkit;
 import sun.awt.util.IdentityArrayList;
@@ -2599,7 +2598,7 @@
                 {
                     Component toFocus =
                         KeyboardFocusManager.getMostRecentFocusOwner(owner);
-                    if (toFocus != null && toFocus.requestFocus(false, CausedFocusEvent.Cause.ACTIVATION)) {
+                    if (toFocus != null && toFocus.requestFocus(false, FocusEvent.Cause.ACTIVATION)) {
                         return;
                     }
                 }
--- a/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/event/FocusEvent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -26,6 +26,9 @@
 package java.awt.event;
 
 import java.awt.Component;
+import java.io.ObjectStreamException;
+
+import sun.awt.AWTAccessor;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 
@@ -51,6 +54,10 @@
  * the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in
  * the event using the isTemporary() method.
  * <p>
+ * Every {@code FocusEvent} records its cause - the reason why this event was
+ * generated. The cause is assigned during the focus event creation and may be
+ * retrieved by calling {@link #getCause}.
+ * <p>
  * An unspecified behavior will be caused if the {@code id} parameter
  * of any particular {@code FocusEvent} instance is not
  * in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}.
@@ -66,6 +73,61 @@
 public class FocusEvent extends ComponentEvent {
 
     /**
+     * This enum represents the cause of a {@code FocusEvent}- the reason why it
+     * occurred. Possible reasons include mouse events, keyboard focus
+     * traversal, window activation.
+     * If no cause is provided then the reason is {@code UNKNOWN}.
+     *
+     * @since 9
+     */
+    public enum Cause {
+        /**
+         * The default value.
+         */
+        UNKNOWN,
+        /**
+         * An activating mouse event.
+         */
+        MOUSE_EVENT,
+        /**
+         * A focus traversal action with unspecified direction.
+         */
+        TRAVERSAL,
+        /**
+         * An up-cycle focus traversal action.
+         */
+        TRAVERSAL_UP,
+        /**
+         * A down-cycle focus traversal action.
+         */
+        TRAVERSAL_DOWN,
+        /**
+         * A forward focus traversal action.
+         */
+        TRAVERSAL_FORWARD,
+        /**
+         * A backward focus traversal action.
+         */
+        TRAVERSAL_BACKWARD,
+        /**
+         * Restoring focus after a focus request has been rejected.
+         */
+        ROLLBACK,
+        /**
+         * A system action causing an unexpected focus change.
+         */
+        UNEXPECTED,
+        /**
+         * An activation of a toplevel window.
+         */
+        ACTIVATION,
+        /**
+         * Clearing global focus owner.
+         */
+        CLEAR_GLOBAL_FOCUS_OWNER
+    }
+
+    /**
      * The first number in the range of ids used for focus events.
      */
     public static final int FOCUS_FIRST         = 1004;
@@ -86,6 +148,16 @@
     public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS
 
     /**
+     * A focus event has the reason why this event was generated.
+     * The cause is set during the focus event creation.
+     *
+     * @serial
+     * @see #getCause()
+     * @since 9
+     */
+    private final Cause cause;
+
+    /**
      * A focus event can have two different levels, permanent and temporary.
      * It will be set to true if some operation takes away the focus
      * temporarily and intends on getting it back once the event is completed.
@@ -115,7 +187,8 @@
 
     /**
      * Constructs a {@code FocusEvent} object with the
-     * specified temporary state and opposite {@code Component}.
+     * specified temporary state, opposite {@code Component} and the
+     * {@code Cause.UNKNOWN} cause.
      * The opposite {@code Component} is the other
      * {@code Component} involved in this focus change.
      * For a {@code FOCUS_GAINED} event, this is the
@@ -142,13 +215,57 @@
      * @see #getID()
      * @see #isTemporary()
      * @see #getOppositeComponent()
+     * @see Cause#UNKNOWN
      * @since 1.4
      */
     public FocusEvent(Component source, int id, boolean temporary,
                       Component opposite) {
+        this(source, id, temporary, opposite, Cause.UNKNOWN);
+    }
+
+    /**
+     * Constructs a {@code FocusEvent} object with the
+     * specified temporary state, opposite {@code Component} and the cause.
+     * The opposite {@code Component} is the other
+     * {@code Component} involved in this focus change.
+     * For a {@code FOCUS_GAINED} event, this is the
+     * {@code Component} that lost focus. For a
+     * {@code FOCUS_LOST} event, this is the {@code Component}
+     * that gained focus. If this focus change occurs with a native
+     * application, with a Java application in a different VM,
+     * or with no other {@code Component}, then the opposite
+     * {@code Component} is {@code null}.
+     * <p> This method throws an
+     * {@code IllegalArgumentException} if {@code source} or {@code cause}
+     * is {@code null}.
+     *
+     * @param source    The {@code Component} that originated the event
+     * @param id        An integer indicating the type of event.
+     *                  For information on allowable values, see
+     *                  the class description for {@link FocusEvent}
+     * @param temporary Equals {@code true} if the focus change is temporary;
+     *                  {@code false} otherwise
+     * @param opposite  The other Component involved in the focus change,
+     *                  or {@code null}
+     * @param cause     The focus event cause.
+     * @throws IllegalArgumentException if {@code source} equals {@code null}
+     *                                  or if {@code cause} equals {@code null}
+     * @see #getSource()
+     * @see #getID()
+     * @see #isTemporary()
+     * @see #getOppositeComponent()
+     * @see Cause
+     * @since 9
+     */
+    public FocusEvent(Component source, int id, boolean temporary,
+                      Component opposite, Cause cause) {
         super(source, id);
+        if (cause == null) {
+            throw new IllegalArgumentException("null cause");
+        }
         this.temporary = temporary;
         this.opposite = opposite;
+        this.cause = cause;
     }
 
     /**
@@ -220,8 +337,8 @@
 
         return (SunToolkit.targetToAppContext(opposite) ==
                 AppContext.getAppContext())
-            ? opposite
-            : null;
+                ? opposite
+                : null;
     }
 
     /**
@@ -233,17 +350,56 @@
     public String paramString() {
         String typeStr;
         switch(id) {
-          case FOCUS_GAINED:
-              typeStr = "FOCUS_GAINED";
-              break;
-          case FOCUS_LOST:
-              typeStr = "FOCUS_LOST";
-              break;
-          default:
-              typeStr = "unknown type";
+            case FOCUS_GAINED:
+                typeStr = "FOCUS_GAINED";
+                break;
+            case FOCUS_LOST:
+                typeStr = "FOCUS_LOST";
+                break;
+            default:
+                typeStr = "unknown type";
         }
         return typeStr + (temporary ? ",temporary" : ",permanent") +
-            ",opposite=" + getOppositeComponent();
+                ",opposite=" + getOppositeComponent() + ",cause=" + getCause();
+    }
+
+    /**
+     * Returns the event cause.
+     *
+     * @return one of {@link Cause} values
+     * @since 9
+     */
+    public final Cause getCause() {
+        return cause;
     }
 
-}
+    /**
+     * Checks if this deserialized {@code FocusEvent} instance is compatible
+     * with the current specification which implies that focus event has
+     * non-null {@code cause} value. If the check fails a new {@code FocusEvent}
+     * instance is returned which {@code cause} field equals to
+     * {@link Cause#UNKNOWN} and its other fields have the same values as in
+     * this {@code FocusEvent} instance.
+     *
+     * @serial
+     * @see #cause
+     * @since 9
+     */
+    @SuppressWarnings("serial")
+    Object readResolve() throws ObjectStreamException {
+        if (cause != null) {
+            return this;
+        }
+        FocusEvent focusEvent = new FocusEvent(new Component(){}, getID(),
+                isTemporary(), getOppositeComponent());
+        focusEvent.setSource(null);
+        focusEvent.consumed = consumed;
+
+        AWTAccessor.AWTEventAccessor accessor =
+                AWTAccessor.getAWTEventAccessor();
+        accessor.setBData(focusEvent, accessor.getBData(this));
+        return focusEvent;
+    }
+
+
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextAttribute.java	Wed Jul 05 21:39:33 2017 +0200
@@ -79,7 +79,7 @@
  *   will be ignored.
  *   <li>The identity of the value does not matter, only the actual
  *   value.  For example, {@code TextAttribute.WEIGHT_BOLD} and
- *   {@code new Float(2.0)}
+ *   {@code Float.valueOf(2.0f)}
  *   indicate the same {@code WEIGHT}.
  *   <li>Attribute values of type {@code Number} (used for
  *   {@code WEIGHT}, {@code WIDTH}, {@code POSTURE},
--- a/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextMeasurer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -105,7 +105,7 @@
         String s = System.getProperty("estLines");
         if (s != null) {
             try {
-                Float f = new Float(s);
+                Float f = Float.valueOf(s);
                 EST_LINES = f.floatValue();
             }
             catch(NumberFormatException e) {
--- a/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/renderable/ParameterBlock.java	Wed Jul 05 21:39:33 2017 +0200
@@ -392,7 +392,7 @@
      *         the specified parameter.
      */
     public ParameterBlock add(float f) {
-        return add(new Float(f));
+        return add(Float.valueOf(f));
     }
 
     /**
@@ -403,7 +403,7 @@
      *         the specified parameter.
      */
     public ParameterBlock add(double d) {
-        return add(new Double(d));
+        return add(Double.valueOf(d));
     }
 
     /**
@@ -521,7 +521,7 @@
      *        the specified parameter.
      */
     public ParameterBlock set(float f, int index) {
-        return set(new Float(f), index);
+        return set(Float.valueOf(f), index);
     }
 
     /**
@@ -537,7 +537,7 @@
      *        the specified parameter.
      */
     public ParameterBlock set(double d, int index) {
-        return set(new Double(d), index);
+        return set(Double.valueOf(d), index);
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/peer/ComponentPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,12 +27,12 @@
 
 import java.awt.*;
 import java.awt.event.PaintEvent;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.image.ColorModel;
 import java.awt.image.ImageObserver;
 import java.awt.image.ImageProducer;
 import java.awt.image.VolatileImage;
 
-import sun.awt.CausedFocusEvent;
 import sun.java2d.pipe.Region;
 
 
@@ -343,7 +343,7 @@
      */
     boolean requestFocus(Component lightweightChild, boolean temporary,
                          boolean focusedWindowChangeAllowed, long time,
-                         CausedFocusEvent.Cause cause);
+                         Cause cause);
 
     /**
      * Returns {@code true} when the component takes part in the focus
--- a/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/java/awt/print/PrinterJob.java	Wed Jul 05 21:39:33 2017 +0200
@@ -577,6 +577,8 @@
     /**
      * Gets the name of the printing user.
      * @return the name of the printing user
+     * @throws SecurityException if a security manager exists and
+     *         PropertyPermission - user.name is not given in the policy file
      */
     public abstract String getUserName();
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,6 @@
 
 import java.awt.*;
 import java.awt.event.*;
-import java.awt.peer.LightweightPeer;
 
 import java.applet.Applet;
 
@@ -57,7 +56,6 @@
 import sun.awt.AWTAccessor;
 import sun.awt.SunToolkit;
 import sun.swing.SwingUtilities2;
-import sun.swing.UIClientPropertyKey;
 
 /**
  * The base class for all Swing components except top-level containers.
@@ -3558,7 +3556,7 @@
         new sun.awt.RequestFocusController() {
             public boolean acceptRequestFocus(Component from, Component to,
                                               boolean temporary, boolean focusedWindowChangeAllowed,
-                                              sun.awt.CausedFocusEvent.Cause cause)
+                                              FocusEvent.Cause cause)
             {
                 if ((to == null) || !(to instanceof JComponent)) {
                     return true;
--- a/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JLayeredPane.java	Wed Jul 05 21:39:33 2017 +0200
@@ -98,7 +98,7 @@
  * <PRE>
  *     layeredPane.add(child, JLayeredPane.DEFAULT_LAYER);
  * or
- *     layeredPane.add(child, new Integer(10));
+ *     layeredPane.add(child, Integer.valueOf.valueOf(10));
  * </PRE>
  * The layer attribute can also be set on a Component by calling<PRE>
  *     layeredPaneParent.setLayer(child, 10)</PRE>
@@ -162,23 +162,23 @@
 @SuppressWarnings("serial")
 public class JLayeredPane extends JComponent implements Accessible {
     /// Watch the values in getObjectForLayer()
-    /** Convenience object defining the Default layer. Equivalent to new Integer(0).*/
+    /** Convenience object defining the Default layer. Equivalent to Integer.valueOf(0).*/
     public static final Integer DEFAULT_LAYER = 0;
-    /** Convenience object defining the Palette layer. Equivalent to new Integer(100).*/
+    /** Convenience object defining the Palette layer. Equivalent to Integer.valueOf(100).*/
     public static final Integer PALETTE_LAYER = 100;
-    /** Convenience object defining the Modal layer. Equivalent to new Integer(200).*/
+    /** Convenience object defining the Modal layer. Equivalent to Integer.valueOf(200).*/
     public static final Integer MODAL_LAYER = 200;
-    /** Convenience object defining the Popup layer. Equivalent to new Integer(300).*/
+    /** Convenience object defining the Popup layer. Equivalent to Integer.valueOf(300).*/
     public static final Integer POPUP_LAYER = 300;
-    /** Convenience object defining the Drag layer. Equivalent to new Integer(400).*/
+    /** Convenience object defining the Drag layer. Equivalent to Integer.valueOf(400).*/
     public static final Integer DRAG_LAYER = 400;
     /** Convenience object defining the Frame Content layer.
       * This layer is normally only use to position the contentPane and menuBar
       * components of JFrame.
-      * Equivalent to new Integer(-30000).
+      * Equivalent to Integer.valueOf(-30000).
       * @see JFrame
       */
-    public static final Integer FRAME_CONTENT_LAYER = new Integer(-30000);
+    public static final Integer FRAME_CONTENT_LAYER = -30000;
 
     /** Bound property */
     public static final String LAYER_PROPERTY = "layeredContainerLayer";
--- a/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JProgressBar.java	Wed Jul 05 21:39:33 2017 +0200
@@ -478,7 +478,7 @@
             if (format == null) {
                 format = NumberFormat.getPercentInstance();
             }
-            return format.format(new Double(getPercentComplete()));
+            return format.format(Double.valueOf(getPercentComplete()));
         }
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java	Wed Jul 05 21:39:33 2017 +0200
@@ -81,7 +81,7 @@
  *      TableModel dataModel = new AbstractTableModel() {
  *          public int getColumnCount() { return 10; }
  *          public int getRowCount() { return 10;}
- *          public Object getValueAt(int row, int col) { return new Integer(row*col); }
+ *          public Object getValueAt(int row, int col) { return Integer.valueOf(row*col); }
  *      };
  *      JTable table = new JTable(dataModel);
  *      JScrollPane scrollpane = new JScrollPane(table);
--- a/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/SpinnerNumberModel.java	Wed Jul 05 21:39:33 2017 +0200
@@ -51,10 +51,10 @@
  * range zero to one hundred, with
  * fifty as the initial value, one could write:
  * <pre>
- * Integer value = new Integer(50);
- * Integer min = new Integer(0);
- * Integer max = new Integer(100);
- * Integer step = new Integer(1);
+ * Integer value = Integer.valueOf(50);
+ * Integer min = Integer.valueOf(0);
+ * Integer max = Integer.valueOf(100);
+ * Integer step = Integer.valueOf(1);
  * SpinnerNumberModel model = new SpinnerNumberModel(value, min, max, step);
  * int fifty = model.getNumber().intValue();
  * </pre>
@@ -175,7 +175,8 @@
      *     <code>minimum &lt;= value &lt;= maximum</code>
      */
     public SpinnerNumberModel(double value, double minimum, double maximum, double stepSize) {
-        this(new Double(value), new Double(minimum), new Double(maximum), new Double(stepSize));
+        this(Double.valueOf(value), Double.valueOf(minimum),
+             Double.valueOf(maximum), Double.valueOf(stepSize));
     }
 
 
@@ -337,10 +338,10 @@
         if ((value instanceof Float) || (value instanceof Double)) {
             double v = value.doubleValue() + (stepSize.doubleValue() * (double)dir);
             if (value instanceof Double) {
-                newValue = new Double(v);
+                newValue = Double.valueOf(v);
             }
             else {
-                newValue = new Float(v);
+                newValue = Float.valueOf((float)v);
             }
         } else {
             long v = value.longValue() + (stepSize.longValue() * (long)dir);
--- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java	Wed Jul 05 21:39:33 2017 +0200
@@ -846,14 +846,46 @@
     }
 
     /**
+     * Check whether MouseEvent contains speficied mouse button or
+     * mouse button down mask based on MouseEvent ID.
+     *
+     * @param anEvent  a MouseEvent object
+     * @param mouseButton mouse button type
+     * @param mouseButtonDownMask mouse button down mask event modifier
+     *
+     * @return true if the anEvent contains speficied mouseButton or
+     * mouseButtonDownMask based on MouseEvent ID.
+     */
+    private static boolean checkMouseButton(MouseEvent anEvent,
+                                            int mouseButton,
+                                            int mouseButtonDownMask)
+    {
+        switch (anEvent.getID()) {
+        case MouseEvent.MOUSE_PRESSED:
+        case MouseEvent.MOUSE_RELEASED:
+        case MouseEvent.MOUSE_CLICKED:
+            return (anEvent.getButton() == mouseButton);
+
+        case MouseEvent.MOUSE_ENTERED:
+        case MouseEvent.MOUSE_EXITED:
+        case MouseEvent.MOUSE_DRAGGED:
+            return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0);
+
+        default:
+            return ((anEvent.getModifiersEx() & mouseButtonDownMask) != 0 ||
+                    anEvent.getButton() == mouseButton);
+        }
+    }
+
+    /**
      * Returns true if the mouse event specifies the left mouse button.
      *
      * @param anEvent  a MouseEvent object
      * @return true if the left mouse button was active
      */
     public static boolean isLeftMouseButton(MouseEvent anEvent) {
-         return ((anEvent.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0 ||
-                 anEvent.getButton() == MouseEvent.BUTTON1);
+        return checkMouseButton(anEvent, MouseEvent.BUTTON1,
+                                InputEvent.BUTTON1_DOWN_MASK);
     }
 
     /**
@@ -863,8 +895,8 @@
      * @return true if the middle mouse button was active
      */
     public static boolean isMiddleMouseButton(MouseEvent anEvent) {
-        return ((anEvent.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0 ||
-                anEvent.getButton() == MouseEvent.BUTTON2);
+        return checkMouseButton(anEvent, MouseEvent.BUTTON2,
+                                InputEvent.BUTTON2_DOWN_MASK);
     }
 
     /**
@@ -874,8 +906,8 @@
      * @return true if the right mouse button was active
      */
     public static boolean isRightMouseButton(MouseEvent anEvent) {
-        return ((anEvent.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) != 0 ||
-                anEvent.getButton() == MouseEvent.BUTTON3);
+        return checkMouseButton(anEvent, MouseEvent.BUTTON3,
+                                InputEvent.BUTTON3_DOWN_MASK);
     }
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIClientPropertyKey.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.swing;
+
+/**
+ * This interface is used only for tagging keys for client properties for
+ * {@code JComponent} set by UI which needs to be cleared on {@literal L&F}
+ * change and serialization.
+ * <p>
+ * All such keys are removed from client properties in
+ * {@code JComponent.setUI()} method after uninstalling old UI and before
+ * installing the new one. They are also removed prior to serialization.
+ *
+ * @author Igor Kushnirskiy
+ * @since 9
+ */
+public interface UIClientPropertyKey {
+}
--- a/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/UIDefaults.java	Wed Jul 05 21:39:33 2017 +0200
@@ -120,7 +120,7 @@
         Object[] uiDefaults = {
              "Font", new Font("Dialog", Font.BOLD, 12),
             "Color", Color.red,
-             "five", new Integer(5)
+             "five", Integer.valueOf(5)
         }
         UIDefaults myDefaults = new UIDefaults(uiDefaults);
      * </pre>
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/metal/OceanTheme.java	Wed Jul 05 21:39:33 2017 +0200
@@ -134,7 +134,7 @@
             new BorderUIResource.LineBorderUIResource(getPrimary1());
         // .30 0 DDE8F3 white secondary2
         java.util.List<?> buttonGradient = Arrays.asList(
-                 new Object[] {new Float(.3f), new Float(0f),
+                 new Object[] {Float.valueOf(.3f), Float.valueOf(0f),
                  new ColorUIResource(0xDDE8F3), getWhite(), getSecondary2() });
 
         // Other possible properties that aren't defined:
@@ -150,7 +150,7 @@
         Object directoryIcon = getIconResource("icons/ocean/directory.gif");
         Object fileIcon = getIconResource("icons/ocean/file.gif");
         java.util.List<?> sliderGradient = Arrays.asList(new Object[] {
-            new Float(.3f), new Float(.2f),
+            Float.valueOf(.3f), Float.valueOf(.2f),
             c8ddf2, getWhite(), new ColorUIResource(SECONDARY2) });
 
         Object[] defaults = new Object[] {
@@ -192,7 +192,7 @@
             "Menu.opaque", Boolean.FALSE,
 
             "MenuBar.gradient", Arrays.asList(new Object[] {
-                     new Float(1f), new Float(0f),
+                     Float.valueOf(1f), Float.valueOf(0f),
                      getWhite(), dadada,
                      new ColorUIResource(dadada) }),
             "MenuBar.borderColor", cccccc,
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthArrowButton.java	Wed Jul 05 21:39:33 2017 +0200
@@ -139,7 +139,6 @@
                 }
             }
 
-            context.dispose();
             return dim;
         }
     }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthBorder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -61,7 +61,6 @@
             return;
         }
         ui.paintBorder(context, g, x, y, width, height);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthButtonUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -105,7 +105,6 @@
             }
 
         }
-        context.dispose();
     }
 
     /**
@@ -125,7 +124,6 @@
         SynthContext context = getContext(b, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -226,7 +224,6 @@
         else {
             baseline = textRect.y + fm.getAscent();
         }
-        context.dispose();
         return baseline;
     }
 
@@ -253,7 +250,6 @@
         SynthLookAndFeel.update(context, g);
         paintBackground(context, g, c);
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -270,7 +266,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -321,7 +316,6 @@
     protected Icon getDefaultIcon(AbstractButton b) {
         SynthContext context = getContext(b);
         Icon icon = context.getStyle().getIcon(context, getPropertyPrefix() + "icon");
-        context.dispose();
         return icon;
     }
 
@@ -473,7 +467,6 @@
                b.getVerticalTextPosition(), b.getIconTextGap(),
                b.getDisplayedMnemonicIndex());
 
-        ss.dispose();
         return size;
     }
 
@@ -494,7 +487,6 @@
                b.getVerticalTextPosition(), b.getIconTextGap(),
                b.getDisplayedMnemonicIndex());
 
-        ss.dispose();
         return size;
     }
 
@@ -516,7 +508,6 @@
                b.getVerticalTextPosition(), b.getIconTextGap(),
                b.getDisplayedMnemonicIndex());
 
-        ss.dispose();
         return size;
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthColorChooserUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -65,7 +65,6 @@
         SynthContext context = getContext(chooser, ENABLED);
         AbstractColorChooserPanel[] panels = (AbstractColorChooserPanel[])
                      context.getStyle().get(context, "ColorChooser.panels");
-        context.dispose();
 
         if (panels == null) {
             panels = ColorChooserComponentFactory.getDefaultChooserPanels();
@@ -85,7 +84,6 @@
     private void updateStyle(JComponent c) {
         SynthContext context = getContext(c, ENABLED);
         style = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -96,7 +94,6 @@
         SynthContext context = getContext(chooser, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
         super.uninstallDefaults();
     }
@@ -155,7 +152,6 @@
         context.getPainter().paintColorChooserBackground(context, g, 0, 0,
                                                   c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -172,7 +168,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthComboBoxUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -144,7 +144,6 @@
             forceOpaque = style.getBoolean(context,
                     "ComboBox.forceOpaque", false);
         }
-        context.dispose();
 
         if(listBox != null) {
             SynthLookAndFeel.updateStyles(listBox);
@@ -182,7 +181,6 @@
         SynthContext context = getContext(comboBox, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -323,7 +321,6 @@
         context.getPainter().paintComboBoxBackground(context, g, 0, 0,
                                                   c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -340,7 +337,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthContext.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,8 +24,6 @@
  */
 package javax.swing.plaf.synth;
 
-import java.util.Queue;
-import java.util.concurrent.ConcurrentLinkedQueue;
 import javax.swing.JComponent;
 
 /**
@@ -40,7 +38,6 @@
  * @author Scott Violet
  */
 public class SynthContext {
-    private static final Queue<SynthContext> queue = new ConcurrentLinkedQueue<>();
 
     private JComponent component;
     private Region region;
@@ -54,19 +51,15 @@
     static SynthContext getContext(JComponent component,
                                    Region region, SynthStyle style,
                                    int state) {
-        SynthContext context = queue.poll();
-        if (context == null) {
-            context = new SynthContext();
-        }
-        context.reset(component, region, style, state);
+        SynthContext context = new SynthContext();
+        context.component = component;
+        context.region = region;
+        context.style = style;
+        context.state = state;
         return context;
     }
 
-    static void releaseContext(SynthContext context) {
-        queue.offer(context);
-    }
-
-    SynthContext() {
+    private SynthContext() {
     }
 
     /**
@@ -86,7 +79,11 @@
             throw new NullPointerException(
                 "You must supply a non-null component, region and style");
         }
-        reset(component, region, style, state);
+
+        this.component = component;
+        this.region = region;
+        this.style = style;
+        this.state = state;
     }
 
 
@@ -147,23 +144,6 @@
     }
 
     /**
-     * Resets the state of the Context.
-     */
-    void reset(JComponent component, Region region, SynthStyle style,
-               int state) {
-        this.component = component;
-        this.region = region;
-        this.style = style;
-        this.state = state;
-    }
-
-    void dispose() {
-        this.component = null;
-        this.style = null;
-        releaseContext(this);
-    }
-
-    /**
      * Convenience method to get the Painter from the current SynthStyle.
      * This will NEVER return null.
      */
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDefaultLookup.java	Wed Jul 05 21:39:33 2017 +0200
@@ -41,7 +41,6 @@
         }
         SynthContext context = ((SynthUI)ui).getContext(c);
         Object value = context.getStyle().get(context, key);
-        context.dispose();
         return value;
     }
 }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopIconUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -121,7 +121,6 @@
     private void updateStyle(JComponent c) {
         SynthContext context = getContext(c, ENABLED);
         style = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -131,7 +130,6 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(desktopIcon, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -171,7 +169,6 @@
         context.getPainter().paintDesktopIconBackground(context, g, 0, 0,
                                                   c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -188,7 +185,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -119,7 +119,6 @@
             uninstallKeyboardActions();
             installKeyboardActions();
         }
-        context.dispose();
     }
 
     /**
@@ -143,7 +142,6 @@
         SynthContext context = getContext(desktop, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         if (taskBar != null) {
@@ -460,7 +458,6 @@
         context.getPainter().paintDesktopPaneBackground(context, g, 0, 0,
                                                   c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -477,7 +474,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthEditorPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -83,7 +83,6 @@
         c.putClientProperty("caretAspectRatio", null);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         Object clientProperty =
@@ -127,7 +126,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -165,7 +163,6 @@
         SynthLookAndFeel.update(context, g);
         paintBackground(context, g, c);
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameTitlePane.java	Wed Jul 05 21:39:33 2017 +0200
@@ -138,7 +138,6 @@
                 }
             }
         }
-        context.dispose();
     }
 
     protected void installDefaults() {
@@ -149,7 +148,6 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(this, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
         JInternalFrame.JDesktopIcon di = frame.getDesktopIcon();
         if(di != null && di.getComponentPopupMenu() == systemPopupMenu) {
@@ -235,7 +233,6 @@
         context.getPainter().paintInternalFrameTitlePaneBackground(context,
                           g, 0, 0, getWidth(), getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     protected void paint(SynthContext context, Graphics g) {
@@ -321,7 +318,6 @@
         SynthContext context = getContext(this);
         LayoutManager lm =
             (LayoutManager)style.get(context, "InternalFrameTitlePane.titlePaneLayout");
-        context.dispose();
         return (lm != null) ? lm : new SynthTitlePaneLayout();
     }
 
@@ -362,7 +358,6 @@
                              Image.SCALE_SMOOTH));
             }
         }
-        context.dispose();
         menuButton.setIcon(frameIcon);
     }
 
@@ -433,7 +428,6 @@
             Insets insets = getInsets();
             height += insets.top + insets.bottom;
             width += insets.left + insets.right;
-            context.dispose();
             return new Dimension(width, height);
         }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthInternalFrameUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -118,7 +118,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -128,7 +127,6 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(frame, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
         if(frame.getLayout() == internalFrameLayout) {
             frame.setLayout(null);
@@ -216,7 +214,6 @@
         context.getPainter().paintInternalFrameBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -233,7 +230,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLabelUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -67,7 +67,6 @@
     void updateStyle(JLabel c) {
         SynthContext context = getContext(c, ENABLED);
         style = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -78,7 +77,6 @@
         SynthContext context = getContext(c, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -150,7 +148,6 @@
         else {
             baseline = textRect.y + fm.getAscent();
         }
-        context.dispose();
         return baseline;
     }
 
@@ -174,7 +171,6 @@
         context.getPainter().paintLabelBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -191,7 +187,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -242,7 +237,6 @@
                label.getVerticalTextPosition(), label.getIconTextGap(),
                label.getDisplayedMnemonicIndex());
 
-        context.dispose();
         return size;
     }
 
@@ -263,7 +257,6 @@
                label.getVerticalTextPosition(), label.getIconTextGap(),
                label.getDisplayedMnemonicIndex());
 
-        context.dispose();
         return size;
     }
 
@@ -284,7 +277,6 @@
                label.getVerticalTextPosition(), label.getIconTextGap(),
                label.getDisplayedMnemonicIndex());
 
-        context.dispose();
         return size;
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthListUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -75,7 +75,6 @@
         SynthLookAndFeel.update(context, g);
         context.getPainter().paintListBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
-        context.dispose();
         paint(g, c);
     }
 
@@ -162,7 +161,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -175,7 +173,6 @@
         SynthContext context = getContext(list, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthLookAndFeel.java	Wed Jul 05 21:39:33 2017 +0200
@@ -976,7 +976,6 @@
                 if (currBG != null && !currBG.equals(lastBG)) {
                     comp.repaint();
                 }
-                context.dispose();
             }
         }
     }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuBarUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -83,7 +83,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -94,7 +93,6 @@
         SynthContext context = getContext(menuBar, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -143,7 +141,6 @@
         context.getPainter().paintMenuBarBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -160,7 +157,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuItemUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -124,13 +124,11 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
 
         SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
                                              ENABLED);
 
         accStyle = SynthLookAndFeel.updateStyle(accContext, this);
-        accContext.dispose();
     }
 
     /**
@@ -140,13 +138,11 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(menuItem, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         SynthContext accContext = getContext(menuItem,
                                      Region.MENU_ITEM_ACCELERATOR, ENABLED);
         accStyle.uninstallDefaults(accContext);
-        accContext.dispose();
         accStyle = null;
 
         super.uninstallDefaults();
@@ -218,8 +214,6 @@
                 defaultTextIconGap, acceleratorDelimiter,
                 MenuItemLayoutHelper.useCheckAndArrow(menuItem),
                 getPropertyPrefix());
-        context.dispose();
-        accContext.dispose();
         return value;
     }
 
@@ -243,7 +237,6 @@
         SynthLookAndFeel.update(context, g);
         paintBackground(context, g, c);
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -260,7 +253,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -280,7 +272,6 @@
         Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
         SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
               acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
-        accContext.dispose();
     }
 
     void paintBackground(SynthContext context, Graphics g, JComponent c) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthMenuUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -110,13 +110,11 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
 
         SynthContext accContext = getContext(mi, Region.MENU_ITEM_ACCELERATOR,
                                              ENABLED);
 
         accStyle = SynthLookAndFeel.updateStyle(accContext, this);
-        accContext.dispose();
     }
 
     /**
@@ -140,13 +138,11 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(menuItem, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         SynthContext accContext = getContext(menuItem,
                                      Region.MENU_ITEM_ACCELERATOR, ENABLED);
         accStyle.uninstallDefaults(accContext);
-        accContext.dispose();
         accStyle = null;
 
         super.uninstallDefaults();
@@ -218,8 +214,6 @@
                 defaultTextIconGap, acceleratorDelimiter,
                 MenuItemLayoutHelper.useCheckAndArrow(menuItem),
                 getPropertyPrefix());
-        context.dispose();
-        accContext.dispose();
         return value;
     }
 
@@ -243,7 +237,6 @@
         context.getPainter().paintMenuBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -260,7 +253,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -279,7 +271,6 @@
         Icon arrowIcon = style.getIcon(context, prefix + ".arrowIcon");
         SynthGraphicsUtils.paint(context, accContext, g, checkIcon, arrowIcon,
               acceleratorDelimiter, defaultTextIconGap, getPropertyPrefix());
-        accContext.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthOptionPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -88,7 +88,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -99,7 +98,6 @@
         SynthContext context = getContext(optionPane, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -125,7 +123,6 @@
             SynthContext context = getContext(optionPane, ENABLED);
             optionPane.add(Box.createVerticalStrut(context.getStyle().
                        getInt(context, "OptionPane.separatorPadding", 6)));
-            context.dispose();
         }
         optionPane.add(createButtonArea());
         optionPane.applyComponentOrientation(optionPane.getComponentOrientation());
@@ -167,7 +164,6 @@
         context.getPainter().paintOptionPaneBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -184,7 +180,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -259,7 +254,6 @@
         SynthContext context = getContext(optionPane, ENABLED);
         cons.anchor = context.getStyle().getInt(context,
                       "OptionPane.messageAnchor", GridBagConstraints.CENTER);
-        context.dispose();
 
         cons.insets = new Insets(0,0,3,0);
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPanelUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -108,14 +108,12 @@
         SynthContext context = getContext(p, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
     private void updateStyle(JPanel c) {
         SynthContext context = getContext(c, ENABLED);
         style = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -154,7 +152,6 @@
         context.getPainter().paintPanelBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -171,7 +168,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPopupMenuUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -77,7 +77,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -97,7 +96,6 @@
         SynthContext context = getContext(popupMenu, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         if (popupMenu.getLayout() instanceof UIResource) {
@@ -150,7 +148,6 @@
         context.getPainter().paintPopupMenuBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -167,7 +164,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthProgressBarUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -118,7 +118,6 @@
         }
         minBarSize = (Dimension)style.get(context, "ProgressBar.minBarSize");
         glowWidth = style.getInt(context, "ProgressBar.glowWidth", 0);
-        context.dispose();
     }
 
     /**
@@ -129,7 +128,6 @@
         SynthContext context = getContext(progressBar, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -160,7 +158,6 @@
             SynthContext context = getContext(c);
             Font font = context.getStyle().getFont(context);
             FontMetrics metrics = progressBar.getFontMetrics(font);
-            context.dispose();
             return (height - metrics.getAscent() - metrics.getDescent()) / 2 +
                     metrics.getAscent();
         }
@@ -216,7 +213,6 @@
                           g, 0, 0, c.getWidth(), c.getHeight(),
                           progressBar.getOrientation());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -233,7 +229,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthRootPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -67,7 +67,6 @@
         SynthContext context = getContext(root, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -97,7 +96,6 @@
                 installKeyboardActions((JRootPane)c);
             }
         }
-        context.dispose();
     }
 
     /**
@@ -120,7 +118,6 @@
         context.getPainter().paintRootPaneBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -137,7 +134,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollBarUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -129,15 +129,12 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
 
         context = getContext(c, Region.SCROLL_BAR_TRACK, ENABLED);
         trackStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
 
         context = getContext(c, Region.SCROLL_BAR_THUMB, ENABLED);
         thumbStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -165,17 +162,14 @@
     protected void uninstallDefaults(){
         SynthContext context = getContext(scrollbar, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         context = getContext(scrollbar, Region.SCROLL_BAR_TRACK, ENABLED);
         trackStyle.uninstallDefaults(context);
-        context.dispose();
         trackStyle = null;
 
         context = getContext(scrollbar, Region.SCROLL_BAR_THUMB, ENABLED);
         thumbStyle.uninstallDefaults(context);
-        context.dispose();
         thumbStyle = null;
 
         super.uninstallDefaults();
@@ -222,7 +216,6 @@
         SynthContext context = getContext(scrollbar);
         boolean value = style.getBoolean(context,
                       "ScrollBar.allowsAbsolutePositioning", false);
-        context.dispose();
         return value;
     }
 
@@ -247,7 +240,6 @@
                           g, 0, 0, c.getWidth(), c.getHeight(),
                           scrollbar.getOrientation());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -264,7 +256,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -278,11 +269,9 @@
         SynthContext subcontext = getContext(scrollbar,
                                              Region.SCROLL_BAR_TRACK);
         paintTrack(subcontext, g, getTrackBounds());
-        subcontext.dispose();
 
         subcontext = getContext(scrollbar, Region.SCROLL_BAR_THUMB);
         paintThumb(subcontext, g, getThumbBounds());
-        subcontext.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthScrollPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -83,7 +83,6 @@
         context.getPainter().paintScrollPaneBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -100,7 +99,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -150,7 +148,6 @@
                 installKeyboardActions(c);
             }
         }
-        context.dispose();
     }
 
     /**
@@ -178,7 +175,6 @@
         SynthContext context = getContext(c, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
 
         if (scrollpane.getViewportBorder() instanceof UIResource) {
             scrollpane.setViewportBorder(null);
@@ -254,7 +250,6 @@
             }
             context.getPainter().paintViewportBorder(context, g, x, y, width,
                                                      height);
-            context.dispose();
         }
 
         @Override
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSeparatorUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -106,7 +106,6 @@
             }
         }
 
-        context.dispose();
     }
 
     /**
@@ -120,7 +119,6 @@
         SynthContext context = getContext(c, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -168,7 +166,6 @@
                           g, 0, 0, c.getWidth(), c.getHeight(),
                           separator.getOrientation());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -185,7 +182,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -231,7 +227,6 @@
             size = new Dimension(insets.left + insets.right,
                                  insets.top + insets.bottom + thickness);
         }
-        context.dispose();
         return size;
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -116,17 +116,14 @@
     protected void uninstallDefaults(JSlider slider) {
         SynthContext context = getContext(slider, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         context = getContext(slider, Region.SLIDER_TRACK, ENABLED);
         sliderTrackStyle.uninstallDefaults(context);
-        context.dispose();
         sliderTrackStyle = null;
 
         context = getContext(slider, Region.SLIDER_THUMB, ENABLED);
         sliderThumbStyle.uninstallDefaults(context);
-        context.dispose();
         sliderThumbStyle = null;
     }
 
@@ -190,17 +187,14 @@
                 installKeyboardActions(c);
             }
         }
-        context.dispose();
 
         context = getContext(c, Region.SLIDER_TRACK, ENABLED);
         sliderTrackStyle =
             SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
 
         context = getContext(c, Region.SLIDER_THUMB, ENABLED);
         sliderThumbStyle =
             SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -252,14 +246,12 @@
             SynthContext trackContext = getContext(slider,
                                                    Region.SLIDER_TRACK);
             style.getInsets(trackContext, trackInsets);
-            trackContext.dispose();
             if (slider.getOrientation() == JSlider.HORIZONTAL) {
                 int valueHeight = 0;
                 if (paintValue) {
                     SynthContext context = getContext(slider);
                     valueHeight = context.getStyle().getGraphicsUtils(context).
                             getMaximumCharHeight(context);
-                    context.dispose();
                 }
                 int tickHeight = 0;
                 if (slider.getPaintTicks()) {
@@ -287,7 +279,6 @@
                         SynthContext context = getContext(slider);
                         valueHeight = context.getStyle().getGraphicsUtils(
                                 context).getMaximumCharHeight(context);
-                        context.dispose();
                     }
                     int contentHeight = height - insetCache.top -
                             insetCache.bottom;
@@ -359,7 +350,6 @@
         Insets trackInsets = new Insets(0, 0, 0, 0);
         SynthContext trackContext = getContext(slider, Region.SLIDER_TRACK);
         style.getInsets(trackContext, trackInsets);
-        trackContext.dispose();
 
         if (slider.getOrientation() == JSlider.HORIZONTAL) {
             // Calculate the height of all the subcomponents so we can center
@@ -509,7 +499,6 @@
                 trackRect.x = startX + tickRect.width + trackInsets.left;
             }
         }
-        context.dispose();
         lastSize = slider.getSize();
     }
 
@@ -715,7 +704,6 @@
             insetCache = newInsets;
             calculateGeometry();
         }
-        context.dispose();
     }
 
     /**
@@ -774,7 +762,6 @@
                           g, 0, 0, c.getWidth(), c.getHeight(),
                           slider.getOrientation());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -790,7 +777,6 @@
     public void paint(Graphics g, JComponent c) {
         SynthContext context = getContext(c);
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -835,13 +821,11 @@
         if (slider.getPaintTrack() && clip.intersects(trackRect)) {
             SynthContext subcontext = getContext(slider, Region.SLIDER_TRACK);
             paintTrack(subcontext, g, trackRect);
-            subcontext.dispose();
         }
 
         if (clip.intersects(thumbRect)) {
             SynthContext subcontext = getContext(slider, Region.SLIDER_THUMB);
             paintThumb(subcontext, g, thumbRect);
-            subcontext.dispose();
         }
 
         if (slider.getPaintTicks() && clip.intersects(tickRect)) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSpinnerUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -131,7 +131,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
 
@@ -151,7 +150,6 @@
         SynthContext context = getContext(spinner, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -301,7 +299,6 @@
         context.getPainter().paintSpinnerBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
 
@@ -319,7 +316,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneDivider.java	Wed Jul 05 21:39:33 2017 +0200
@@ -81,7 +81,6 @@
 
         context.getPainter().paintSplitPaneDividerForeground(context, g, 0, 0,
                 getWidth(), getHeight(), splitPane.getOrientation());
-        context.dispose();
 
         // super.paint(g2);
         for (int counter = 0; counter < getComponentCount(); counter++) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSplitPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -121,7 +121,6 @@
                                           ENABLED);
         SynthStyle oldDividerStyle = dividerStyle;
         dividerStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
 
         context = getContext(splitPane, ENABLED);
         SynthStyle oldStyle = style;
@@ -160,7 +159,6 @@
             divider.setBasicSplitPaneUI(this);
             splitPane.add(divider, JSplitPane.DIVIDER);
         }
-        context.dispose();
     }
 
     /**
@@ -180,12 +178,10 @@
         SynthContext context = getContext(splitPane, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         context = getContext(splitPane, Region.SPLIT_PANE_DIVIDER, ENABLED);
         dividerStyle.uninstallDefaults(context);
-        context.dispose();
         dividerStyle = null;
 
         super.uninstallDefaults();
@@ -287,7 +283,6 @@
         context.getPainter().paintSplitPaneBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -304,7 +299,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -338,7 +332,6 @@
         context.getPainter().paintSplitPaneDragDivider(context, g, x, y, w, h,
                                            splitPane.getOrientation());
         g.setClip(oldClip);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -154,27 +154,17 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
 
-        if (tabContext != null) {
-            tabContext.dispose();
-        }
         tabContext = getContext(c, Region.TABBED_PANE_TAB, ENABLED);
         this.tabStyle = SynthLookAndFeel.updateStyle(tabContext, this);
         tabInsets = tabStyle.getInsets(tabContext, null);
 
 
-        if (tabAreaContext != null) {
-            tabAreaContext.dispose();
-        }
         tabAreaContext = getContext(c, Region.TABBED_PANE_TAB_AREA, ENABLED);
         this.tabAreaStyle = SynthLookAndFeel.updateStyle(tabAreaContext, this);
         tabAreaInsets = tabAreaStyle.getInsets(tabAreaContext, null);
 
 
-        if (tabContentContext != null) {
-            tabContentContext.dispose();
-        }
         tabContentContext = getContext(c, Region.TABBED_PANE_CONTENT, ENABLED);
         this.tabContentStyle = SynthLookAndFeel.updateStyle(tabContentContext,
                                                             this);
@@ -207,21 +197,17 @@
     protected void uninstallDefaults() {
         SynthContext context = getContext(tabPane, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         tabStyle.uninstallDefaults(tabContext);
-        tabContext.dispose();
         tabContext = null;
         tabStyle = null;
 
         tabAreaStyle.uninstallDefaults(tabAreaContext);
-        tabAreaContext.dispose();
         tabAreaContext = null;
         tabAreaStyle = null;
 
         tabContentStyle.uninstallDefaults(tabContentContext);
-        tabContentContext.dispose();
         tabContentContext = null;
         tabContentStyle = null;
     }
@@ -374,7 +360,6 @@
         context.getPainter().paintTabbedPaneBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -424,7 +409,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -85,7 +85,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -109,7 +108,6 @@
         SynthContext context = getContext(header, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -142,7 +140,6 @@
         context.getPainter().paintTableHeaderBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -159,7 +156,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -189,7 +189,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -220,7 +219,6 @@
         }
         SynthContext context = getContext(table, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -273,7 +271,6 @@
         context.getPainter().paintTableBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -299,7 +296,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextAreaUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -88,7 +88,6 @@
         getComponent().removeFocusListener(handler);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
         super.uninstallDefaults();
     }
@@ -107,7 +106,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -142,7 +140,6 @@
         context.getPainter().paintTextAreaBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTextFieldUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -79,7 +79,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     static void updateStyle(JTextComponent comp, SynthContext context,
@@ -179,7 +178,6 @@
         SynthLookAndFeel.update(context, g);
         paintBackground(context, g, c);
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -262,7 +260,6 @@
         getComponent().removeFocusListener(handler);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
         super.uninstallDefaults();
     }
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolBarUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -98,11 +98,9 @@
         SynthContext context = getContext(
                 c, Region.TOOL_BAR_CONTENT, null, ENABLED);
         contentStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
 
         context = getContext(c, Region.TOOL_BAR_DRAG_WINDOW, null, ENABLED);
         dragWindowStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
 
         context = getContext(c, ENABLED);
         SynthStyle oldStyle = style;
@@ -116,7 +114,6 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
     }
 
     /**
@@ -127,7 +124,6 @@
         SynthContext context = getContext(toolBar, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         handleIcon = null;
@@ -135,13 +131,11 @@
         context = getContext(toolBar, Region.TOOL_BAR_CONTENT,
                              contentStyle, ENABLED);
         contentStyle.uninstallDefaults(context);
-        context.dispose();
         contentStyle = null;
 
         context = getContext(toolBar, Region.TOOL_BAR_DRAG_WINDOW,
                              dragWindowStyle, ENABLED);
         dragWindowStyle.uninstallDefaults(context);
-        context.dispose();
         dragWindowStyle = null;
 
         toolBar.setLayout(null);
@@ -215,7 +209,6 @@
                           g, 0, 0, c.getWidth(), c.getHeight(),
                           toolBar.getOrientation());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -232,7 +225,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -289,7 +281,6 @@
         SynthContext subcontext = getContext(
                 toolBar, Region.TOOL_BAR_CONTENT, contentStyle);
         paintContent(subcontext, g, contentRect);
-        subcontext.dispose();
     }
 
     /**
@@ -326,7 +317,6 @@
                                                            dragWindow.getOrientation());
         context.getPainter().paintToolBarDragWindowBorder(context, g, 0, 0, w, h,
                                                           dragWindow.getOrientation());
-        context.dispose();
     }
 
     //
@@ -383,7 +373,6 @@
             dim.width += insets.left + insets.right;
             dim.height += insets.top + insets.bottom;
 
-            context.dispose();
             return dim;
         }
 
@@ -421,7 +410,6 @@
             dim.width += insets.left + insets.right;
             dim.height += insets.top + insets.bottom;
 
-            context.dispose();
             return dim;
         }
 
@@ -543,7 +531,6 @@
                     }
                 }
             }
-            context.dispose();
         }
 
         private boolean isGlue(Component c) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthToolTipUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -68,7 +68,6 @@
     private void updateStyle(JComponent c) {
         SynthContext context = getContext(c, ENABLED);
         style = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -78,7 +77,6 @@
     protected void uninstallDefaults(JComponent c) {
         SynthContext context = getContext(c, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -139,7 +137,6 @@
         context.getPainter().paintToolTipBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -165,7 +162,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -218,7 +214,6 @@
                 prefSize.height += fm.getHeight();
             }
         }
-        context.dispose();
         return prefSize;
     }
 
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTreeUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -147,11 +147,9 @@
                 installKeyboardActions();
             }
         }
-        context.dispose();
 
         context = getContext(tree, Region.TREE_CELL, ENABLED);
         cellStyle = SynthLookAndFeel.updateStyle(context, this);
-        context.dispose();
     }
 
     /**
@@ -223,12 +221,10 @@
         SynthContext context = getContext(tree, ENABLED);
 
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
 
         context = getContext(tree, Region.TREE_CELL, ENABLED);
         cellStyle.uninstallDefaults(context);
-        context.dispose();
         cellStyle = null;
 
 
@@ -266,7 +262,6 @@
         context.getPainter().paintTreeBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -292,7 +287,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -425,7 +419,6 @@
                 row++;
             }
         }
-        cellContext.dispose();
 
         paintDropLine(g);
 
@@ -743,7 +736,6 @@
                     context.getPainter().paintTreeCellFocus(context, g,
                             0, 0, getWidth() - imageOffset, getHeight());
                 }
-                context.dispose();
             }
             SynthLookAndFeel.resetSelectedUI();
         }
@@ -785,7 +777,6 @@
             if (context == null) {
                 context = getContext(tree);
                 SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
-                context.dispose();
             }
             else {
                 SynthGraphicsUtils.paintIcon(expandedIcon, context, g, x, y, w, h);
@@ -797,7 +788,6 @@
             if (context == null) {
                 context = getContext(tree);
                 width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
-                context.dispose();
             }
             else {
                 width = SynthGraphicsUtils.getIconWidth(expandedIcon, context);
@@ -810,7 +800,6 @@
             if (context == null) {
                 context = getContext(tree);
                 height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
-                context.dispose();
             }
             else {
                 height = SynthGraphicsUtils.getIconHeight(expandedIcon, context);
--- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthViewportUI.java	Wed Jul 05 21:39:33 2017 +0200
@@ -99,7 +99,6 @@
             newStyle.installDefaults(context);
         }
         this.style = newStyle;
-        context.dispose();
     }
 
     /**
@@ -128,7 +127,6 @@
     protected void uninstallDefaults(JComponent c) {
         SynthContext context = getContext(c, ENABLED);
         style.uninstallDefaults(context);
-        context.dispose();
         style = null;
     }
 
@@ -168,7 +166,6 @@
         context.getPainter().paintViewportBackground(context,
                           g, 0, 0, c.getWidth(), c.getHeight());
         paint(context, g);
-        context.dispose();
     }
 
     /**
@@ -202,7 +199,6 @@
         SynthContext context = getContext(c);
 
         paint(context, g);
-        context.dispose();
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/JTextComponent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -2580,7 +2580,7 @@
          * @param e the DocumentEvent
          */
         public void insertUpdate(DocumentEvent e) {
-            final Integer pos = new Integer (e.getOffset());
+            final Integer pos = e.getOffset();
             if (SwingUtilities.isEventDispatchThread()) {
                 firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
             } else {
@@ -2602,7 +2602,7 @@
          * @param e the DocumentEvent
          */
         public void removeUpdate(DocumentEvent e) {
-            final Integer pos = new Integer (e.getOffset());
+            final Integer pos = e.getOffset();
             if (SwingUtilities.isEventDispatchThread()) {
                 firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
             } else {
@@ -2624,7 +2624,7 @@
          * @param e the DocumentEvent
          */
         public void changedUpdate(DocumentEvent e) {
-            final Integer pos = new Integer (e.getOffset());
+            final Integer pos = e.getOffset();
             if (SwingUtilities.isEventDispatchThread()) {
                 firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, pos);
             } else {
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/NumberFormatter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -73,7 +73,7 @@
  * type the value class represents. For example:
  * <code>setValueClass(Integer.class)</code> will cause the resulting
  * value to be created via
- * <code>new Integer(((Number)formatter.parseObject(string)).intValue())</code>.
+ * <code>Integer.valueOf(((Number)formatter.parseObject(string)).intValue())</code>.
  * This is typically useful if you
  * wish to set a min/max value as the various <code>Number</code>
  * implementations are generally not comparable to each other. This is also
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/StyleConstants.java	Wed Jul 05 21:39:33 2017 +0200
@@ -608,7 +608,7 @@
      * @param i the value
      */
     public static void setFirstLineIndent(MutableAttributeSet a, float i) {
-        a.addAttribute(FirstLineIndent, new Float(i));
+        a.addAttribute(FirstLineIndent, Float.valueOf(i));
     }
 
     /**
@@ -632,7 +632,7 @@
      * @param i the value
      */
     public static void setRightIndent(MutableAttributeSet a, float i) {
-        a.addAttribute(RightIndent, new Float(i));
+        a.addAttribute(RightIndent, Float.valueOf(i));
     }
 
     /**
@@ -656,7 +656,7 @@
      * @param i the value
      */
     public static void setLeftIndent(MutableAttributeSet a, float i) {
-        a.addAttribute(LeftIndent, new Float(i));
+        a.addAttribute(LeftIndent, Float.valueOf(i));
     }
 
     /**
@@ -680,7 +680,7 @@
      * @param i the value
      */
     public static void setLineSpacing(MutableAttributeSet a, float i) {
-        a.addAttribute(LineSpacing, new Float(i));
+        a.addAttribute(LineSpacing, Float.valueOf(i));
     }
 
     /**
@@ -704,7 +704,7 @@
      * @param i the value
      */
     public static void setSpaceAbove(MutableAttributeSet a, float i) {
-        a.addAttribute(SpaceAbove, new Float(i));
+        a.addAttribute(SpaceAbove, Float.valueOf(i));
     }
 
     /**
@@ -728,7 +728,7 @@
      * @param i the value
      */
     public static void setSpaceBelow(MutableAttributeSet a, float i) {
-        a.addAttribute(SpaceBelow, new Float(i));
+        a.addAttribute(SpaceBelow, Float.valueOf(i));
     }
 
     /**
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/html/CSS.java	Wed Jul 05 21:39:33 2017 +0200
@@ -2564,7 +2564,7 @@
          *   represents the CSS attribute value
          */
         Object toStyleConstants(StyleConstants key, View v) {
-            return new Float(getValue(false));
+            return Float.valueOf(getValue(false));
         }
 
         /** If true, span is a percentage value, and that to determine
@@ -2837,25 +2837,25 @@
         static Hashtable<String, Float> lengthMapping = new Hashtable<String, Float>(6);
         static Hashtable<String, Float> w3cLengthMapping = new Hashtable<String, Float>(6);
         static {
-            lengthMapping.put("pt", new Float(1f));
+            lengthMapping.put("pt", Float.valueOf(1f));
             // Not sure about 1.3, determined by experiementation.
-            lengthMapping.put("px", new Float(1.3f));
-            lengthMapping.put("mm", new Float(2.83464f));
-            lengthMapping.put("cm", new Float(28.3464f));
-            lengthMapping.put("pc", new Float(12f));
-            lengthMapping.put("in", new Float(72f));
+            lengthMapping.put("px", Float.valueOf(1.3f));
+            lengthMapping.put("mm", Float.valueOf(2.83464f));
+            lengthMapping.put("cm", Float.valueOf(28.3464f));
+            lengthMapping.put("pc", Float.valueOf(12f));
+            lengthMapping.put("in", Float.valueOf(72f));
             int res = 72;
             try {
                 res = Toolkit.getDefaultToolkit().getScreenResolution();
             } catch (HeadlessException e) {
             }
             // mapping according to the CSS2 spec
-            w3cLengthMapping.put("pt", new Float(res/72f));
-            w3cLengthMapping.put("px", new Float(1f));
-            w3cLengthMapping.put("mm", new Float(res/25.4f));
-            w3cLengthMapping.put("cm", new Float(res/2.54f));
-            w3cLengthMapping.put("pc", new Float(res/6f));
-            w3cLengthMapping.put("in", new Float(res));
+            w3cLengthMapping.put("pt", Float.valueOf(res/72f));
+            w3cLengthMapping.put("px", Float.valueOf(1f));
+            w3cLengthMapping.put("mm", Float.valueOf(res/25.4f));
+            w3cLengthMapping.put("cm", Float.valueOf(res/2.54f));
+            w3cLengthMapping.put("pc", Float.valueOf(res/6f));
+            w3cLengthMapping.put("in", Float.valueOf((float)res));
         }
 
         LengthUnit(String value, short defaultType, float defaultValue) {
--- a/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/javax/swing/text/rtf/RTFAttributes.java	Wed Jul 05 21:39:33 2017 +0200
@@ -357,7 +357,7 @@
         public static NumericAttribute NewTwips(int d, Object s, String r,
                                                 float ds, int dr)
         {
-            return new NumericAttribute(d, s, r, new Float(ds), dr, 20f);
+            return new NumericAttribute(d, s, r, Float.valueOf(ds), dr, 20f);
         }
 
         public static NumericAttribute NewTwips(int d, Object s, String r,
@@ -378,7 +378,7 @@
             if (scale == 1f)
                 swingValue = Integer.valueOf(parameter);
             else
-                swingValue = new Float(parameter / scale);
+                swingValue = Float.valueOf(parameter / scale);
             target.addAttribute(swingName, swingValue);
             return true;
         }
--- a/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/AWTAccessor.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -29,6 +29,7 @@
 
 import javax.accessibility.AccessibleContext;
 import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.dnd.DragSourceContext;
 import java.awt.dnd.DropTargetContext;
 import java.awt.dnd.peer.DragSourceContextPeer;
@@ -104,7 +105,7 @@
         /*
          * Requests focus to the component.
          */
-        boolean requestFocus(Component comp, CausedFocusEvent.Cause cause);
+        boolean requestFocus(Component comp, Cause cause);
         /*
          * Determines if the component can gain focus.
          */
@@ -438,7 +439,7 @@
                                            boolean temporary,
                                            boolean focusedWindowChangeAllowed,
                                            long time,
-                                           CausedFocusEvent.Cause cause);
+                                           Cause cause);
         /**
          * Delivers focus for the lightweight descendant of the heavyweight
          * synchronously.
--- a/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/CausedFocusEvent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,17 +27,18 @@
 
 import java.awt.event.FocusEvent;
 import java.awt.Component;
+import java.io.ObjectStreamException;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 
 /**
- * This class represents FocusEvents with a known "cause" - reason why this event happened. It can
- * be mouse press, traversal, activation, and so on - all causes are described as Cause enum. The
- * event with the cause can be constructed in two ways - explicitly through constructor of
- * CausedFocusEvent class or implicitly, by calling appropriate requestFocusXXX method with "cause"
- * parameter. The default cause is UNKNOWN.
+ * This class exists for deserialization compatibility only.
  */
-@SuppressWarnings("serial")
-public class CausedFocusEvent extends FocusEvent {
-    public enum Cause {
+class CausedFocusEvent extends FocusEvent {
+    private static final long serialVersionUID = -3647309088427840738L;
+
+    private enum Cause {
         UNKNOWN,
         MOUSE_EVENT,
         TRAVERSAL,
@@ -51,39 +52,82 @@
         NATIVE_SYSTEM,
         ACTIVATION,
         CLEAR_GLOBAL_FOCUS_OWNER,
-        RETARGETED
+        RETARGETED;
     };
 
+    @SuppressWarnings("serial")
+    private static final Component dummy = new Component(){};
+
     private final Cause cause;
 
-    public Cause getCause() {
-        return cause;
-    }
-
-    public String toString() {
-        return "java.awt.FocusEvent[" + super.paramString() + ",cause=" + cause + "] on " + getSource();
-    }
-
-    public CausedFocusEvent(Component source, int id, boolean temporary,
+    private CausedFocusEvent(Component source, int id, boolean temporary,
                             Component opposite, Cause cause) {
         super(source, id, temporary, opposite);
-        if (cause == null) {
-            cause = Cause.UNKNOWN;
-        }
-        this.cause = cause;
+        throw new IllegalStateException();
     }
 
-    /**
-     * Retargets the original focus event to the new target.  If the
-     * original focus event is CausedFocusEvent, it remains such and
-     * cause is copied.  Otherwise, new CausedFocusEvent is created,
-     * with cause as RETARGETED.
-     * @return retargeted event, or null if e is null
-     */
-    public static FocusEvent retarget(FocusEvent e, Component newSource) {
-        if (e == null) return null;
+    Object readResolve() throws ObjectStreamException {
+        FocusEvent.Cause newCause;
+        switch (cause) {
+            case UNKNOWN:
+                newCause = FocusEvent.Cause.UNKNOWN;
+                break;
+            case MOUSE_EVENT:
+                newCause = FocusEvent.Cause.MOUSE_EVENT;
+                break;
+            case TRAVERSAL:
+                newCause = FocusEvent.Cause.TRAVERSAL;
+                break;
+            case TRAVERSAL_UP:
+                newCause = FocusEvent.Cause.TRAVERSAL_UP;
+                break;
+            case TRAVERSAL_DOWN:
+                newCause = FocusEvent.Cause.TRAVERSAL_DOWN;
+                break;
+            case TRAVERSAL_FORWARD:
+                newCause = FocusEvent.Cause.TRAVERSAL_FORWARD;
+                break;
+            case TRAVERSAL_BACKWARD:
+                newCause = FocusEvent.Cause.TRAVERSAL_BACKWARD;
+                break;
+            case ROLLBACK:
+                newCause = FocusEvent.Cause.ROLLBACK;
+                break;
+            case NATIVE_SYSTEM:
+                newCause = FocusEvent.Cause.UNEXPECTED;
+                break;
+            case ACTIVATION:
+                newCause = FocusEvent.Cause.ACTIVATION;
+                break;
+            case CLEAR_GLOBAL_FOCUS_OWNER:
+                newCause = FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER;
+                break;
+            default:
+                newCause = FocusEvent.Cause.UNKNOWN;
+        }
 
-        return new CausedFocusEvent(newSource, e.getID(), e.isTemporary(), e.getOppositeComponent(),
-                                    (e instanceof CausedFocusEvent) ? ((CausedFocusEvent)e).getCause() : Cause.RETARGETED);
+        FocusEvent focusEvent = new FocusEvent(dummy, getID(), isTemporary(),
+                        getOppositeComponent(), newCause);
+        focusEvent.setSource(null);
+        try {
+            final Field consumedField = FocusEvent.class.getField("consumed");
+            AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                @Override
+                public Object run() {
+                    consumedField.setAccessible(true);
+                    try {
+                        consumedField.set(focusEvent, consumed);
+                    } catch (IllegalAccessException e) {
+                    }
+                    return null;
+                }
+            });
+        } catch (NoSuchFieldException e) {
+        }
+
+        AWTAccessor.AWTEventAccessor accessor =
+                                           AWTAccessor.getAWTEventAccessor();
+        accessor.setBData(focusEvent, accessor.getBData(this));
+        return focusEvent;
     }
 }
--- a/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/KeyboardFocusManagerPeerImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -60,8 +60,8 @@
                 focusLog.fine("Clearing global focus owner " + focusOwner);
             }
             if (focusOwner != null) {
-                FocusEvent fl = new CausedFocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
-                                                     CausedFocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
+                FocusEvent fl = new FocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
+                                                     FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
                 SunToolkit.postPriorityEvent(fl);
             }
         }
@@ -110,7 +110,7 @@
                                        boolean temporary,
                                        boolean focusedWindowChangeAllowed,
                                        long time,
-                                       CausedFocusEvent.Cause cause,
+                                       FocusEvent.Cause cause,
                                        Component currentFocusOwner) // provided by the descendant peers
     {
         if (lightweightChild == null) {
@@ -122,7 +122,7 @@
             currentOwner = null;
         }
         if (currentOwner != null) {
-            FocusEvent fl = new CausedFocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
+            FocusEvent fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
                                                  false, lightweightChild, cause);
 
             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -131,7 +131,7 @@
             SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
         }
 
-        FocusEvent fg = new CausedFocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
+        FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
                                              false, currentOwner, cause);
 
         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
@@ -142,7 +142,7 @@
     }
 
     // WARNING: Don't call it on the Toolkit thread.
-    public static boolean requestFocusFor(Component target, CausedFocusEvent.Cause cause) {
+    public static boolean requestFocusFor(Component target, FocusEvent.Cause cause) {
         return AWTAccessor.getComponentAccessor().requestFocus(target, cause);
     }
 
@@ -152,7 +152,7 @@
                                                      boolean temporary,
                                                      boolean focusedWindowChangeAllowed,
                                                      long time,
-                                                     CausedFocusEvent.Cause cause)
+                                                     FocusEvent.Cause cause)
     {
         return KfmAccessor.instance.shouldNativelyFocusHeavyweight(
             heavyweight, descendant, temporary, focusedWindowChangeAllowed,
--- a/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/NullComponentPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -37,7 +37,7 @@
 import java.awt.GraphicsConfiguration;
 import java.awt.Image;
 import java.awt.Insets;
-import java.awt.MenuBar;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.Point;
 import java.awt.Event;
 import java.awt.event.PaintEvent;
@@ -178,7 +178,7 @@
 
     public boolean requestFocus
         (Component lightweightChild, boolean temporary,
-         boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause) {
+         boolean focusedWindowChangeAllowed, long time, Cause cause) {
         return false;
     }
 
--- a/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/RequestFocusController.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,11 @@
 package sun.awt;
 
 import java.awt.Component;
+import java.awt.event.FocusEvent.Cause;
 
 public interface RequestFocusController
 {
     public boolean acceptRequestFocus(Component from, Component to,
                                       boolean temporary, boolean focusedWindowChangeAllowed,
-                                      CausedFocusEvent.Cause cause);
+                                      Cause cause);
 }
--- a/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/awt/image/PNGImageDecoder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -87,7 +87,7 @@
         properties.put(key,value);
     }
     private void property(String key,float value) {
-        property(key,new Float(value));
+        property(key, Float.valueOf(value));
     }
     private final void pngassert(boolean b) throws IOException {
         if(!b) {
--- a/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/font/SunFontManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1843,7 +1843,7 @@
 
     private PhysicalFont registerFontFile(String file) {
         if (new File(file).isAbsolute() &&
-            !registeredFonts.contains(file)) {
+            !registeredFonts.containsKey(file)) {
             int fontFormat = FONTFORMAT_NONE;
             int fontRank = Font2D.UNKNOWN_RANK;
             if (ttFilter.accept(null, file)) {
--- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1388,6 +1388,8 @@
         Doc doc = new PageableDoc(getPageable());
         if (attributes == null) {
             attributes = new HashPrintRequestAttributeSet();
+            attributes.add(new Copies(getCopies()));
+            attributes.add(new JobName(getJobName(), null));
         }
         try {
             job.print(doc, attributes);
--- a/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/print/ServiceDialog.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1402,8 +1402,8 @@
             format.setParseIntegerOnly(false);
             format.setDecimalSeparatorAlwaysShown(true);
             NumberFormatter nf = new NumberFormatter(format);
-            nf.setMinimum(new Float(0.0f));
-            nf.setMaximum(new Float(999.0f));
+            nf.setMinimum(Float.valueOf(0.0f));
+            nf.setMaximum(Float.valueOf(999.0f));
             nf.setAllowsInvalid(true);
             nf.setCommitsOnValidEdit(true);
 
@@ -1422,13 +1422,13 @@
             topMargin.addActionListener(this);
             topMargin.getAccessibleContext().setAccessibleName(
                                               getMsg("label.topmargin"));
-            topMargin = new JFormattedTextField(nf);
+
             bottomMargin = new JFormattedTextField(nf);
             bottomMargin.addFocusListener(this);
             bottomMargin.addActionListener(this);
             bottomMargin.getAccessibleContext().setAccessibleName(
                                               getMsg("label.bottommargin"));
-            topMargin = new JFormattedTextField(nf);
+
             c.gridwidth = GridBagConstraints.RELATIVE;
             lblLeft = new JLabel(getMsg("label.leftmargin") + " " + unitsMsg,
                                  JLabel.LEADING);
@@ -1836,10 +1836,10 @@
             rmVal = mediaSize.getX(units) - pax - paw;
             bmVal = mediaSize.getY(units) - pay - pah;
 
-            lmObj = new Float(lmVal);
-            rmObj = new Float(rmVal);
-            tmObj = new Float(tmVal);
-            bmObj = new Float(bmVal);
+            lmObj = lmVal;
+            rmObj = rmVal;
+            tmObj = tmVal;
+            bmObj = bmVal;
 
             /* Now we know the values to use, we need to assign them
              * to the fields appropriate for the orientation.
--- a/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/share/classes/sun/swing/StringUIClientPropertyKey.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package sun.swing;
 
+import javax.swing.UIClientPropertyKey;
+
 /**
  * An implementation of {@code UIClientPropertyKey} that wraps a {@code String}.
  *
--- a/jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.swing;
-
-/**
- * This interface is used only for tagging keys for client properties
- * for {@code JComponent} set by UI which needs to be cleared on {@literal L&F}
- * change and serialization.
- *
- * All such keys are removed from client properties in {@code
- * JComponent.setUI()} method after uninstalling old UI and before
- * intalling the new one. They are also removed prior to serialization.
- *
- * @author Igor Kushnirskiy
- */
-public interface UIClientPropertyKey {
-}
--- a/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/UNIXToolkit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,9 +29,12 @@
 import java.awt.color.ColorSpace;
 import java.awt.image.*;
 import java.security.AccessController;
+import java.security.PrivilegedAction;
+
 import sun.security.action.GetIntegerAction;
 import com.sun.java.swing.plaf.gtk.GTKConstants.TextDirection;
 import sun.java2d.opengl.OGLRenderQueue;
+import sun.security.action.GetPropertyAction;
 
 public abstract class UNIXToolkit extends SunToolkit
 {
@@ -42,6 +45,40 @@
     private static final int[] BAND_OFFSETS_ALPHA = { 0, 1, 2, 3 };
     private static final int DEFAULT_DATATRANSFER_TIMEOUT = 10000;
 
+    // Allowed GTK versions
+    public enum GtkVersions {
+        ANY(0),
+        GTK2(Constants.GTK2_MAJOR_NUMBER),
+        GTK3(Constants.GTK3_MAJOR_NUMBER);
+
+        static class Constants {
+            static final int GTK2_MAJOR_NUMBER = 2;
+            static final int GTK3_MAJOR_NUMBER = 3;
+        }
+
+        final int number;
+
+        GtkVersions(int number) {
+            this.number = number;
+        }
+
+        public static GtkVersions getVersion(int number) {
+            switch (number) {
+                case Constants.GTK2_MAJOR_NUMBER:
+                    return GTK2;
+                case Constants.GTK3_MAJOR_NUMBER:
+                    return GTK3;
+                default:
+                    return ANY;
+            }
+        }
+
+        // major GTK version number
+        public int getNumber() {
+            return number;
+        }
+    };
+
     private Boolean nativeGTKAvailable;
     private Boolean nativeGTKLoaded;
     private BufferedImage tmpImage = null;
@@ -79,7 +116,7 @@
                 return nativeGTKAvailable;
 
             } else {
-                boolean success = check_gtk();
+                boolean success = check_gtk(getEnabledGtkVersion().getNumber());
                 nativeGTKAvailable = success;
                 return success;
             }
@@ -97,7 +134,8 @@
     public boolean loadGTK() {
         synchronized (GTK_LOCK) {
             if (nativeGTKLoaded == null) {
-                nativeGTKLoaded = load_gtk();
+                nativeGTKLoaded = load_gtk(getEnabledGtkVersion().getNumber(),
+                                                                isGtkVerbose());
             }
         }
         return nativeGTKLoaded;
@@ -241,14 +279,15 @@
         tmpImage = new BufferedImage(colorModel, raster, false, null);
     }
 
-    private static native boolean check_gtk();
-    private static native boolean load_gtk();
+    private static native boolean check_gtk(int version);
+    private static native boolean load_gtk(int version, boolean verbose);
     private static native boolean unload_gtk();
     private native boolean load_gtk_icon(String filename);
     private native boolean load_stock_icon(int widget_type, String stock_id,
             int iconSize, int textDirection, String detail);
 
     private native void nativeSync();
+    private static native int get_gtk_version();
 
     @Override
     public void sync() {
@@ -338,4 +377,26 @@
         }
         return false;
     }
+
+    public static GtkVersions getEnabledGtkVersion() {
+        String version = AccessController.doPrivileged(
+                new GetPropertyAction("jdk.gtk.version"));
+        if (version == null) {
+            return GtkVersions.ANY;
+        } else if (version.startsWith("2")) {
+            return GtkVersions.GTK2;
+        } else if("3".equals(version) ){
+            return GtkVersions.GTK3;
+        }
+        return GtkVersions.ANY;
+    }
+
+    public static GtkVersions getGtkVersion() {
+        return GtkVersions.getVersion(get_gtk_version());
+    }
+
+    public static boolean isGtkVerbose() {
+        return AccessController.doPrivileged((PrivilegedAction<Boolean>)()
+                -> Boolean.getBoolean("jdk.gtk.verbose"));
+    }
 }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XComponentPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -287,7 +287,7 @@
     @SuppressWarnings("deprecation")
     public final boolean requestFocus(Component lightweightChild, boolean temporary,
                                       boolean focusedWindowChangeAllowed, long time,
-                                      CausedFocusEvent.Cause cause)
+                                      FocusEvent.Cause cause)
     {
         if (XKeyboardFocusManagerPeer.
             processSynchronousLightweightTransfer(target, lightweightChild, temporary,
@@ -527,7 +527,7 @@
 //                       WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
 //                       parentWindow.dispatchEvent(wfg);
 //                   }
-                  XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
+                  XKeyboardFocusManagerPeer.requestFocusFor(target, FocusEvent.Cause.MOUSE_EVENT);
               }
               break;
         }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XDesktopPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
 package sun.awt.X11;
 
 
+import sun.awt.UNIXToolkit;
+
 import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -57,7 +59,8 @@
         XToolkit.awtLock();
         try {
             if (!initExecuted) {
-                nativeLibraryLoaded = init();
+                nativeLibraryLoaded = init(UNIXToolkit.getEnabledGtkVersion()
+                        .ordinal(), UNIXToolkit.isGtkVerbose());
             }
         } finally {
             initExecuted = true;
@@ -123,5 +126,5 @@
     }
 
     private native boolean gnome_url_show(byte[] url);
-    private static native boolean init();
+    private static native boolean init(int gtkVersion, boolean verbose);
 }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedCanvasPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -430,13 +430,10 @@
         if (isXEmbedActive()) {
             xembedLog.fine("Forwarding FOCUS_GAINED");
             int flavor = XEMBED_FOCUS_CURRENT;
-            if (e instanceof CausedFocusEvent) {
-                CausedFocusEvent ce = (CausedFocusEvent)e;
-                if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_FORWARD) {
-                    flavor = XEMBED_FOCUS_FIRST;
-                } else if (ce.getCause() == CausedFocusEvent.Cause.TRAVERSAL_BACKWARD) {
-                    flavor = XEMBED_FOCUS_LAST;
-                }
+            if (e.getCause() == FocusEvent.Cause.TRAVERSAL_FORWARD) {
+                flavor = XEMBED_FOCUS_FIRST;
+            } else if (e.getCause() == FocusEvent.Cause.TRAVERSAL_BACKWARD) {
+                flavor = XEMBED_FOCUS_LAST;
             }
             xembed.sendMessage(xembed.handle, XEMBED_FOCUS_IN, flavor, 0, 0);
         }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XEmbedChildProxyPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -195,7 +195,7 @@
                                 boolean temporary,
                                 boolean focusedWindowChangeAllowed,
                                 long time,
-                                CausedFocusEvent.Cause cause)
+                                FocusEvent.Cause cause)
     {
         int result = XKeyboardFocusManagerPeer
             .shouldNativelyFocusHeavyweight(proxy, lightweightChild,
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XKeyboardFocusManagerPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 import java.awt.Window;
 
 import sun.awt.AWTAccessor;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent;
 import sun.awt.KeyboardFocusManagerPeerImpl;
 import sun.util.logging.PlatformLogger;
 
@@ -101,7 +101,7 @@
                                        boolean temporary,
                                        boolean focusedWindowChangeAllowed,
                                        long time,
-                                       CausedFocusEvent.Cause cause)
+                                       FocusEvent.Cause cause)
     {
         return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
                                                          target,
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTaskbarPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -29,6 +29,8 @@
 import java.awt.Taskbar.Feature;
 import java.awt.peer.TaskbarPeer;
 import java.awt.event.ActionEvent;
+
+import sun.awt.UNIXToolkit;
 import java.security.AccessController;
 import sun.security.action.GetPropertyAction;
 
@@ -45,7 +47,9 @@
             if (!initExecuted) {
                 String dname = AccessController.doPrivileged(
                                 new GetPropertyAction("java.desktop.appName", ""));
-                nativeLibraryLoaded = init(dname);
+                nativeLibraryLoaded = init(dname,
+                        UNIXToolkit.getEnabledGtkVersion().ordinal(),
+                        UNIXToolkit.isGtkVerbose());
                 if (nativeLibraryLoaded) {
                     Thread t = new Thread(null, () -> { runloop(); },
                                           "TaskBar", 0, false);
@@ -147,7 +151,8 @@
         }
     }
 
-    private static native boolean init(String name);
+    private static native boolean init(String name, int version,
+                                                               boolean verbose);
 
     private static native void runloop();
 
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextAreaPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -59,7 +59,6 @@
 
 import javax.swing.plaf.BorderUIResource;
 import java.awt.im.InputMethodRequests;
-import sun.awt.CausedFocusEvent;
 import sun.awt.AWTAccessor;
 import sun.awt.SunToolkit;
 
@@ -945,14 +944,16 @@
 
         void forwardFocusGained( FocusEvent e) {
             isFocused = true;
-            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+                    e.getOppositeComponent(), e.getCause());
             super.processFocusEvent(fe);
         }
 
 
         void forwardFocusLost( FocusEvent e) {
             isFocused = false;
-            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+                    e.getOppositeComponent(), e.getCause());
             super.processFocusEvent(fe);
         }
 
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XTextFieldPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -54,7 +54,6 @@
 
 import sun.util.logging.PlatformLogger;
 
-import sun.awt.CausedFocusEvent;
 import sun.awt.AWTAccessor;
 
 final class XTextFieldPeer extends XComponentPeer implements TextFieldPeer {
@@ -618,13 +617,15 @@
 
         void forwardFocusGained( FocusEvent e) {
             isFocused = true;
-            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+                    e.getOppositeComponent(), e.getCause());
             super.processFocusEvent(fe);
         }
 
         void forwardFocusLost( FocusEvent e) {
             isFocused = false;
-            FocusEvent fe = CausedFocusEvent.retarget(e, this);
+            FocusEvent fe = new FocusEvent(this, e.getID(), e.isTemporary(),
+                    e.getOppositeComponent(), e.getCause());
             super.processFocusEvent(fe);
 
         }
--- a/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/awt/X11/XToolkit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -52,7 +52,6 @@
 import sun.awt.datatransfer.DataTransferer;
 import sun.font.FontConfigManager;
 import sun.java2d.SunGraphicsEnvironment;
-import sun.misc.*;
 import sun.awt.util.PerformanceLogger;
 import sun.awt.util.ThreadGroupUtils;
 import sun.print.PrintJob2D;
@@ -1144,7 +1143,8 @@
     public FileDialogPeer createFileDialog(FileDialog target) {
         FileDialogPeer peer = null;
         // The current GtkFileChooser is available from GTK+ 2.4
-        if (!getSunAwtDisableGtkFileDialogs() && checkGtkVersion(2, 4, 0)) {
+        if (!getSunAwtDisableGtkFileDialogs() &&
+                      (checkGtkVersion(2, 4, 0) || checkGtkVersion(3, 0, 0))) {
             peer = new GtkFileDialogPeer(target);
         } else {
             peer = new XFileDialogPeer(target);
--- a/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/classes/sun/print/PrintServiceLookupProvider.java	Wed Jul 05 21:39:33 2017 +0200
@@ -117,7 +117,7 @@
 
         if (refreshTimeStr != null) {
             try {
-                minRefreshTime = (new Integer(refreshTimeStr)).intValue();
+                minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
             } catch (NumberFormatException e) {
             }
             if (minRefreshTime < DEFAULT_MINREFRESH) {
--- a/jdk/src/java.desktop/unix/native/common/awt/awt.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/common/awt/awt.h	Wed Jul 05 21:39:33 2017 +0200
@@ -35,7 +35,9 @@
 #include "debug_util.h"
 
 #if !defined(HEADLESS) && !defined(MACOSX)
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+typedef char Boolean;
 #endif /* !HEADLESS && !MACOSX */
 
 
--- a/jdk/src/java.desktop/unix/native/common/awt/awt_p.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/common/awt/awt_p.h	Wed Jul 05 21:39:33 2017 +0200
@@ -41,13 +41,6 @@
 #include <string.h>
 #include <unistd.h>
 #ifndef HEADLESS
-#include <X11/Intrinsic.h>
-#include <X11/IntrinsicP.h>
-#include <X11/Shell.h>
-#include <X11/StringDefs.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#include <X11/keysymdef.h>
 #include <X11/extensions/Xrender.h>
 #endif /* !HEADLESS */
 #include "awt.h"
--- a/jdk/src/java.desktop/unix/native/common/awt/extutil.h	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,251 +0,0 @@
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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:
- *
- * $Xorg: extutil.h,v 1.3 2000/08/18 04:05:45 coskrey Exp $
- *
-Copyright 1989, 1998  The Open Group
-
-All Rights Reserved.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
- *
- * Author:  Jim Fulton, MIT The Open Group
- *
- *                     Xlib Extension-Writing Utilities
- *
- * This package contains utilities for writing the client API for various
- * protocol extensions.  THESE INTERFACES ARE NOT PART OF THE X STANDARD AND
- * ARE SUBJECT TO CHANGE!
- */
-/* $XFree86: xc/include/extensions/extutil.h,v 1.5 2001/01/17 17:53:20 dawes Exp $ */
-
-#if defined(__linux__) || defined(MACOSX)
-
-#ifndef _EXTUTIL_H_
-#define _EXTUTIL_H_
-
-/*
- * We need to keep a list of open displays since the Xlib display list isn't
- * public.  We also have to per-display info in a separate block since it isn't
- * stored directly in the Display structure.
- */
-typedef struct _XExtDisplayInfo {
-    struct _XExtDisplayInfo *next;      /* keep a linked list */
-    Display *display;                   /* which display this is */
-    XExtCodes *codes;                   /* the extension protocol codes */
-    XPointer data;                      /* extra data for extension to use */
-} XExtDisplayInfo;
-
-typedef struct _XExtensionInfo {
-    XExtDisplayInfo *head;              /* start of list */
-    XExtDisplayInfo *cur;               /* most recently used */
-    int ndisplays;                      /* number of displays */
-} XExtensionInfo;
-
-typedef struct _XExtensionHooks {
-    int (*create_gc)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              GC                        /* gc */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*copy_gc)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              GC                        /* gc */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*flush_gc)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              GC                        /* gc */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*free_gc)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              GC                        /* gc */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*create_font)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              XFontStruct*              /* fs */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*free_font)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              XFontStruct*              /* fs */,
-              XExtCodes*                /* codes */
-#endif
-);
-    int (*close_display)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              XExtCodes*                /* codes */
-#endif
-);
-    Bool (*wire_to_event)(
-#if NeedNestedPrototypes
-               Display*                 /* display */,
-               XEvent*                  /* re */,
-               xEvent*                  /* event */
-#endif
-);
-    Status (*event_to_wire)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              XEvent*                   /* re */,
-              xEvent*                   /* event */
-#endif
-);
-    int (*error)(
-#if NeedNestedPrototypes
-              Display*                  /* display */,
-              xError*                   /* err */,
-              XExtCodes*                /* codes */,
-              int*                      /* ret_code */
-#endif
-);
-    char *(*error_string)(
-#if NeedNestedPrototypes
-                Display*                /* display */,
-                int                     /* code */,
-                XExtCodes*              /* codes */,
-                char*                   /* buffer */,
-                int                     /* nbytes */
-#endif
-);
-} XExtensionHooks;
-
-extern XExtensionInfo *XextCreateExtension(
-#if NeedFunctionPrototypes
-    void
-#endif
-);
-extern void XextDestroyExtension(
-#if NeedFunctionPrototypes
-    XExtensionInfo*     /* info */
-#endif
-);
-extern XExtDisplayInfo *XextAddDisplay(
-#if NeedFunctionPrototypes
-    XExtensionInfo*     /* extinfo */,
-    Display*            /* dpy */,
-    char*               /* ext_name */,
-    XExtensionHooks*    /* hooks */,
-    int                 /* nevents */,
-    XPointer            /* data */
-#endif
-);
-extern int XextRemoveDisplay(
-#if NeedFunctionPrototypes
-    XExtensionInfo*     /* extinfo */,
-    Display*            /* dpy */
-#endif
-);
-extern XExtDisplayInfo *XextFindDisplay(
-#if NeedFunctionPrototypes
-    XExtensionInfo*     /* extinfo */,
-    Display*            /* dpy */
-#endif
-);
-
-#define XextHasExtension(i) ((i) && ((i)->codes))
-#define XextCheckExtension(dpy,i,name,val) \
-  if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return val; }
-#define XextSimpleCheckExtension(dpy,i,name) \
-  if (!XextHasExtension(i)) { XMissingExtension (dpy, name); return; }
-
-
-/*
- * helper macros to generate code that is common to all extensions; caller
- * should prefix it with static if extension source is in one file; this
- * could be a utility function, but have to stack 6 unused arguments for
- * something that is called many, many times would be bad.
- */
-#define XEXT_GENERATE_FIND_DISPLAY(proc,extinfo,extname,hooks,nev,data) \
-XExtDisplayInfo *proc (Display *dpy) \
-{ \
-    XExtDisplayInfo *dpyinfo; \
-    if (!extinfo) { if (!(extinfo = XextCreateExtension())) return NULL; } \
-    if (!(dpyinfo = XextFindDisplay (extinfo, dpy))) \
-      dpyinfo = XextAddDisplay (extinfo,dpy,extname,hooks,nev,data); \
-    return dpyinfo; \
-}
-
-#define XEXT_FIND_DISPLAY_PROTO(proc) \
-        XExtDisplayInfo *proc(Display *dpy)
-
-#define XEXT_GENERATE_CLOSE_DISPLAY(proc,extinfo) \
-int proc (Display *dpy, XExtCodes *codes) \
-{ \
-    return XextRemoveDisplay (extinfo, dpy); \
-}
-
-#define XEXT_CLOSE_DISPLAY_PROTO(proc) \
-        int proc(Display *dpy, XExtCodes *codes)
-
-#define XEXT_GENERATE_ERROR_STRING(proc,extname,nerr,errl) \
-char *proc (Display *dpy, int code, XExtCodes *codes, char *buf, int n) \
-{  \
-    code -= codes->first_error;  \
-    if (code >= 0 && code < nerr) { \
-        char tmp[256]; \
-        sprintf (tmp, "%s.%d", extname, code); \
-        XGetErrorDatabaseText (dpy, "XProtoError", tmp, errl[code], buf, n); \
-        return buf; \
-    } \
-    return (char *)0; \
-}
-
-#define XEXT_ERROR_STRING_PROTO(proc) \
-        char *proc(Display *dpy, int code, XExtCodes *codes, char *buf, int n)
-#endif
-
-#endif /* __linux__ || MACOSX */
--- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c	Wed Jul 05 21:39:33 2017 +0200
@@ -270,7 +270,6 @@
     xsdo->sdOps.Dispose = X11SD_Dispose;
     xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg;
     xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg;
-    xsdo->widget = NULL;
     if (peer != NULL) {
         xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j;
         if (hasException) {
@@ -1087,7 +1086,7 @@
 X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds,
                  X11SDOps *xsdo)
 {
-    Position x1=0, y1=0, x2=0, y2=0;
+    short x1=0, y1=0, x2=0, y2=0;
     int tmpx, tmpy;
     Window tmpchild;
 
--- a/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.h	Wed Jul 05 21:39:33 2017 +0200
@@ -101,7 +101,6 @@
     jboolean            isPixmap;
     jobject             peer;
     Drawable            drawable;
-    Widget              widget;
     GC                  javaGC;        /* used for Java-level GC validation */
     GC                  cachedGC;      /* cached for use in X11SD_Unlock() */
     jint                depth;
--- a/jdk/src/java.desktop/unix/native/include/jawt_md.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/include/jawt_md.h	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,6 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <X11/Intrinsic.h>
 #include "jawt.h"
 
 #ifdef __cplusplus
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,344 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#ifndef HEADLESS
-
-#include <X11/IntrinsicP.h>
-#include "VDrawingAreaP.h"
-
-#endif /* !HEADLESS */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#ifdef __linux__
-/* XXX: Shouldn't be necessary. */
-#include "awt_p.h"
-#endif /* __linux__ */
-
-
-/******************************************************************
- *
- * Provides Canvas widget which allows the X11 visual to be
- * changed (the Motif DrawingArea restricts the visual to that
- * of the parent widget).
- *
- ******************************************************************/
-
-
-/******************************************************************
- *
- * VDrawingArea Widget Resources
- *
- ******************************************************************/
-
-#ifndef HEADLESS
-#define Offset(x)       (XtOffsetOf(VDrawingAreaRec, x))
-static XtResource resources[]=
-{
-        { XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*),
-          Offset(vdrawing_area.visual), XtRImmediate, CopyFromParent}
-};
-
-
-static void Realize();
-static Boolean SetValues();
-static void Destroy ();
-
-static XmBaseClassExtRec baseClassExtRec = {
-    NULL,
-    NULLQUARK,
-    XmBaseClassExtVersion,
-    sizeof(XmBaseClassExtRec),
-    NULL,                               /* InitializePrehook    */
-    NULL,                               /* SetValuesPrehook     */
-    NULL,                               /* InitializePosthook   */
-    NULL,                               /* SetValuesPosthook    */
-    NULL,                               /* secondaryObjectClass */
-    NULL,                               /* secondaryCreate      */
-    NULL,                               /* getSecRes data       */
-    { 0 },                              /* fastSubclass flags   */
-    NULL,                               /* getValuesPrehook     */
-    NULL,                               /* getValuesPosthook    */
-    NULL,                               /* classPartInitPrehook */
-    NULL,                               /* classPartInitPosthook*/
-    NULL,                               /* ext_resources        */
-    NULL,                               /* compiled_ext_resources*/
-    0,                                  /* num_ext_resources    */
-    FALSE,                              /* use_sub_resources    */
-    NULL,                               /* widgetNavigable      */
-    NULL,                               /* focusChange          */
-    NULL                                /* wrapper_data         */
-};
-
-VDrawingAreaClassRec vDrawingAreaClassRec = {
-{
-    /* Core class part */
-
-    /* superclass         */    (WidgetClass)&xmDrawingAreaClassRec,
-    /* class_name         */    "VDrawingArea",
-    /* widget_size        */    sizeof(VDrawingAreaRec),
-    /* class_initialize   */    NULL,
-    /* class_part_initialize*/  NULL,
-    /* class_inited       */    FALSE,
-    /* initialize         */    NULL,
-    /* initialize_hook    */    NULL,
-    /* realize            */    Realize,
-    /* actions            */    NULL,
-    /* num_actions        */    0,
-    /* resources          */    resources,
-    /* num_resources      */    XtNumber(resources),
-    /* xrm_class          */    NULLQUARK,
-    /* compress_motion    */    FALSE,
-    /* compress_exposure  */    FALSE,
-    /* compress_enterleave*/    FALSE,
-    /* visible_interest   */    FALSE,
-    /* destroy            */    Destroy,
-    /* resize             */    XtInheritResize,
-    /* expose             */    XtInheritExpose,
-    /* set_values         */    SetValues,
-    /* set_values_hook    */    NULL,
-    /* set_values_almost  */    XtInheritSetValuesAlmost,
-    /* get_values_hook    */    NULL,
-    /* accept_focus       */    NULL,
-    /* version            */    XtVersion,
-    /* callback_offsets   */    NULL,
-    /* tm_table           */    NULL,
-    /* query_geometry       */  NULL,
-    /* display_accelerator  */  NULL,
-    /* extension            */  NULL
-  },
-
-   {            /* composite_class fields */
-      XtInheritGeometryManager,                 /* geometry_manager   */
-      XtInheritChangeManaged,                   /* change_managed     */
-      XtInheritInsertChild,                     /* insert_child       */
-      XtInheritDeleteChild,                     /* delete_child       */
-      NULL,                                     /* extension          */
-   },
-
-   {            /* constraint_class fields */
-      NULL,                                     /* resource list        */
-      0,                                        /* num resources        */
-      0,                                        /* constraint size      */
-      NULL,                                     /* init proc            */
-      NULL,                                     /* destroy proc         */
-      NULL,                                     /* set values proc      */
-      NULL,                                     /* extension            */
-   },
-
-   {            /* manager_class fields */
-      XtInheritTranslations,                    /* translations           */
-      NULL,                                     /* syn_resources          */
-      0,                                        /* num_get_resources      */
-      NULL,                                     /* syn_cont_resources     */
-      0,                                        /* num_get_cont_resources */
-      XmInheritParentProcess,                   /* parent_process         */
-      NULL,                                     /* extension           */
-   },
-
-   {            /* drawingArea class */
-           /* extension */      NULL
-   },
-
-   /* VDrawingArea class part */
-   {
-        /* extension    */      NULL
-   }
-};
-
-WidgetClass vDrawingAreaClass = (WidgetClass)&vDrawingAreaClassRec;
-
-static Boolean
-SetValues(cw, rw, nw, args, num_args)
-    Widget cw;
-    Widget rw;
-    Widget nw;
-    ArgList args;
-    Cardinal *num_args;
-{
-    VDrawingAreaWidget current = (VDrawingAreaWidget)cw;
-    VDrawingAreaWidget new_w = (VDrawingAreaWidget)nw;
-
-    if (new_w->vdrawing_area.visual != current->vdrawing_area.visual) {
-        new_w->vdrawing_area.visual = current->vdrawing_area.visual;
-#ifdef DEBUG
-        fprintf(stdout, "VDrawingArea.SetValues: can't change visual from: visualID=%ld to visualID=%ld\n",
-                     current->vdrawing_area.visual->visualid,
-                     new_w->vdrawing_area.visual->visualid);
-#endif
-
-    }
-
-    return (False);
-}
-
-int
-FindWindowInList (Window parentWindow, Window *colormap_windows, int count)
-{
-    int i;
-
-    for (i = 0; i < count; i++)
-        if (colormap_windows [i] == parentWindow)
-           return i;
-    return -1;
-}
-
-static void
-Realize(w, value_mask, attributes)
-    Widget               w;
-    XtValueMask          *value_mask;
-    XSetWindowAttributes *attributes;
-{
-    Widget parent;
-    Status status;
-    Window *colormap_windows;
-    Window *new_colormap_windows;
-    int count;
-    int i;
-    VDrawingAreaWidget vd = (VDrawingAreaWidget)w;
-
-#ifdef DEBUG
-    fprintf(stdout, "VDrawingArea.Realize: visualID=%ld, depth=%d\n",
-                        vd->vdrawing_area.visual->visualid, w->core.depth);
-#endif
-
-    /* 4328588:
-     * Since we have our own Realize() function, we don't execute the one for
-     * our super-super class, XmManager, and miss the code which checks that
-     * height and width != 0.  I've added that here.  -bchristi
-     */
-    if (!XtWidth(w)) XtWidth(w) = 1 ;
-    if (!XtHeight(w)) XtHeight(w) = 1 ;
-
-    w->core.window = XCreateWindow (XtDisplay (w), XtWindow (w->core.parent),
-                        w->core.x, w->core.y, w->core.width, w->core.height,
-                        0, w->core.depth, InputOutput,
-                        vd->vdrawing_area.visual,
-                        *value_mask, attributes );
-
-    /* Need to add this window to the list of Colormap windows */
-    parent = XtParent (w);
-    while ((parent != NULL) && (!(XtIsShell (parent))))
-        parent = XtParent (parent);
-    if (parent == NULL) {
-        fprintf (stderr, "NO TopLevel widget?!\n");
-        return;
-    }
-
-    status = XGetWMColormapWindows (XtDisplay (w), XtWindow (parent),
-                                    &colormap_windows, &count);
-
-    /* If status is zero, add this window and shell to the list
-       of colormap Windows */
-    if (status == 0) {
-        new_colormap_windows = (Window *) calloc (2, sizeof (Window));
-        new_colormap_windows [0] = XtWindow (w);
-        new_colormap_windows [1] = XtWindow (parent);
-        XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
-                               new_colormap_windows, 2);
-        free (new_colormap_windows);
-    } else {
-        /* Check if parent is already in the list */
-        int parent_entry = -1;
-
-        if (count > 0)
-            parent_entry = FindWindowInList (XtWindow (parent),
-                                        colormap_windows, count);
-        if (parent_entry == -1) {  /*  Parent not in list  */
-            new_colormap_windows = (Window *) calloc (count + 2,
-                                                sizeof (Window));
-            new_colormap_windows [0] = XtWindow (w);
-            new_colormap_windows [1] = XtWindow (parent);
-            for (i = 0; i < count; i++)
-                new_colormap_windows [i + 2] = colormap_windows [i];
-            XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
-                                   new_colormap_windows, count + 2);
-
-        } else {        /* parent already in list, just add new window */
-            new_colormap_windows = (Window *) calloc (count + 1,
-                                                sizeof (Window));
-            new_colormap_windows [0] = XtWindow (w);
-            for (i = 0; i < count; i++)
-                new_colormap_windows [i + 1] = colormap_windows [i];
-            XSetWMColormapWindows (XtDisplay (w), XtWindow (parent),
-                                   new_colormap_windows, count + 1);
-        }
-        free (new_colormap_windows);
-        XFree (colormap_windows);
-    }
-
-
-}
-
-static void
-Destroy(Widget widget)
-{
-    Status status;
-    Widget parent;
-    Window *colormap_windows;
-    Window *new_colormap_windows;
-    int count;
-    int listEntry;
-    int i;
-    int j;
-
-    /* Need to get this window's parent shell first */
-    parent = XtParent (widget);
-    while ((parent != NULL) && (!(XtIsShell (parent))))
-        parent = XtParent (parent);
-    if (parent == NULL) {
-        fprintf (stderr, "NO TopLevel widget?!\n");
-        return;
-    }
-
-    status = XGetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
-                                    &colormap_windows, &count);
-
-    /* If status is zero, then there were no colormap windows for
-       the parent ?? */
-
-    if (status == 0)
-        return;
-
-    /* Remove this window from the list of colormap windows */
-    listEntry = FindWindowInList (XtWindow (widget), colormap_windows,
-                                  count);
-
-    new_colormap_windows = (Window *) calloc (count - 1, sizeof (Window));
-    j = 0;
-    for (i = 0; i < count; i++) {
-        if (i == listEntry)
-           continue;
-        new_colormap_windows [j] = colormap_windows [i];
-        j++;
-    }
-    XSetWMColormapWindows (XtDisplay (widget), XtWindow (parent),
-                           new_colormap_windows, count - 1);
-    free (new_colormap_windows);
-    XFree (colormap_windows);
-
-}
-#endif /* !HEADLESS */
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 1997, 2001, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 _VDrawingArea_h_
-#define _VDrawingArea_h_
-
-#ifndef HEADLESS
-extern WidgetClass vDrawingAreaClass;
-
-typedef struct _VDrawingAreaClassRec    *VDrawingAreaWidgetClass;
-typedef struct _VDrawingAreaRec         *VDrawingAreaWidget;
-#endif /* !HEADLESS */
-
-#endif /* !_VDrawingArea_h_ */
--- a/jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please 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 _VDrawingAreaP_h_
-#define _VDrawingAreaP_h_
-
-#include <Xm/DrawingAP.h>
-#include "VDrawingArea.h"
-
-
-/***************************************************************
- * VDrawingArea Widget Data Structures
- *
- *
- **************************************************************/
-
-/* Define part class structure */
-typedef struct _VDrawingAreaClass {
-        XtPointer                       extension;
-} VDrawingAreaClassPart;
-
-/* Define the full class record */
-typedef struct _VDrawingAreaClassRec {
-        CoreClassPart           core_class;
-        CompositeClassPart      composite_class;
-        ConstraintClassPart     constraint_class;
-        XmManagerClassPart      manager_class;
-        XmDrawingAreaClassPart  drawing_area_class;
-        VDrawingAreaClassPart   vdrawingarea_class;
-} VDrawingAreaClassRec;
-
-/* External definition for class record */
-extern VDrawingAreaClassRec vDrawingAreaClassRec;
-
-typedef struct {
-        Visual *visual;
-} VDrawingAreaPart;
-
-/****************************************************************
- *
- * Full instance record declaration
- *
- ****************************************************************/
-
-typedef struct _VDrawingAreaRec
-{
-        CorePart                core;
-        CompositePart           composite;
-        ConstraintPart          constraint;
-        XmManagerPart           manager;
-        XmDrawingAreaPart       drawing_area;
-        VDrawingAreaPart        vdrawing_area;
-} VDrawingAreaRec;
-
-
-
-#endif /* !_VDrawingAreaP_h_ */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c	Wed Jul 05 21:39:33 2017 +0200
@@ -30,6 +30,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <X11/Xlib.h>
+#include <X11/keysym.h>
 #include <sys/time.h>
 
 #include "awt.h"
@@ -40,7 +41,6 @@
 
 #define THROW_OUT_OF_MEMORY_ERROR() \
         JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL)
-#define SETARG(name, value)     XtSetArg(args[argc], name, value); argc++
 
 struct X11InputMethodIDs {
   jfieldID pData;
@@ -590,7 +590,7 @@
     char **mclr;
     int  mccr = 0;
     char *dsr;
-    Pixel bg, fg, light, dim;
+    unsigned long bg, fg, light, dim;
     int x, y, off_x, off_y, xx, yy;
     unsigned int w, h, bw, depth;
     XGCValues values;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_Robot.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,6 @@
 #include "awt_GraphicsEnv.h"
 #define XK_MISCELLANY
 #include <X11/keysymdef.h>
-#include <X11/Intrinsic.h>
 #include <X11/Xutil.h>
 #include <X11/Xmd.h>
 #include <X11/extensions/xtestext1.h>
@@ -45,7 +44,7 @@
 #include "wsutils.h"
 #include "list.h"
 #include "multiVis.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 
 #if defined(__linux__) || defined(MACOSX)
 #include <sys/socket.h>
@@ -264,70 +263,10 @@
     int index;
 
     if (isGtkSupported) {
-        GdkPixbuf *pixbuf;
-        (*fp_gdk_threads_enter)();
-        GdkWindow *root = (*fp_gdk_get_default_root_window)();
-
-        pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL,
-                                                    x, y, 0, 0, width, height);
-        if (pixbuf && scale != 1) {
-            GdkPixbuf *scaledPixbuf;
-            x /= scale;
-            y /= scale;
-            width /= scale;
-            height /= scale;
-            dx /= scale;
-            dy /= scale;
-            scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
-                                                         GDK_INTERP_BILINEAR);
-            (*fp_g_object_unref)(pixbuf);
-            pixbuf = scaledPixbuf;
-        }
-
-        if (pixbuf) {
-            int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
-            int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
-
-            if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
-                    && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
-                    && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
-                    && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
-                    && nchan >= 3
-                    ) {
-                guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
-
-                ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
-                if (!ary) {
-                    (*fp_g_object_unref)(pixbuf);
-                    (*fp_gdk_threads_leave)();
-                    AWT_UNLOCK();
-                    return;
-                }
-
-                for (_y = 0; _y < height; _y++) {
-                    for (_x = 0; _x < width; _x++) {
-                        p = pix + _y * stride + _x * nchan;
-
-                        index = (_y + dy) * jwidth + (_x + dx);
-                        ary[index] = 0xff000000
-                                        | (p[0] << 16)
-                                        | (p[1] << 8)
-                                        | (p[2]);
-
-                    }
-                }
-                (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
-                if ((*env)->ExceptionCheck(env)) {
-                    (*fp_g_object_unref)(pixbuf);
-                    (*fp_gdk_threads_leave)();
-                    AWT_UNLOCK();
-                    return;
-                }
-                gtk_failed = FALSE;
-            }
-            (*fp_g_object_unref)(pixbuf);
-        }
-        (*fp_gdk_threads_leave)();
+        gtk->gdk_threads_enter();
+        gtk_failed = gtk->get_drawable_data(env, pixelArray, x, y, width,
+                                            height, jwidth, dx, dy, scale);
+        gtk->gdk_threads_leave();
     }
 
     if (gtk_failed) {
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_UNIXToolkit.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
 
 #ifndef HEADLESS
 #include "awt.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 #endif /* !HEADLESS */
 
 
@@ -45,13 +45,12 @@
 /*
  * Class:     sun_awt_UNIXToolkit
  * Method:    check_gtk
- * Signature: ()Z
+ * Signature: (I)Z
  */
 JNIEXPORT jboolean JNICALL
-Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass)
-{
+Java_sun_awt_UNIXToolkit_check_1gtk(JNIEnv *env, jclass klass, jint version) {
 #ifndef HEADLESS
-    return (jboolean)gtk2_check_version();
+    return (jboolean)gtk_check_version(version);
 #else
     return JNI_FALSE;
 #endif /* !HEADLESS */
@@ -61,13 +60,13 @@
 /*
  * Class:     sun_awt_UNIXToolkit
  * Method:    load_gtk
- * Signature: ()Z
+ * Signature: (I)Z
  */
 JNIEXPORT jboolean JNICALL
-Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass)
-{
+Java_sun_awt_UNIXToolkit_load_1gtk(JNIEnv *env, jclass klass, jint version,
+                                                             jboolean verbose) {
 #ifndef HEADLESS
-    return (jboolean)gtk2_load(env);
+    return (jboolean)gtk_load(env, version, verbose);
 #else
     return JNI_FALSE;
 #endif /* !HEADLESS */
@@ -83,16 +82,14 @@
 Java_sun_awt_UNIXToolkit_unload_1gtk(JNIEnv *env, jclass klass)
 {
 #ifndef HEADLESS
-    return (jboolean)gtk2_unload();
+    return (jboolean)gtk->unload();
 #else
     return JNI_FALSE;
 #endif /* !HEADLESS */
 }
 
-jboolean _icon_upcall(JNIEnv *env, jobject this, GdkPixbuf *pixbuf)
+jboolean init_method(JNIEnv *env, jobject this)
 {
-    jboolean result = JNI_FALSE;
-
     if (this_class == NULL) {
         this_class = (*env)->NewGlobalRef(env,
                                           (*env)->GetObjectClass(env, this));
@@ -100,33 +97,7 @@
                                  "loadIconCallback", "([BIIIIIZ)V");
         CHECK_NULL_RETURN(icon_upcall_method, JNI_FALSE);
     }
-
-    if (pixbuf != NULL)
-    {
-        guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
-        int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
-        int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
-        int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
-        int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
-        int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
-        gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
-
-        /* Copy the data array into a Java structure so we can pass it back. */
-        jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
-        JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
-
-        (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
-                                   (jbyte *)pixbuf_data);
-
-        /* Release the pixbuf. */
-        (*fp_g_object_unref)(pixbuf);
-
-        /* Call the callback method to create the image on the Java side. */
-        (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
-                width, height, row_stride, bps, channels, alpha);
-        result = JNI_TRUE;
-    }
-    return result;
+    return JNI_TRUE;
 }
 
 /*
@@ -144,7 +115,6 @@
     int len;
     char *filename_str = NULL;
     GError **error = NULL;
-    GdkPixbuf *pixbuf;
 
     if (filename == NULL)
     {
@@ -158,13 +128,17 @@
         JNU_ThrowOutOfMemoryError(env, "OutOfMemoryError");
         return JNI_FALSE;
     }
+    if (!init_method(env, this) ) {
+        return JNI_FALSE;
+    }
     (*env)->GetStringUTFRegion(env, filename, 0, len, filename_str);
-    pixbuf = (*fp_gdk_pixbuf_new_from_file)(filename_str, error);
+    jboolean result = gtk->get_file_icon_data(env, filename_str, error,
+                                            icon_upcall_method, this);
 
     /* Release the strings we've allocated. */
     free(filename_str);
 
-    return _icon_upcall(env, this, pixbuf);
+    return result;
 #else /* HEADLESS */
     return JNI_FALSE;
 #endif /* !HEADLESS */
@@ -186,7 +160,6 @@
     int len;
     char *stock_id_str = NULL;
     char *detail_str = NULL;
-    GdkPixbuf *pixbuf;
 
     if (stock_id == NULL)
     {
@@ -215,8 +188,12 @@
         (*env)->GetStringUTFRegion(env, detail, 0, len, detail_str);
     }
 
-    pixbuf = gtk2_get_stock_icon(widget_type, stock_id_str, icon_size,
-                                 text_direction, detail_str);
+    if (!init_method(env, this) ) {
+        return JNI_FALSE;
+    }
+    jboolean result = gtk->get_icon_data(env, widget_type, stock_id_str,
+                  icon_size, text_direction, detail_str,
+                  icon_upcall_method, this);
 
     /* Release the strings we've allocated. */
     free(stock_id_str);
@@ -224,8 +201,7 @@
     {
         free(detail_str);
     }
-
-    return _icon_upcall(env, this, pixbuf);
+    return result;
 #else /* HEADLESS */
     return JNI_FALSE;
 #endif /* !HEADLESS */
@@ -279,11 +255,25 @@
 {
     char *ret;
 
-    ret = fp_gtk_check_version(major, minor, micro);
+    ret = gtk->gtk_check_version(major, minor, micro);
     if (ret == NULL) {
         return TRUE;
     }
 
-    free(ret);
     return FALSE;
 }
+
+/*
+ * Class:     sun_awt_UNIXToolkit
+ * Method:    get_gtk_version
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL
+Java_sun_awt_UNIXToolkit_get_1gtk_1version(JNIEnv *env, jclass klass)
+{
+#ifndef HEADLESS
+    return gtk ? gtk->version : GTK_ANY;
+#else
+    return GTK_ANY;
+#endif /* !HEADLESS */
+}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/awt_util.c	Wed Jul 05 21:39:33 2017 +0200
@@ -29,7 +29,6 @@
 
 #include "awt_p.h"
 #include "color.h"
-#include <X11/IntrinsicP.h>
 #include <X11/Xatom.h>
 #include <X11/Xmd.h>
 #include <X11/Xutil.h>
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.c	Wed Jul 05 21:39:33 2017 +0200
@@ -35,52 +35,18 @@
 #include <jni_util.h>
 #include "awt.h"
 
-#define GTK2_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0")
-#define GTK2_LIB JNI_LIB_NAME("gtk-x11-2.0")
 #define GTHREAD_LIB_VERSIONED VERSIONED_JNI_LIB_NAME("gthread-2.0", "0")
 #define GTHREAD_LIB JNI_LIB_NAME("gthread-2.0")
 
-#define G_TYPE_INVALID                  G_TYPE_MAKE_FUNDAMENTAL (0)
-#define G_TYPE_NONE                     G_TYPE_MAKE_FUNDAMENTAL (1)
-#define G_TYPE_INTERFACE                G_TYPE_MAKE_FUNDAMENTAL (2)
-#define G_TYPE_CHAR                     G_TYPE_MAKE_FUNDAMENTAL (3)
-#define G_TYPE_UCHAR                    G_TYPE_MAKE_FUNDAMENTAL (4)
-#define G_TYPE_BOOLEAN                  G_TYPE_MAKE_FUNDAMENTAL (5)
-#define G_TYPE_INT                      G_TYPE_MAKE_FUNDAMENTAL (6)
-#define G_TYPE_UINT                     G_TYPE_MAKE_FUNDAMENTAL (7)
-#define G_TYPE_LONG                     G_TYPE_MAKE_FUNDAMENTAL (8)
-#define G_TYPE_ULONG                    G_TYPE_MAKE_FUNDAMENTAL (9)
-#define G_TYPE_INT64                    G_TYPE_MAKE_FUNDAMENTAL (10)
-#define G_TYPE_UINT64                   G_TYPE_MAKE_FUNDAMENTAL (11)
-#define G_TYPE_ENUM                     G_TYPE_MAKE_FUNDAMENTAL (12)
-#define G_TYPE_FLAGS                    G_TYPE_MAKE_FUNDAMENTAL (13)
-#define G_TYPE_FLOAT                    G_TYPE_MAKE_FUNDAMENTAL (14)
-#define G_TYPE_DOUBLE                   G_TYPE_MAKE_FUNDAMENTAL (15)
-#define G_TYPE_STRING                   G_TYPE_MAKE_FUNDAMENTAL (16)
-#define G_TYPE_POINTER                  G_TYPE_MAKE_FUNDAMENTAL (17)
-#define G_TYPE_BOXED                    G_TYPE_MAKE_FUNDAMENTAL (18)
-#define G_TYPE_PARAM                    G_TYPE_MAKE_FUNDAMENTAL (19)
-#define G_TYPE_OBJECT                   G_TYPE_MAKE_FUNDAMENTAL (20)
-
 #define GTK_TYPE_BORDER                 ((*fp_gtk_border_get_type)())
 
 #define G_TYPE_FUNDAMENTAL_SHIFT        (2)
 #define G_TYPE_MAKE_FUNDAMENTAL(x)      ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
-#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
 
 #define CONV_BUFFER_SIZE 128
 
 #define NO_SYMBOL_EXCEPTION 1
 
-/* SynthConstants */
-const gint ENABLED    = 1 << 0;
-const gint MOUSE_OVER = 1 << 1;
-const gint PRESSED    = 1 << 2;
-const gint DISABLED   = 1 << 3;
-const gint FOCUSED    = 1 << 8;
-const gint SELECTED   = 1 << 9;
-const gint DEFAULT    = 1 << 10;
-
 static void *gtk2_libhandle = NULL;
 static void *gthread_libhandle = NULL;
 
@@ -105,54 +71,6 @@
 static gboolean new_combo = TRUE;
 const char ENV_PREFIX[] = "GTK_MODULES=";
 
-/*******************/
-enum GtkWidgetType
-{
-    _GTK_ARROW_TYPE,
-    _GTK_BUTTON_TYPE,
-    _GTK_CHECK_BUTTON_TYPE,
-    _GTK_CHECK_MENU_ITEM_TYPE,
-    _GTK_COLOR_SELECTION_DIALOG_TYPE,
-    _GTK_COMBO_BOX_TYPE,
-    _GTK_COMBO_BOX_ARROW_BUTTON_TYPE,
-    _GTK_COMBO_BOX_TEXT_FIELD_TYPE,
-    _GTK_CONTAINER_TYPE,
-    _GTK_ENTRY_TYPE,
-    _GTK_FRAME_TYPE,
-    _GTK_HANDLE_BOX_TYPE,
-    _GTK_HPANED_TYPE,
-    _GTK_HPROGRESS_BAR_TYPE,
-    _GTK_HSCALE_TYPE,
-    _GTK_HSCROLLBAR_TYPE,
-    _GTK_HSEPARATOR_TYPE,
-    _GTK_IMAGE_TYPE,
-    _GTK_MENU_TYPE,
-    _GTK_MENU_BAR_TYPE,
-    _GTK_MENU_ITEM_TYPE,
-    _GTK_NOTEBOOK_TYPE,
-    _GTK_LABEL_TYPE,
-    _GTK_RADIO_BUTTON_TYPE,
-    _GTK_RADIO_MENU_ITEM_TYPE,
-    _GTK_SCROLLED_WINDOW_TYPE,
-    _GTK_SEPARATOR_MENU_ITEM_TYPE,
-    _GTK_SEPARATOR_TOOL_ITEM_TYPE,
-    _GTK_SPIN_BUTTON_TYPE,
-    _GTK_TEXT_VIEW_TYPE,
-    _GTK_TOGGLE_BUTTON_TYPE,
-    _GTK_TOOLBAR_TYPE,
-    _GTK_TOOLTIP_TYPE,
-    _GTK_TREE_VIEW_TYPE,
-    _GTK_VIEWPORT_TYPE,
-    _GTK_VPANED_TYPE,
-    _GTK_VPROGRESS_BAR_TYPE,
-    _GTK_VSCALE_TYPE,
-    _GTK_VSCROLLBAR_TYPE,
-    _GTK_VSEPARATOR_TYPE,
-    _GTK_WINDOW_TYPE,
-    _GTK_DIALOG_TYPE,
-    _GTK_WIDGET_TYPE_SIZE
-};
-
 
 static GtkWidget *gtk2_widgets[_GTK_WIDGET_TYPE_SIZE];
 
@@ -359,20 +277,6 @@
 static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
 
 /* Method bodies */
-const char *getStrFor(JNIEnv *env, jstring val)
-{
-    int length = (*env)->GetStringLength(env, val);
-    if (length > CONV_BUFFER_SIZE-1)
-    {
-        length = CONV_BUFFER_SIZE-1;
-#ifdef DEBUG
-        fprintf(stderr, "Note: Detail is too long: %d chars\n", length);
-#endif /* DEBUG */
-    }
-
-    (*env)->GetStringUTFRegion(env, val, 0, length, convertionBuffer);
-    return convertionBuffer;
-}
 
 static void throw_exception(JNIEnv *env, const char* name, const char* message)
 {
@@ -408,33 +312,34 @@
     return result;
 }
 
-gboolean gtk2_check_version()
+gboolean gtk2_check(const char* lib_name, int flags)
 {
     if (gtk2_libhandle != NULL) {
         /* We've already successfully opened the GTK libs, so return true. */
         return TRUE;
     } else {
         void *lib = NULL;
-        gboolean result = FALSE;
 
-        lib = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+        lib = dlopen(lib_name, flags);
+
         if (lib == NULL) {
-            lib = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
-            if (lib == NULL) {
-                return FALSE;
-            }
+            return FALSE;
+        }
+
+        if (flags & RTLD_NOLOAD) {
+            return TRUE;
         }
 
         fp_gtk_check_version = dlsym(lib, "gtk_check_version");
         /* Check for GTK 2.2+ */
         if (!fp_gtk_check_version(2, 2, 0)) {
-            result = TRUE;
+            return TRUE;
         }
 
         // 8048289: workaround for https://bugzilla.gnome.org/show_bug.cgi?id=733065
         // dlclose(lib);
 
-        return result;
+        return FALSE;
     }
 }
 
@@ -450,7 +355,7 @@
 } while(0);
 
 
-void update_supported_actions(JNIEnv *env) {
+static void update_supported_actions(JNIEnv *env) {
     GVfs * (*fp_g_vfs_get_default) (void);
     const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
     const gchar * const * schemes = NULL;
@@ -513,7 +418,7 @@
 /**
  * Functions for awt_Desktop.c
  */
-gboolean gtk2_show_uri_load(JNIEnv *env) {
+static gboolean gtk2_show_uri_load(JNIEnv *env) {
      gboolean success = FALSE;
      dlerror();
      const char *gtk_version = fp_gtk_check_version(2, 14, 0);
@@ -537,6 +442,7 @@
              fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
 #endif /* DEBUG */
         } else {
+            gtk->gtk_show_uri = fp_gtk_show_uri;
             update_supported_actions(env);
             success = TRUE;
         }
@@ -547,7 +453,7 @@
 /**
  * Functions for sun_awt_X11_GtkFileDialogPeer.c
  */
-void gtk2_file_chooser_load()
+static void gtk2_file_chooser_load()
 {
     fp_gtk_file_chooser_get_filename = dl_symbol(
             "gtk_file_chooser_get_filename");
@@ -576,7 +482,7 @@
     fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_drawable_get_xid");
 }
 
-gboolean gtk2_load(JNIEnv *env)
+GtkApi* gtk2_load(JNIEnv *env, const char* lib_name)
 {
     gboolean result;
     int i;
@@ -584,11 +490,9 @@
     int (*io_handler)();
     char *gtk_modules_env;
 
-    gtk2_libhandle = dlopen(GTK2_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
+    gtk2_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
     if (gtk2_libhandle == NULL) {
-        gtk2_libhandle = dlopen(GTK2_LIB, RTLD_LAZY | RTLD_LOCAL);
-        if (gtk2_libhandle == NULL)
-            return FALSE;
+        return FALSE;
     }
 
     gthread_libhandle = dlopen(GTHREAD_LIB_VERSIONED, RTLD_LAZY | RTLD_LOCAL);
@@ -962,8 +866,12 @@
     {
         gtk2_widgets[i] = NULL;
     }
-
-    return result;
+    if (result) {
+        GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));
+        gtk2_init(gtk);
+        return gtk;
+    }
+    return NULL;
 }
 
 int gtk2_unload()
@@ -1007,7 +915,7 @@
 /* Dispatch all pending events from the GTK event loop.
  * This is needed to catch theme change and update widgets' style.
  */
-void flush_gtk_event_loop()
+static void flush_gtk_event_loop()
 {
     while( (*fp_g_main_context_iteration)(NULL, FALSE));
 }
@@ -1056,7 +964,7 @@
  * comparing results. This can be optimized by using subclassed pixmap and
  * doing the second drawing only if necessary.
 */
-void gtk2_init_painting(JNIEnv *env, gint width, gint height)
+static void gtk2_init_painting(JNIEnv *env, gint width, gint height)
 {
     GdkGC *gc;
     GdkPixbuf *white, *black;
@@ -1116,7 +1024,7 @@
  * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
  * java_awt_Transparency_TRANSLUCENT.
  */
-gint gtk2_copy_image(gint *dst, gint width, gint height)
+static gint gtk2_copy_image(gint *dst, gint width, gint height)
 {
     gint i, j, r, g, b;
     guchar *white, *black;
@@ -1778,7 +1686,7 @@
             x, y, w, h);
 }
 
-void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
                     GtkShadowType shadow_type, const gchar *detail,
                     gint x, gint y, gint width, gint height,
                     gint synth_state, GtkTextDirection dir)
@@ -1948,7 +1856,7 @@
             x, y, width, height, gap_side, gap_x, gap_width);
 }
 
-void gtk2_paint_check(WidgetType widget_type, gint synth_state,
+static void gtk2_paint_check(WidgetType widget_type, gint synth_state,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
     GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
@@ -1965,7 +1873,7 @@
             x, y, width, height);
 }
 
-void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
         gint x, gint y, gint width, gint height)
 {
@@ -1978,7 +1886,7 @@
             x, y, width, height);
 }
 
-void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
         const gchar *detail, gint x, gint y, gint width, gint height,
         GtkExpanderStyle expander_style)
 {
@@ -1991,7 +1899,7 @@
             x + width / 2, y + height / 2, expander_style);
 }
 
-void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
         gint x, gint y, gint width, gint height, GtkPositionType gap_side)
 {
@@ -2004,7 +1912,7 @@
             x, y, width, height, gap_side);
 }
 
-void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
         gint x, gint y, gint width, gint height, gboolean has_focus)
 {
@@ -2023,7 +1931,7 @@
             x, y, width, height);
 }
 
-void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
         const char *detail, gint x, gint y, gint width, gint height)
 {
     gtk2_widget = gtk2_get_widget(widget_type);
@@ -2033,7 +1941,7 @@
             NULL, gtk2_widget, detail, x, y, width, height);
 }
 
-void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
         gint x, gint y, gint width, gint height, GtkOrientation orientation)
 {
@@ -2046,7 +1954,7 @@
             x, y, width, height, orientation);
 }
 
-void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
     gtk2_widget = gtk2_get_widget(widget_type);
@@ -2056,7 +1964,7 @@
             NULL, gtk2_widget, detail, x, x + width, y);
 }
 
-void gtk2_paint_option(WidgetType widget_type, gint synth_state,
+static void gtk2_paint_option(WidgetType widget_type, gint synth_state,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
     GtkStateType state_type = get_gtk_state_type(widget_type, synth_state);
@@ -2073,7 +1981,7 @@
             x, y, width, height);
 }
 
-void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
                        GtkShadowType shadow_type, const gchar *detail,
                        gint x, gint y, gint width, gint height,
                        gint synth_state, GtkTextDirection dir)
@@ -2123,9 +2031,10 @@
     gtk2_set_direction(gtk2_widget, GTK_TEXT_DIR_LTR);
 }
 
-void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
         GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height, GtkOrientation orientation)
+        gint x, gint y, gint width, gint height, GtkOrientation orientation,
+        gboolean has_focus)
 {
     gtk2_widget = gtk2_get_widget(widget_type);
     (*fp_gtk_paint_slider)(gtk2_widget->style, gtk2_white_pixmap, state_type,
@@ -2136,7 +2045,7 @@
             x, y, width, height, orientation);
 }
 
-void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
+static void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
         const gchar *detail, gint x, gint y, gint width, gint height)
 {
     gtk2_widget = gtk2_get_widget(widget_type);
@@ -2146,7 +2055,7 @@
             NULL, gtk2_widget, detail, y, y + height, x);
 }
 
-void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
+static void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
         gint x, gint y, gint width, gint height)
 {
     gtk2_widget = gtk2_get_widget(widget_type);
@@ -2156,7 +2065,7 @@
             gtk2_black_pixmap, TRUE, state_type, NULL, x, y, width, height);
 }
 
-GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
+static GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
         GtkIconSize size, GtkTextDirection direction, const char *detail)
 {
     init_containers();
@@ -2166,8 +2075,52 @@
     return (*fp_gtk_widget_render_icon)(gtk2_widget, stock_id, size, detail);
 }
 
+static jboolean gtk2_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,
+                              jmethodID icon_upcall_method, jobject this) {
+    if (!pixbuf) {
+        return JNI_FALSE;
+    }
+    guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+    if (pixbuf_data) {
+        int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+        int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
+        int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
+        int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
+        int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+        gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
+
+        jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
+        JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+        (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
+                                   (jbyte *)pixbuf_data);
+        (*fp_g_object_unref)(pixbuf);
+
+        /* Call the callback method to create the image on the Java side. */
+        (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
+                width, height, row_stride, bps, channels, alpha);
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+static jboolean gtk2_get_file_icon_data(JNIEnv *env, const char *filename,
+                 GError **error, jmethodID icon_upcall_method, jobject this) {
+    GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);
+    return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+static jboolean gtk2_get_icon_data(JNIEnv *env, gint widget_type,
+                              const gchar *stock_id, GtkIconSize size,
+                              GtkTextDirection direction, const char *detail,
+                              jmethodID icon_upcall_method, jobject this) {
+    GdkPixbuf* pixbuf = gtk2_get_stock_icon(widget_type, stock_id, size,
+                                       direction, detail);
+    return gtk2_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
 /*************************************************/
-gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
+static gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type)
 {
     init_containers();
 
@@ -2176,7 +2129,7 @@
     return style->xthickness;
 }
 
-gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
+static gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type)
 {
     init_containers();
 
@@ -2186,12 +2139,12 @@
 }
 
 /*************************************************/
-guint8 recode_color(guint16 channel)
+static guint8 recode_color(guint16 channel)
 {
     return (guint8)(channel>>8);
 }
 
-gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
+static gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
                               GtkStateType state_type, ColorType color_type)
 {
     gint result = 0;
@@ -2243,19 +2196,19 @@
 }
 
 /*************************************************/
-jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
-jobject create_Integer(JNIEnv *env, jint int_value);
-jobject create_Long(JNIEnv *env, jlong long_value);
-jobject create_Float(JNIEnv *env, jfloat float_value);
-jobject create_Double(JNIEnv *env, jdouble double_value);
-jobject create_Character(JNIEnv *env, jchar char_value);
-jobject create_Insets(JNIEnv *env, GtkBorder *border);
+static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
+static jobject create_Integer(JNIEnv *env, jint int_value);
+static jobject create_Long(JNIEnv *env, jlong long_value);
+static jobject create_Float(JNIEnv *env, jfloat float_value);
+static jobject create_Double(JNIEnv *env, jdouble double_value);
+static jobject create_Character(JNIEnv *env, jchar char_value);
+static jobject create_Insets(JNIEnv *env, GtkBorder *border);
 
-jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring jkey)
+static jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type,
+                              const char* key)
 {
     init_containers();
 
-    const char* key = getStrFor(env, jkey);
     gtk2_widget = gtk2_get_widget(widget_type);
 
     GValue value;
@@ -2376,7 +2329,7 @@
     return NULL;
 }
 
-void gtk2_set_range_value(WidgetType widget_type, jdouble value,
+static void gtk2_set_range_value(WidgetType widget_type, jdouble value,
                           jdouble min, jdouble max, jdouble visible)
 {
     GtkAdjustment *adj;
@@ -2391,7 +2344,7 @@
 }
 
 /*************************************************/
-jobject create_Object(JNIEnv *env, jmethodID *cid,
+static jobject create_Object(JNIEnv *env, jmethodID *cid,
                              const char* class_name,
                              const char* signature,
                              jvalue* value)
@@ -2494,7 +2447,7 @@
 }
 
 /*********************************************/
-jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
+static jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
 {
     init_containers();
 
@@ -2513,7 +2466,7 @@
 }
 
 /***********************************************/
-jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_string_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
 {
     jobject result = NULL;
     gchar*  strval = NULL;
@@ -2525,21 +2478,21 @@
     return result;
 }
 
-jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_integer_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
 {
     gint intval = NULL;
     (*fp_g_object_get)(settings, key, &intval, NULL);
     return create_Integer(env, intval);
 }
 
-jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
+static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings, const gchar* key)
 {
     gint intval = NULL;
     (*fp_g_object_get)(settings, key, &intval, NULL);
     return create_Boolean(env, intval);
 }
 
-jobject gtk2_get_setting(JNIEnv *env, Setting property)
+static jobject gtk2_get_setting(JNIEnv *env, Setting property)
 {
     GtkSettings* settings = (*fp_gtk_settings_get_default)();
 
@@ -2557,3 +2510,148 @@
 
     return NULL;
 }
+
+static gboolean gtk2_get_drawable_data(JNIEnv *env, jintArray pixelArray, jint x,
+     jint y, jint width, jint height, jint jwidth, int dx, int dy, jint scale) {
+    GdkPixbuf *pixbuf;
+    jint *ary;
+
+    GdkWindow *root = (*fp_gdk_get_default_root_window)();
+
+    pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(NULL, root, NULL, x, y,
+                                                    0, 0, width, height);
+    if (pixbuf && scale != 1) {
+        GdkPixbuf *scaledPixbuf;
+        x /= scale;
+        y /= scale;
+        width /= scale;
+        height /= scale;
+        dx /= scale;
+        dy /= scale;
+        scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
+                                                     GDK_INTERP_BILINEAR);
+        (*fp_g_object_unref)(pixbuf);
+        pixbuf = scaledPixbuf;
+    }
+
+    if (pixbuf) {
+        int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+        int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+
+        if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
+                && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
+                && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
+                && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
+                && nchan >= 3
+                ) {
+            guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+
+            ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
+            if (ary) {
+                jint _x, _y;
+                int index;
+                for (_y = 0; _y < height; _y++) {
+                    for (_x = 0; _x < width; _x++) {
+                        p = pix + _y * stride + _x * nchan;
+
+                        index = (_y + dy) * jwidth + (_x + dx);
+                        ary[index] = 0xff000000
+                                        | (p[0] << 16)
+                                        | (p[1] << 8)
+                                        | (p[2]);
+
+                    }
+                }
+                (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
+            }
+        }
+        (*fp_g_object_unref)(pixbuf);
+    }
+    return JNI_FALSE;
+}
+
+static GdkWindow* gtk2_get_window(void *widget) {
+    return ((GtkWidget*)widget)->window;
+}
+
+void gtk2_init(GtkApi* gtk) {
+    gtk->version = GTK_2;
+
+    gtk->show_uri_load = &gtk2_show_uri_load;
+    gtk->unload = &gtk2_unload;
+    gtk->flush_event_loop = &flush_gtk_event_loop;
+    gtk->gtk_check_version = fp_gtk_check_version;
+    gtk->get_setting = &gtk2_get_setting;
+
+    gtk->paint_arrow = &gtk2_paint_arrow;
+    gtk->paint_box = &gtk2_paint_box;
+    gtk->paint_box_gap = &gtk2_paint_box_gap;
+    gtk->paint_expander = &gtk2_paint_expander;
+    gtk->paint_extension = &gtk2_paint_extension;
+    gtk->paint_flat_box = &gtk2_paint_flat_box;
+    gtk->paint_focus = &gtk2_paint_focus;
+    gtk->paint_handle = &gtk2_paint_handle;
+    gtk->paint_hline = &gtk2_paint_hline;
+    gtk->paint_vline = &gtk2_paint_vline;
+    gtk->paint_option = &gtk2_paint_option;
+    gtk->paint_shadow = &gtk2_paint_shadow;
+    gtk->paint_slider = &gtk2_paint_slider;
+    gtk->paint_background = &gtk_paint_background;
+    gtk->paint_check = &gtk2_paint_check;
+    gtk->set_range_value = &gtk2_set_range_value;
+
+    gtk->init_painting = &gtk2_init_painting;
+    gtk->copy_image = &gtk2_copy_image;
+
+    gtk->get_xthickness = &gtk2_get_xthickness;
+    gtk->get_ythickness = &gtk2_get_ythickness;
+    gtk->get_color_for_state = &gtk2_get_color_for_state;
+    gtk->get_class_value = &gtk2_get_class_value;
+
+    gtk->get_pango_font_name = &gtk2_get_pango_font_name;
+    gtk->get_icon_data = &gtk2_get_icon_data;
+    gtk->get_file_icon_data = &gtk2_get_file_icon_data;
+    gtk->gdk_threads_enter = fp_gdk_threads_enter;
+    gtk->gdk_threads_leave = fp_gdk_threads_leave;
+    gtk->gtk_show_uri = fp_gtk_show_uri;
+    gtk->get_drawable_data = &gtk2_get_drawable_data;
+    gtk->g_free = fp_g_free;
+
+    gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;
+    gtk->gtk_widget_hide = fp_gtk_widget_hide;
+    gtk->gtk_main_quit = fp_gtk_main_quit;
+    gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;
+    gtk->gtk_file_chooser_set_current_folder =
+                          fp_gtk_file_chooser_set_current_folder;
+    gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;
+    gtk->gtk_file_chooser_set_current_name =
+                          fp_gtk_file_chooser_set_current_name;
+    gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;
+    gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;
+    gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;
+    gtk->gtk_file_filter_new = fp_gtk_file_filter_new;
+    gtk->gtk_file_chooser_set_do_overwrite_confirmation =
+                          fp_gtk_file_chooser_set_do_overwrite_confirmation;
+    gtk->gtk_file_chooser_set_select_multiple =
+                          fp_gtk_file_chooser_set_select_multiple;
+    gtk->gtk_file_chooser_get_current_folder =
+                          fp_gtk_file_chooser_get_current_folder;
+    gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;
+    gtk->gtk_g_slist_length = fp_gtk_g_slist_length;
+    gtk->g_signal_connect_data = fp_g_signal_connect_data;
+    gtk->gtk_widget_show = fp_gtk_widget_show;
+    gtk->gtk_main = fp_gtk_main;
+    gtk->gtk_main_level = fp_gtk_main_level;
+    gtk->g_path_get_dirname = fp_g_path_get_dirname;
+    gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;
+    gtk->gtk_widget_destroy = fp_gtk_widget_destroy;
+    gtk->gtk_window_present = fp_gtk_window_present;
+    gtk->gtk_window_move = fp_gtk_window_move;
+    gtk->gtk_window_resize = fp_gtk_window_resize;
+    gtk->get_window = &gtk2_get_window;
+
+    gtk->g_object_unref = fp_g_object_unref;
+    gtk->g_list_append = fp_g_list_append;
+    gtk->g_list_free = fp_g_list_free;
+    gtk->g_list_free_full = fp_g_list_free_full;
+}
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk2_interface.h	Wed Jul 05 21:39:33 2017 +0200
@@ -28,232 +28,11 @@
 #include <stdlib.h>
 #include <jni.h>
 #include <X11/X.h>
-
-#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))
-#define GTK_TYPE_FILE_CHOOSER             (fp_gtk_file_chooser_get_type ())
-#define GTK_FILE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser))
-#define fp_g_signal_connect(instance, detailed_signal, c_handler, data) \
-    fp_g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)
-#define G_CALLBACK(f) ((GCallback) (f))
-#define G_TYPE_FUNDAMENTAL_SHIFT (2)
-#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
-#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
-#define G_OBJECT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), G_TYPE_OBJECT, GObject))
-#define GTK_STOCK_CANCEL           "gtk-cancel"
-#define GTK_STOCK_SAVE             "gtk-save"
-#define GTK_STOCK_OPEN             "gtk-open"
-#define GDK_CURRENT_TIME           0L
-
-typedef enum _WidgetType
-{
-    BUTTON,                     /* GtkButton */
-    CHECK_BOX,                  /* GtkCheckButton */
-    CHECK_BOX_MENU_ITEM,        /* GtkCheckMenuItem */
-    COLOR_CHOOSER,              /* GtkColorSelectionDialog */
-    COMBO_BOX,                  /* GtkComboBox */
-    COMBO_BOX_ARROW_BUTTON,     /* GtkComboBoxEntry */
-    COMBO_BOX_TEXT_FIELD,       /* GtkComboBoxEntry */
-    DESKTOP_ICON,               /* GtkLabel */
-    DESKTOP_PANE,               /* GtkContainer */
-    EDITOR_PANE,                /* GtkTextView */
-    FORMATTED_TEXT_FIELD,       /* GtkEntry */
-    HANDLE_BOX,                 /* GtkHandleBox */
-    HPROGRESS_BAR,              /* GtkProgressBar */
-    HSCROLL_BAR,                /* GtkHScrollbar */
-    HSCROLL_BAR_BUTTON_LEFT,    /* GtkHScrollbar */
-    HSCROLL_BAR_BUTTON_RIGHT,   /* GtkHScrollbar */
-    HSCROLL_BAR_TRACK,          /* GtkHScrollbar */
-    HSCROLL_BAR_THUMB,          /* GtkHScrollbar */
-    HSEPARATOR,                 /* GtkHSeparator */
-    HSLIDER,                    /* GtkHScale */
-    HSLIDER_TRACK,              /* GtkHScale */
-    HSLIDER_THUMB,              /* GtkHScale */
-    HSPLIT_PANE_DIVIDER,        /* GtkHPaned */
-    INTERNAL_FRAME,             /* GtkWindow */
-    INTERNAL_FRAME_TITLE_PANE,  /* GtkLabel */
-    IMAGE,                      /* GtkImage */
-    LABEL,                      /* GtkLabel */
-    LIST,                       /* GtkTreeView */
-    MENU,                       /* GtkMenu */
-    MENU_BAR,                   /* GtkMenuBar */
-    MENU_ITEM,                  /* GtkMenuItem */
-    MENU_ITEM_ACCELERATOR,      /* GtkLabel */
-    OPTION_PANE,                /* GtkMessageDialog */
-    PANEL,                      /* GtkContainer */
-    PASSWORD_FIELD,             /* GtkEntry */
-    POPUP_MENU,                 /* GtkMenu */
-    POPUP_MENU_SEPARATOR,       /* GtkSeparatorMenuItem */
-    RADIO_BUTTON,               /* GtkRadioButton */
-    RADIO_BUTTON_MENU_ITEM,     /* GtkRadioMenuItem */
-    ROOT_PANE,                  /* GtkContainer */
-    SCROLL_PANE,                /* GtkScrolledWindow */
-    SPINNER,                    /* GtkSpinButton */
-    SPINNER_ARROW_BUTTON,       /* GtkSpinButton */
-    SPINNER_TEXT_FIELD,         /* GtkSpinButton */
-    SPLIT_PANE,                 /* GtkPaned */
-    TABBED_PANE,                /* GtkNotebook */
-    TABBED_PANE_TAB_AREA,       /* GtkNotebook */
-    TABBED_PANE_CONTENT,        /* GtkNotebook */
-    TABBED_PANE_TAB,            /* GtkNotebook */
-    TABLE,                      /* GtkTreeView */
-    TABLE_HEADER,               /* GtkButton */
-    TEXT_AREA,                  /* GtkTextView */
-    TEXT_FIELD,                 /* GtkEntry */
-    TEXT_PANE,                  /* GtkTextView */
-    TITLED_BORDER,              /* GtkFrame */
-    TOGGLE_BUTTON,              /* GtkToggleButton */
-    TOOL_BAR,                   /* GtkToolbar */
-    TOOL_BAR_DRAG_WINDOW,       /* GtkToolbar */
-    TOOL_BAR_SEPARATOR,         /* GtkSeparatorToolItem */
-    TOOL_TIP,                   /* GtkWindow */
-    TREE,                       /* GtkTreeView */
-    TREE_CELL,                  /* GtkTreeView */
-    VIEWPORT,                   /* GtkViewport */
-    VPROGRESS_BAR,              /* GtkProgressBar */
-    VSCROLL_BAR,                /* GtkVScrollbar */
-    VSCROLL_BAR_BUTTON_UP,      /* GtkVScrollbar */
-    VSCROLL_BAR_BUTTON_DOWN,    /* GtkVScrollbar */
-    VSCROLL_BAR_TRACK,          /* GtkVScrollbar */
-    VSCROLL_BAR_THUMB,          /* GtkVScrollbar */
-    VSEPARATOR,                 /* GtkVSeparator */
-    VSLIDER,                    /* GtkVScale */
-    VSLIDER_TRACK,              /* GtkVScale */
-    VSLIDER_THUMB,              /* GtkVScale */
-    VSPLIT_PANE_DIVIDER,        /* GtkVPaned */
-    WIDGET_TYPE_SIZE
-} WidgetType;
-
-typedef enum _ColorType
-{
-    FOREGROUND,
-    BACKGROUND,
-    TEXT_FOREGROUND,
-    TEXT_BACKGROUND,
-    FOCUS,
-    LIGHT,
-    DARK,
-    MID,
-    BLACK,
-    WHITE
-} ColorType;
-
-typedef enum _Setting
-{
-    GTK_FONT_NAME,
-    GTK_ICON_SIZES,
-    GTK_CURSOR_BLINK,
-    GTK_CURSOR_BLINK_TIME
-} Setting;
-
-/* GTK types, here to eliminate need for GTK headers at compile time */
-
-#ifndef FALSE
-#define FALSE           (0)
-#define TRUE            (!FALSE)
-#endif
+#include "gtk_interface.h"
 
 #define GTK_HAS_FOCUS   (1 << 12)
 #define GTK_HAS_DEFAULT (1 << 14)
 
-
-/* basic types */
-typedef char    gchar;
-typedef short   gshort;
-typedef int     gint;
-typedef long    glong;
-typedef float   gfloat;
-typedef double  gdouble;
-typedef void*   gpointer;
-typedef gint    gboolean;
-
-typedef signed char  gint8;
-typedef signed short gint16;
-typedef signed int   gint32;
-
-typedef unsigned char  guchar;
-typedef unsigned char  guint8;
-typedef unsigned short gushort;
-typedef unsigned short guint16;
-typedef unsigned int   guint;
-typedef unsigned int   guint32;
-typedef unsigned int   gsize;
-typedef unsigned long  gulong;
-
-typedef signed long long   gint64;
-typedef unsigned long long guint64;
-
-/* enumerated constants */
-typedef enum
-{
-  GTK_ARROW_UP,
-  GTK_ARROW_DOWN,
-  GTK_ARROW_LEFT,
-  GTK_ARROW_RIGHT
-} GtkArrowType;
-
-typedef enum {
-  GDK_COLORSPACE_RGB
-} GdkColorspace;
-
-typedef enum
-{
-  GTK_EXPANDER_COLLAPSED,
-  GTK_EXPANDER_SEMI_COLLAPSED,
-  GTK_EXPANDER_SEMI_EXPANDED,
-  GTK_EXPANDER_EXPANDED
-} GtkExpanderStyle;
-
-typedef enum
-{
-  GTK_ICON_SIZE_INVALID,
-  GTK_ICON_SIZE_MENU,
-  GTK_ICON_SIZE_SMALL_TOOLBAR,
-  GTK_ICON_SIZE_LARGE_TOOLBAR,
-  GTK_ICON_SIZE_BUTTON,
-  GTK_ICON_SIZE_DND,
-  GTK_ICON_SIZE_DIALOG
-} GtkIconSize;
-
-typedef enum
-{
-  GTK_ORIENTATION_HORIZONTAL,
-  GTK_ORIENTATION_VERTICAL
-} GtkOrientation;
-
-typedef enum
-{
-  GTK_POS_LEFT,
-  GTK_POS_RIGHT,
-  GTK_POS_TOP,
-  GTK_POS_BOTTOM
-} GtkPositionType;
-
-typedef enum
-{
-  GTK_SHADOW_NONE,
-  GTK_SHADOW_IN,
-  GTK_SHADOW_OUT,
-  GTK_SHADOW_ETCHED_IN,
-  GTK_SHADOW_ETCHED_OUT
-} GtkShadowType;
-
-typedef enum
-{
-  GTK_STATE_NORMAL,
-  GTK_STATE_ACTIVE,
-  GTK_STATE_PRELIGHT,
-  GTK_STATE_SELECTED,
-  GTK_STATE_INSENSITIVE
-} GtkStateType;
-
-typedef enum
-{
-  GTK_TEXT_DIR_NONE,
-  GTK_TEXT_DIR_LTR,
-  GTK_TEXT_DIR_RTL
-} GtkTextDirection;
-
 typedef enum
 {
   GTK_WINDOW_TOPLEVEL,
@@ -270,41 +49,15 @@
   G_PARAM_PRIVATE             = 1 << 5
 } GParamFlags;
 
-typedef enum {
-    GDK_INTERP_NEAREST,
-    GDK_INTERP_TILES,
-    GDK_INTERP_BILINEAR,
-    GDK_INTERP_HYPER
-} GdkInterpType;
-
 /* We define all structure pointers to be void* */
-typedef void GError;
 typedef void GMainContext;
 typedef void GVfs;
 
-typedef struct _GSList GSList;
-struct _GSList
-{
-  gpointer data;
-  GSList *next;
-};
-
-typedef struct _GList GList;
-
-struct _GList
-{
-  gpointer data;
-  GList *next;
-  GList *prev;
-};
-
 typedef void GdkColormap;
 typedef void GdkDrawable;
 typedef void GdkGC;
-typedef void GdkScreen;
 typedef void GdkPixbuf;
 typedef void GdkPixmap;
-typedef void GdkWindow;
 
 typedef void GtkFixed;
 typedef void GtkMenuItem;
@@ -364,7 +117,6 @@
  * structures. This is a place where getting rid of gtk
  * headers may be dangerous.
  ******************************************************/
-typedef gulong         GType;
 
 typedef struct
 {
@@ -599,70 +351,9 @@
   guint ellipsize : 3;
 };
 
-typedef enum {
-  GTK_RESPONSE_NONE = -1,
-  GTK_RESPONSE_REJECT = -2,
-  GTK_RESPONSE_ACCEPT = -3,
-  GTK_RESPONSE_DELETE_EVENT = -4,
-  GTK_RESPONSE_OK = -5,
-  GTK_RESPONSE_CANCEL = -6,
-  GTK_RESPONSE_CLOSE = -7,
-  GTK_RESPONSE_YES = -8,
-  GTK_RESPONSE_NO = -9,
-  GTK_RESPONSE_APPLY = -10,
-  GTK_RESPONSE_HELP = -11
-} GtkResponseType;
-
-typedef struct _GtkWindow GtkWindow;
-
-typedef struct _GtkFileChooser GtkFileChooser;
-
-typedef enum {
-  GTK_FILE_CHOOSER_ACTION_OPEN,
-  GTK_FILE_CHOOSER_ACTION_SAVE,
-  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
-  GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
-} GtkFileChooserAction;
-
-typedef struct _GtkFileFilter GtkFileFilter;
-
-typedef enum {
-  GTK_FILE_FILTER_FILENAME = 1 << 0,
-  GTK_FILE_FILTER_URI = 1 << 1,
-  GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
-  GTK_FILE_FILTER_MIME_TYPE = 1 << 3
-} GtkFileFilterFlags;
-
-typedef struct {
-  GtkFileFilterFlags contains;
-  const gchar *filename;
-  const gchar *uri;
-  const gchar *display_name;
-  const gchar *mime_type;
-} GtkFileFilterInfo;
-
-typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info,
-    gpointer data);
-
-typedef void (*GDestroyNotify)(gpointer data);
-
-typedef void (*GCallback)(void);
-
-typedef struct _GClosure GClosure;
-
-typedef void (*GClosureNotify)(gpointer data, GClosure *closure);
-
-typedef enum {
-  G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1
-} GConnectFlags;
 
 typedef struct _GThreadFunctions GThreadFunctions;
 
-/*
- * Converts java.lang.String object to UTF-8 character string.
- */
-const char *getStrFor(JNIEnv *env, jstring value);
-
 /**
  * Returns :
  * NULL if the GLib library is compatible with the given version, or a string
@@ -670,7 +361,7 @@
  * Please note that the glib_check_version() is available since 2.6,
  * so you should use GLIB_CHECK_VERSION macro instead.
  */
-gchar* (*fp_glib_check_version)(guint required_major, guint required_minor,
+static gchar* (*fp_glib_check_version)(guint required_major, guint required_minor,
                        guint required_micro);
 
 /**
@@ -680,193 +371,96 @@
 #define GLIB_CHECK_VERSION(major, minor, micro) \
     (fp_glib_check_version && fp_glib_check_version(major, minor, micro) == NULL)
 
-/*
- * Check whether the gtk2 library is available and meets the minimum
- * version requirement.  If the library is already loaded this method has no
- * effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_check_version();
-
 /**
  * Returns :
  * NULL if the GTK+ library is compatible with the given version, or a string
  * describing the version mismatch.
  */
-gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor,
+static gchar* (*fp_gtk_check_version)(guint required_major, guint required_minor,
                        guint required_micro);
-/*
- * Load the gtk2 library.  If the library is already loaded this method has no
- * effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_load(JNIEnv *env);
 
-/*
- * Loads fp_gtk_show_uri function pointer. This initialization is
- * separated because the function is required only
- * for java.awt.Desktop API. The function relies on initialization in
- * gtk2_load, so it must be invoked only after a successful gtk2_load
- * invocation
- */
-gboolean gtk2_show_uri_load(JNIEnv *env);
+static void gtk2_init(GtkApi* gtk);
 
-/*
- * Unload the gtk2 library.  If the library is already unloaded this method has
- * no effect and returns success.
- * Returns FALSE on failure and TRUE on success.
- */
-gboolean gtk2_unload();
+static void (*fp_g_free)(gpointer mem);
+static void (*fp_g_object_unref)(gpointer object);
+static GdkWindow *(*fp_gdk_get_default_root_window) (void);
 
-void gtk2_paint_arrow(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height,
-        GtkArrowType arrow_type, gboolean fill);
-void gtk2_paint_box(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height,
-        gint synth_state, GtkTextDirection dir);
-void gtk2_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height,
-        GtkPositionType gap_side, gint gap_x, gint gap_width);
-void gtk2_paint_check(WidgetType widget_type, gint synth_state,
-        const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_diamond(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height);
-void gtk2_paint_expander(WidgetType widget_type, GtkStateType state_type,
-        const gchar *detail, gint x, gint y, gint width, gint height,
-        GtkExpanderStyle expander_style);
-void gtk2_paint_extension(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height, GtkPositionType gap_side);
-void gtk2_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height, gboolean has_focus);
-void gtk2_paint_focus(WidgetType widget_type, GtkStateType state_type,
-        const char *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_handle(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height, GtkOrientation orientation);
-void gtk2_paint_hline(WidgetType widget_type, GtkStateType state_type,
-        const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_option(WidgetType widget_type, gint synth_state,
-        const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk2_paint_shadow(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height,
-        gint synth_state, GtkTextDirection dir);
-void gtk2_paint_slider(WidgetType widget_type, GtkStateType state_type,
-        GtkShadowType shadow_type, const gchar *detail,
-        gint x, gint y, gint width, gint height, GtkOrientation orientation);
-void gtk2_paint_vline(WidgetType widget_type, GtkStateType state_type,
-        const gchar *detail, gint x, gint y, gint width, gint height);
-void gtk_paint_background(WidgetType widget_type, GtkStateType state_type,
-        gint x, gint y, gint width, gint height);
+static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
+static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
+static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
+static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error);
+static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
 
-void gtk2_init_painting(JNIEnv *env, gint w, gint h);
-gint gtk2_copy_image(gint *dest, gint width, gint height);
-
-gint gtk2_get_xthickness(JNIEnv *env, WidgetType widget_type);
-gint gtk2_get_ythickness(JNIEnv *env, WidgetType widget_type);
-gint gtk2_get_color_for_state(JNIEnv *env, WidgetType widget_type,
-                              GtkStateType state_type, ColorType color_type);
-jobject gtk2_get_class_value(JNIEnv *env, WidgetType widget_type, jstring key);
-
-GdkPixbuf *gtk2_get_stock_icon(gint widget_type, const gchar *stock_id,
-        GtkIconSize size, GtkTextDirection direction, const char *detail);
-GdkPixbuf *gtk2_get_icon(const gchar *filename, gint size);
-jstring gtk2_get_pango_font_name(JNIEnv *env, WidgetType widget_type);
-
-void flush_gtk_event_loop();
-
-jobject gtk2_get_setting(JNIEnv *env, Setting property);
-
-void gtk2_set_range_value(WidgetType widget_type, jdouble value,
-                          jdouble min, jdouble max, jdouble visible);
-
-void (*fp_g_free)(gpointer mem);
-void (*fp_g_object_unref)(gpointer object);
-GdkWindow *(*fp_gdk_get_default_root_window) (void);
-
-int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
-guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
-gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
-int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
-GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename, GError **error);
-GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
-
-GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
+static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkPixbuf *dest,
         GdkDrawable *src, GdkColormap *cmap, int src_x, int src_y,
         int dest_x, int dest_y, int width, int height);
-GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
+static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
         int dest_width, int dest_heigh, GdkInterpType interp_type);
 
 
-void (*fp_gtk_widget_destroy)(GtkWidget *widget);
-void (*fp_gtk_window_present)(GtkWindow *window);
-void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
-void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
+static void (*fp_gtk_widget_destroy)(void *widget);
+static void (*fp_gtk_window_present)(GtkWindow *window);
+static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
+static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
 
 /**
  * Function Pointers for GtkFileChooser
  */
-gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
-void (*fp_gtk_widget_hide)(GtkWidget *widget);
-void (*fp_gtk_main_quit)(void);
-GtkWidget* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
+static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+static void (*fp_gtk_widget_hide)(void *widget);
+static void (*fp_gtk_main_quit)(void);
+static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
     GtkWindow *parent, GtkFileChooserAction action,
     const gchar *first_button_text, ...);
-gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
+static gboolean (*fp_gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
     const gchar *filename);
-gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
     const char *filename);
-void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
     const gchar *name);
-void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
+static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
     GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
     GDestroyNotify notify);
-void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
     GtkFileFilter *filter);
-GType (*fp_gtk_file_chooser_get_type)(void);
-GtkFileFilter* (*fp_gtk_file_filter_new)(void);
-void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
+static GType (*fp_gtk_file_chooser_get_type)(void);
+static GtkFileFilter* (*fp_gtk_file_filter_new)(void);
+static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
     GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
-void (*fp_gtk_file_chooser_set_select_multiple)(
+static void (*fp_gtk_file_chooser_set_select_multiple)(
     GtkFileChooser *chooser, gboolean select_multiple);
-gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
-GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
-guint (*fp_gtk_g_slist_length)(GSList *list);
-gulong (*fp_g_signal_connect_data)(gpointer instance,
+static gchar* (*fp_gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
+static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+static guint (*fp_gtk_g_slist_length)(GSList *list);
+static gulong (*fp_g_signal_connect_data)(gpointer instance,
     const gchar *detailed_signal, GCallback c_handler, gpointer data,
     GClosureNotify destroy_data, GConnectFlags connect_flags);
-void (*fp_gtk_widget_show)(GtkWidget *widget);
-void (*fp_gtk_main)(void);
-guint (*fp_gtk_main_level)(void);
-gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
-XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
+static void (*fp_gtk_widget_show)(void *widget);
+static void (*fp_gtk_main)(void);
+static guint (*fp_gtk_main_level)(void);
+static gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
+static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
 
-
-GList* (*fp_g_list_append) (GList *list, gpointer data);
-void (*fp_g_list_free) (GList *list);
-void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
+static GList* (*fp_g_list_append) (GList *list, gpointer data);
+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.
  */
-gboolean (*fp_g_thread_get_initialized)(void);
+static gboolean (*fp_g_thread_get_initialized)(void);
 
-void (*fp_g_thread_init)(GThreadFunctions *vtable);
-void (*fp_gdk_threads_init)(void);
-void (*fp_gdk_threads_enter)(void);
-void (*fp_gdk_threads_leave)(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);
 
-gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
+static gboolean (*fp_gtk_show_uri)(GdkScreen *screen, const gchar *uri,
     guint32 timestamp, GError **error);
 
 #endif /* !_GTK2_INTERFACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,2882 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <dlfcn.h>
+#include <setjmp.h>
+#include <X11/Xlib.h>
+#include <limits.h>
+#include <string.h>
+#include "gtk3_interface.h"
+#include "java_awt_Transparency.h"
+#include "sizecalc.h"
+#include <jni_util.h>
+#include <stdio.h>
+#include "awt.h"
+
+static void *gtk3_libhandle = NULL;
+
+static jmp_buf j;
+
+/* Widgets */
+static GtkWidget *gtk3_widget = NULL;
+static GtkWidget *gtk3_window = NULL;
+static GtkFixed  *gtk3_fixed  = NULL;
+static GtkStyleProvider *gtk3_css = NULL;
+
+/* Paint system */
+static cairo_surface_t *surface = NULL;
+static cairo_t *cr = NULL;
+
+static const char ENV_PREFIX[] = "GTK_MODULES=";
+
+static GtkWidget *gtk3_widgets[_GTK_WIDGET_TYPE_SIZE];
+
+static void throw_exception(JNIEnv *env, const char* name, const char* message)
+{
+    jclass class = (*env)->FindClass(env, name);
+
+    if (class != NULL)
+        (*env)->ThrowNew(env, class, message);
+
+    (*env)->DeleteLocalRef(env, class);
+}
+
+static void gtk3_add_state(GtkWidget *widget, GtkStateType state) {
+    GtkStateType old_state = fp_gtk_widget_get_state(widget);
+    fp_gtk_widget_set_state(widget, old_state | state);
+}
+
+static void gtk3_remove_state(GtkWidget *widget, GtkStateType state) {
+    GtkStateType old_state = fp_gtk_widget_get_state(widget);
+    fp_gtk_widget_set_state(widget, old_state & ~state);
+}
+
+/* This is a workaround for the bug:
+ * http://sourceware.org/bugzilla/show_bug.cgi?id=1814
+ * (dlsym/dlopen clears dlerror state)
+ * This bug is specific to Linux, but there is no harm in
+ * applying this workaround on Solaris as well.
+ */
+static void* dl_symbol(const char* name)
+{
+    void* result = dlsym(gtk3_libhandle, name);
+    if (!result)
+        longjmp(j, NO_SYMBOL_EXCEPTION);
+
+    return result;
+}
+
+gboolean gtk3_check(const char* lib_name, int flags)
+{
+    if (gtk3_libhandle != NULL) {
+        /* We've already successfully opened the GTK libs, so return true. */
+        return TRUE;
+    } else {
+        return dlopen(lib_name, flags) != NULL;
+    }
+}
+
+#define ADD_SUPPORTED_ACTION(actionStr)                                        \
+do {                                                                           \
+    jfieldID fld_action = (*env)->GetStaticFieldID(env, cls_action, actionStr, \
+                                                 "Ljava/awt/Desktop$Action;"); \
+    if (!(*env)->ExceptionCheck(env)) {                                        \
+        jobject action = (*env)->GetStaticObjectField(env, cls_action,         \
+                                                                  fld_action); \
+        (*env)->CallBooleanMethod(env, supportedActions, mid_arrayListAdd,     \
+                                                                      action); \
+    } else {                                                                   \
+        (*env)->ExceptionClear(env);                                           \
+    }                                                                          \
+} while(0);
+
+
+static void update_supported_actions(JNIEnv *env) {
+    GVfs * (*fp_g_vfs_get_default) (void);
+    const gchar * const * (*fp_g_vfs_get_supported_uri_schemes) (GVfs * vfs);
+    const gchar * const * schemes = NULL;
+
+    jclass cls_action = (*env)->FindClass(env, "java/awt/Desktop$Action");
+    CHECK_NULL(cls_action);
+    jclass cls_xDesktopPeer = (*env)->
+                                     FindClass(env, "sun/awt/X11/XDesktopPeer");
+    CHECK_NULL(cls_xDesktopPeer);
+    jfieldID fld_supportedActions = (*env)->GetStaticFieldID(env,
+                      cls_xDesktopPeer, "supportedActions", "Ljava/util/List;");
+    CHECK_NULL(fld_supportedActions);
+    jobject supportedActions = (*env)->GetStaticObjectField(env,
+                                        cls_xDesktopPeer, fld_supportedActions);
+
+    jclass cls_arrayList = (*env)->FindClass(env, "java/util/ArrayList");
+    CHECK_NULL(cls_arrayList);
+    jmethodID mid_arrayListAdd = (*env)->GetMethodID(env, cls_arrayList, "add",
+                                                       "(Ljava/lang/Object;)Z");
+    CHECK_NULL(mid_arrayListAdd);
+    jmethodID mid_arrayListClear = (*env)->GetMethodID(env, cls_arrayList,
+                                                                "clear", "()V");
+    CHECK_NULL(mid_arrayListClear);
+
+    (*env)->CallVoidMethod(env, supportedActions, mid_arrayListClear);
+
+    ADD_SUPPORTED_ACTION("OPEN");
+
+    /**
+     * gtk_show_uri() documentation says:
+     *
+     * > you need to install gvfs to get support for uri schemes such as http://
+     * > or ftp://, as only local files are handled by GIO itself.
+     *
+     * So OPEN action was safely added here.
+     * However, it looks like Solaris 11 have gvfs support only for 32-bit
+     * applications only by default.
+     */
+
+    fp_g_vfs_get_default = dl_symbol("g_vfs_get_default");
+    fp_g_vfs_get_supported_uri_schemes =
+                           dl_symbol("g_vfs_get_supported_uri_schemes");
+    dlerror();
+
+    if (fp_g_vfs_get_default && fp_g_vfs_get_supported_uri_schemes) {
+        GVfs * vfs = fp_g_vfs_get_default();
+        schemes = vfs ? fp_g_vfs_get_supported_uri_schemes(vfs) : NULL;
+        if (schemes) {
+            int i = 0;
+            while (schemes[i]) {
+                if (strcmp(schemes[i], "http") == 0) {
+                    ADD_SUPPORTED_ACTION("BROWSE");
+                    ADD_SUPPORTED_ACTION("MAIL");
+                    break;
+                }
+                i++;
+            }
+        }
+    } else {
+#ifdef DEBUG
+        fprintf(stderr, "Cannot load g_vfs_get_supported_uri_schemes\n");
+#endif /* DEBUG */
+    }
+
+}
+/**
+ * Functions for awt_Desktop.c
+ */
+static gboolean gtk3_show_uri_load(JNIEnv *env) {
+    gboolean success = FALSE;
+    dlerror();
+    fp_gtk_show_uri = dl_symbol("gtk_show_uri");
+    const char *dlsym_error = dlerror();
+    if (dlsym_error) {
+#ifdef DEBUG
+        fprintf (stderr, "Cannot load symbol: %s \n", dlsym_error);
+#endif /* DEBUG */
+    } else if (fp_gtk_show_uri == NULL) {
+#ifdef DEBUG
+        fprintf(stderr, "dlsym(gtk_show_uri) returned NULL\n");
+#endif /* DEBUG */
+    } else {
+        gtk->gtk_show_uri = fp_gtk_show_uri;
+        update_supported_actions(env);
+        success = TRUE;
+    }
+    return success;
+}
+
+/**
+ * Functions for sun_awt_X11_GtkFileDialogPeer.c
+ */
+static void gtk3_file_chooser_load()
+{
+    fp_gtk_file_chooser_get_filename = dl_symbol(
+            "gtk_file_chooser_get_filename");
+    fp_gtk_file_chooser_dialog_new = dl_symbol("gtk_file_chooser_dialog_new");
+    fp_gtk_file_chooser_set_current_folder = dl_symbol(
+            "gtk_file_chooser_set_current_folder");
+    fp_gtk_file_chooser_set_filename = dl_symbol(
+            "gtk_file_chooser_set_filename");
+    fp_gtk_file_chooser_set_current_name = dl_symbol(
+            "gtk_file_chooser_set_current_name");
+    fp_gtk_file_filter_add_custom = dl_symbol("gtk_file_filter_add_custom");
+    fp_gtk_file_chooser_set_filter = dl_symbol("gtk_file_chooser_set_filter");
+    fp_gtk_file_chooser_get_type = dl_symbol("gtk_file_chooser_get_type");
+    fp_gtk_file_filter_new = dl_symbol("gtk_file_filter_new");
+    fp_gtk_file_chooser_set_do_overwrite_confirmation = dl_symbol(
+                "gtk_file_chooser_set_do_overwrite_confirmation");
+    fp_gtk_file_chooser_set_select_multiple = dl_symbol(
+            "gtk_file_chooser_set_select_multiple");
+    fp_gtk_file_chooser_get_current_folder = dl_symbol(
+            "gtk_file_chooser_get_current_folder");
+    fp_gtk_file_chooser_get_filenames = dl_symbol(
+            "gtk_file_chooser_get_filenames");
+    fp_gtk_g_slist_length = dl_symbol("g_slist_length");
+    fp_gdk_x11_drawable_get_xid = dl_symbol("gdk_x11_window_get_xid");
+}
+
+static void empty() {}
+
+static gboolean gtk3_version_3_10 = TRUE;
+static gboolean gtk3_version_3_14 = FALSE;
+
+GtkApi* gtk3_load(JNIEnv *env, const char* lib_name)
+{
+    gboolean result;
+    int i;
+    int (*handler)();
+    int (*io_handler)();
+    char *gtk_modules_env;
+    gtk3_libhandle = dlopen(lib_name, RTLD_LAZY | RTLD_LOCAL);
+    if (gtk3_libhandle == NULL) {
+        return FALSE;
+    }
+
+    if (setjmp(j) == 0)
+    {
+        fp_gtk_check_version = dl_symbol("gtk_check_version");
+
+        /* GLib */
+        fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version");
+        if (!fp_glib_check_version) {
+            dlerror();
+        }
+        fp_g_free = dl_symbol("g_free");
+        fp_g_object_unref = dl_symbol("g_object_unref");
+
+        fp_g_main_context_iteration =
+            dl_symbol("g_main_context_iteration");
+
+        fp_g_value_init = dl_symbol("g_value_init");
+        fp_g_type_is_a = dl_symbol("g_type_is_a");
+        fp_g_value_get_boolean = dl_symbol("g_value_get_boolean");
+        fp_g_value_get_char = dl_symbol("g_value_get_char");
+        fp_g_value_get_uchar = dl_symbol("g_value_get_uchar");
+        fp_g_value_get_int = dl_symbol("g_value_get_int");
+        fp_g_value_get_uint = dl_symbol("g_value_get_uint");
+        fp_g_value_get_long = dl_symbol("g_value_get_long");
+        fp_g_value_get_ulong = dl_symbol("g_value_get_ulong");
+        fp_g_value_get_int64 = dl_symbol("g_value_get_int64");
+        fp_g_value_get_uint64 = dl_symbol("g_value_get_uint64");
+        fp_g_value_get_float = dl_symbol("g_value_get_float");
+        fp_g_value_get_double = dl_symbol("g_value_get_double");
+        fp_g_value_get_string = dl_symbol("g_value_get_string");
+        fp_g_value_get_enum = dl_symbol("g_value_get_enum");
+        fp_g_value_get_flags = dl_symbol("g_value_get_flags");
+        fp_g_value_get_param = dl_symbol("g_value_get_param");
+        fp_g_value_get_boxed = dl_symbol("g_value_get_boxed");
+        fp_g_value_get_pointer = dl_symbol("g_value_get_pointer");
+
+        fp_g_object_get = dl_symbol("g_object_get");
+        fp_g_object_set = dl_symbol("g_object_set");
+
+        fp_g_str_has_prefix = dl_symbol("g_str_has_prefix");
+        fp_g_strsplit = dl_symbol("g_strsplit");
+        fp_g_strfreev = dl_symbol("g_strfreev");
+
+        /* GDK */
+        fp_gdk_get_default_root_window =
+            dl_symbol("gdk_get_default_root_window");
+
+        /* Pixbuf */
+        fp_gdk_pixbuf_new = dl_symbol("gdk_pixbuf_new");
+        fp_gdk_pixbuf_new_from_file =
+                dl_symbol("gdk_pixbuf_new_from_file");
+        fp_gdk_pixbuf_get_from_drawable =
+                    dl_symbol("gdk_pixbuf_get_from_window");
+        fp_gdk_pixbuf_get_width = dl_symbol("gdk_pixbuf_get_width");
+        fp_gdk_pixbuf_get_height = dl_symbol("gdk_pixbuf_get_height");
+        fp_gdk_pixbuf_get_pixels = dl_symbol("gdk_pixbuf_get_pixels");
+        fp_gdk_pixbuf_get_rowstride =
+                dl_symbol("gdk_pixbuf_get_rowstride");
+        fp_gdk_pixbuf_get_has_alpha =
+                dl_symbol("gdk_pixbuf_get_has_alpha");
+        fp_gdk_pixbuf_get_bits_per_sample =
+                dl_symbol("gdk_pixbuf_get_bits_per_sample");
+        fp_gdk_pixbuf_get_n_channels =
+                dl_symbol("gdk_pixbuf_get_n_channels");
+        fp_gdk_pixbuf_get_colorspace =
+                dl_symbol("gdk_pixbuf_get_colorspace");
+
+        fp_cairo_image_surface_create = dl_symbol("cairo_image_surface_create");
+        fp_cairo_surface_destroy = dl_symbol("cairo_surface_destroy");
+        fp_cairo_create = dl_symbol("cairo_create");
+        fp_cairo_destroy = dl_symbol("cairo_destroy");
+        fp_cairo_fill = dl_symbol("cairo_fill");
+        fp_cairo_rectangle = dl_symbol("cairo_rectangle");
+        fp_cairo_set_source_rgb = dl_symbol("cairo_set_source_rgb");
+        fp_cairo_set_source_rgba = dl_symbol("cairo_set_source_rgba");
+        fp_cairo_surface_flush = dl_symbol("cairo_surface_flush");
+        fp_cairo_paint = dl_symbol("cairo_paint");
+        fp_cairo_clip = dl_symbol("cairo_clip");
+        fp_cairo_image_surface_get_data =
+                       dl_symbol("cairo_image_surface_get_data");
+        fp_cairo_image_surface_get_stride =
+                       dl_symbol("cairo_image_surface_get_stride");
+
+        fp_gdk_pixbuf_get_from_surface =
+                       dl_symbol("gdk_pixbuf_get_from_surface");
+
+        fp_gtk_widget_get_state = dl_symbol("gtk_widget_get_state");
+        fp_gtk_widget_set_state = dl_symbol("gtk_widget_set_state");
+
+        fp_gtk_widget_is_focus = dl_symbol("gtk_widget_is_focus");
+        fp_gtk_widget_set_allocation = dl_symbol("gtk_widget_set_allocation");
+        fp_gtk_widget_get_parent = dl_symbol("gtk_widget_get_parent");
+        fp_gtk_widget_get_window = dl_symbol("gtk_widget_get_window");
+
+        fp_gtk_widget_get_style_context =
+                       dl_symbol("gtk_widget_get_style_context");
+        fp_gtk_style_context_get_color =
+                       dl_symbol("gtk_style_context_get_color");
+        fp_gtk_style_context_get_background_color =
+                       dl_symbol("gtk_style_context_get_background_color");
+        fp_gtk_widget_get_state_flags = dl_symbol("gtk_widget_get_state_flags");
+        fp_gtk_style_context_set_state =
+                       dl_symbol("gtk_style_context_set_state");
+        fp_gtk_style_context_add_class =
+                       dl_symbol("gtk_style_context_add_class");
+        fp_gtk_style_context_save = dl_symbol("gtk_style_context_save");
+        fp_gtk_style_context_restore = dl_symbol("gtk_style_context_restore");
+        fp_gtk_render_check = dl_symbol("gtk_render_check");
+        fp_gtk_render_option = dl_symbol("gtk_render_option");
+        fp_gtk_render_extension = dl_symbol("gtk_render_extension");
+        fp_gtk_render_expander = dl_symbol("gtk_render_expander");
+        fp_gtk_render_frame_gap = dl_symbol("gtk_render_frame_gap");
+        fp_gtk_render_line = dl_symbol("gtk_render_line");
+        fp_gtk_widget_render_icon_pixbuf =
+                      dl_symbol("gtk_widget_render_icon_pixbuf");
+        if (fp_gtk_check_version(3, 10, 0)) {
+            gtk3_version_3_10 = FALSE;
+        } else {
+            fp_gdk_window_create_similar_image_surface =
+                       dl_symbol("gdk_window_create_similar_image_surface");
+        }
+        gtk3_version_3_14 = !fp_gtk_check_version(3, 14, 0);
+
+        fp_gdk_window_create_similar_surface =
+                      dl_symbol("gdk_window_create_similar_surface");
+        fp_gtk_settings_get_for_screen =
+                      dl_symbol("gtk_settings_get_for_screen");
+        fp_gtk_widget_get_screen = dl_symbol("gtk_widget_get_screen");
+        fp_gtk_css_provider_get_named = dl_symbol("gtk_css_provider_get_named");
+        fp_gtk_style_context_add_provider =
+                      dl_symbol("gtk_style_context_add_provider");
+        fp_gtk_render_frame = dl_symbol("gtk_render_frame");
+        fp_gtk_render_focus = dl_symbol("gtk_render_focus");
+        fp_gtk_render_handle = dl_symbol("gtk_render_handle");
+        fp_gtk_render_arrow = dl_symbol("gtk_render_arrow");
+
+        fp_gtk_style_context_get_property =
+                      dl_symbol("gtk_style_context_get_property");
+        fp_gtk_scrolled_window_set_shadow_type =
+                      dl_symbol("gtk_scrolled_window_set_shadow_type");
+        fp_gtk_render_slider = dl_symbol("gtk_render_slider");
+        fp_gtk_style_context_get_padding =
+                      dl_symbol("gtk_style_context_get_padding");
+        fp_gtk_range_set_inverted = dl_symbol("gtk_range_set_inverted");
+        fp_gtk_style_context_get_font = dl_symbol("gtk_style_context_get_font");
+        fp_gtk_widget_get_allocated_width =
+                      dl_symbol("gtk_widget_get_allocated_width");
+        fp_gtk_widget_get_allocated_height =
+                      dl_symbol("gtk_widget_get_allocated_height");
+        fp_gtk_icon_theme_get_default = dl_symbol("gtk_icon_theme_get_default");
+        fp_gtk_icon_theme_load_icon = dl_symbol("gtk_icon_theme_load_icon");
+
+        fp_gtk_adjustment_set_lower = dl_symbol("gtk_adjustment_set_lower");
+        fp_gtk_adjustment_set_page_increment =
+                      dl_symbol("gtk_adjustment_set_page_increment");
+        fp_gtk_adjustment_set_page_size =
+                      dl_symbol("gtk_adjustment_set_page_size");
+        fp_gtk_adjustment_set_step_increment =
+                      dl_symbol("gtk_adjustment_set_step_increment");
+        fp_gtk_adjustment_set_upper = dl_symbol("gtk_adjustment_set_upper");
+        fp_gtk_adjustment_set_value = dl_symbol("gtk_adjustment_set_value");
+
+        fp_gtk_render_activity = dl_symbol("gtk_render_activity");
+        fp_gtk_render_background = dl_symbol("gtk_render_background");
+        fp_gtk_style_context_has_class =
+                      dl_symbol("gtk_style_context_has_class");
+
+        fp_gtk_style_context_set_junction_sides =
+                      dl_symbol("gtk_style_context_set_junction_sides");
+        fp_gtk_style_context_add_region =
+                      dl_symbol("gtk_style_context_add_region");
+
+        fp_gtk_init_check = dl_symbol("gtk_init_check");
+
+        /* GTK widgets */
+        fp_gtk_arrow_new = dl_symbol("gtk_arrow_new");
+        fp_gtk_button_new = dl_symbol("gtk_button_new");
+        fp_gtk_spin_button_new = dl_symbol("gtk_spin_button_new");
+        fp_gtk_check_button_new = dl_symbol("gtk_check_button_new");
+        fp_gtk_check_menu_item_new =
+                dl_symbol("gtk_check_menu_item_new");
+        fp_gtk_color_selection_dialog_new =
+                dl_symbol("gtk_color_selection_dialog_new");
+        fp_gtk_entry_new = dl_symbol("gtk_entry_new");
+        fp_gtk_fixed_new = dl_symbol("gtk_fixed_new");
+        fp_gtk_handle_box_new = dl_symbol("gtk_handle_box_new");
+        fp_gtk_image_new = dl_symbol("gtk_image_new");
+        fp_gtk_hpaned_new = dl_symbol("gtk_hpaned_new");
+        fp_gtk_vpaned_new = dl_symbol("gtk_vpaned_new");
+        fp_gtk_scale_new = dl_symbol("gtk_scale_new");
+        fp_gtk_hscrollbar_new = dl_symbol("gtk_hscrollbar_new");
+        fp_gtk_vscrollbar_new = dl_symbol("gtk_vscrollbar_new");
+        fp_gtk_hseparator_new = dl_symbol("gtk_hseparator_new");
+        fp_gtk_vseparator_new = dl_symbol("gtk_vseparator_new");
+        fp_gtk_label_new = dl_symbol("gtk_label_new");
+        fp_gtk_menu_new = dl_symbol("gtk_menu_new");
+        fp_gtk_menu_bar_new = dl_symbol("gtk_menu_bar_new");
+        fp_gtk_menu_item_new = dl_symbol("gtk_menu_item_new");
+        fp_gtk_menu_item_set_submenu =
+                dl_symbol("gtk_menu_item_set_submenu");
+        fp_gtk_notebook_new = dl_symbol("gtk_notebook_new");
+        fp_gtk_progress_bar_new =
+            dl_symbol("gtk_progress_bar_new");
+        fp_gtk_progress_bar_set_orientation =
+            dl_symbol("gtk_orientable_set_orientation");
+        fp_gtk_radio_button_new =
+            dl_symbol("gtk_radio_button_new");
+        fp_gtk_radio_menu_item_new =
+            dl_symbol("gtk_radio_menu_item_new");
+        fp_gtk_scrolled_window_new =
+            dl_symbol("gtk_scrolled_window_new");
+        fp_gtk_separator_menu_item_new =
+            dl_symbol("gtk_separator_menu_item_new");
+        fp_gtk_text_view_new = dl_symbol("gtk_text_view_new");
+        fp_gtk_toggle_button_new =
+            dl_symbol("gtk_toggle_button_new");
+        fp_gtk_toolbar_new = dl_symbol("gtk_toolbar_new");
+        fp_gtk_tree_view_new = dl_symbol("gtk_tree_view_new");
+        fp_gtk_viewport_new = dl_symbol("gtk_viewport_new");
+        fp_gtk_window_new = dl_symbol("gtk_window_new");
+        fp_gtk_window_present = dl_symbol("gtk_window_present");
+        fp_gtk_window_move = dl_symbol("gtk_window_move");
+        fp_gtk_window_resize = dl_symbol("gtk_window_resize");
+
+          fp_gtk_dialog_new = dl_symbol("gtk_dialog_new");
+        fp_gtk_frame_new = dl_symbol("gtk_frame_new");
+
+        fp_gtk_adjustment_new = dl_symbol("gtk_adjustment_new");
+        fp_gtk_container_add = dl_symbol("gtk_container_add");
+        fp_gtk_menu_shell_append =
+            dl_symbol("gtk_menu_shell_append");
+        fp_gtk_widget_realize = dl_symbol("gtk_widget_realize");
+        fp_gtk_widget_destroy = dl_symbol("gtk_widget_destroy");
+        fp_gtk_widget_render_icon =
+            dl_symbol("gtk_widget_render_icon");
+        fp_gtk_widget_set_name =
+            dl_symbol("gtk_widget_set_name");
+        fp_gtk_widget_set_parent =
+            dl_symbol("gtk_widget_set_parent");
+        fp_gtk_widget_set_direction =
+            dl_symbol("gtk_widget_set_direction");
+        fp_gtk_widget_style_get =
+            dl_symbol("gtk_widget_style_get");
+        fp_gtk_widget_class_install_style_property =
+            dl_symbol("gtk_widget_class_install_style_property");
+        fp_gtk_widget_class_find_style_property =
+            dl_symbol("gtk_widget_class_find_style_property");
+        fp_gtk_widget_style_get_property =
+            dl_symbol("gtk_widget_style_get_property");
+        fp_pango_font_description_to_string =
+            dl_symbol("pango_font_description_to_string");
+        fp_gtk_settings_get_default =
+            dl_symbol("gtk_settings_get_default");
+        fp_gtk_widget_get_settings =
+            dl_symbol("gtk_widget_get_settings");
+        fp_gtk_border_get_type =  dl_symbol("gtk_border_get_type");
+        fp_gtk_arrow_set = dl_symbol("gtk_arrow_set");
+        fp_gtk_widget_size_request =
+            dl_symbol("gtk_widget_size_request");
+        fp_gtk_range_get_adjustment =
+            dl_symbol("gtk_range_get_adjustment");
+
+        fp_gtk_widget_hide = dl_symbol("gtk_widget_hide");
+        fp_gtk_main_quit = dl_symbol("gtk_main_quit");
+        fp_g_signal_connect_data = dl_symbol("g_signal_connect_data");
+        fp_gtk_widget_show = dl_symbol("gtk_widget_show");
+        fp_gtk_main = dl_symbol("gtk_main");
+
+        fp_g_path_get_dirname = dl_symbol("g_path_get_dirname");
+
+        fp_gdk_threads_enter = &empty;
+        fp_gdk_threads_leave = &empty;
+
+        /**
+         * Functions for sun_awt_X11_GtkFileDialogPeer.c
+         */
+        gtk3_file_chooser_load();
+
+        fp_gtk_combo_box_new = dlsym(gtk3_libhandle, "gtk_combo_box_new");
+        fp_gtk_combo_box_entry_new = dlsym(gtk3_libhandle,
+                                                "gtk_combo_box_new_with_entry");
+        fp_gtk_separator_tool_item_new = dlsym(gtk3_libhandle,
+                                                 "gtk_separator_tool_item_new");
+
+        fp_g_list_append = dl_symbol("g_list_append");
+        fp_g_list_free = dl_symbol("g_list_free");
+        fp_g_list_free_full = dl_symbol("g_list_free_full");
+    }
+    /* Now we have only one kind of exceptions: NO_SYMBOL_EXCEPTION
+     * Otherwise we can check the return value of setjmp method.
+     */
+    else
+    {
+        dlclose(gtk3_libhandle);
+        gtk3_libhandle = NULL;
+
+        return NULL;
+    }
+
+    /*
+     * Strip the AT-SPI GTK_MODULEs if present
+     */
+    gtk_modules_env = getenv ("GTK_MODULES");
+    if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") ||
+        gtk_modules_env && strstr (gtk_modules_env, "gail"))
+    {
+        /* the new env will be smaller than the old one */
+        gchar *s, *new_env = SAFE_SIZE_STRUCT_ALLOC(malloc,
+                sizeof(ENV_PREFIX), 1, strlen (gtk_modules_env));
+
+        if (new_env != NULL )
+        {
+            /* careful, strtok modifies its args */
+            gchar *tmp_env = strdup (gtk_modules_env);
+            strcpy(new_env, ENV_PREFIX);
+
+            /* strip out 'atk-bridge' and 'gail' */
+            size_t PREFIX_LENGTH = strlen(ENV_PREFIX);
+            while (s = strtok(tmp_env, ":"))
+            {
+                if ((!strstr (s, "atk-bridge")) && (!strstr (s, "gail")))
+                {
+                    if (strlen (new_env) > PREFIX_LENGTH) {
+                        new_env = strcat (new_env, ":");
+                    }
+                    new_env = strcat(new_env, s);
+                }
+                if (tmp_env)
+                {
+                    free (tmp_env);
+                    tmp_env = NULL; /* next call to strtok arg1==NULL */
+                }
+            }
+            putenv (new_env);
+            free (new_env);
+            free (tmp_env);
+        }
+    }
+    /*
+     * GTK should be initialized with gtk_init_check() before use.
+     *
+     * gtk_init_check installs its own error handlers. It is critical that
+     * we preserve error handler set from AWT. Otherwise we'll crash on
+     * BadMatch errors which we would normally ignore. The IO error handler
+     * is preserved here, too, just for consistency.
+    */
+    AWT_LOCK();
+    handler = XSetErrorHandler(NULL);
+    io_handler = XSetIOErrorHandler(NULL);
+    result = (*fp_gtk_init_check)(NULL, NULL);
+    XSetErrorHandler(handler);
+    XSetIOErrorHandler(io_handler);
+    AWT_UNLOCK();
+    /* Initialize widget array. */
+    for (i = 0; i < _GTK_WIDGET_TYPE_SIZE; i++)
+    {
+        gtk3_widgets[i] = NULL;
+    }
+    if (result) {
+        GtkApi* gtk = (GtkApi*)malloc(sizeof(GtkApi));
+        gtk3_init(gtk);
+        return gtk;
+    }
+    return NULL;
+}
+
+static int gtk3_unload()
+{
+    int i;
+    char *gtk3_error;
+
+    if (!gtk3_libhandle)
+        return TRUE;
+
+    /* Release painting objects */
+    if (surface != NULL) {
+        fp_cairo_destroy(cr);
+        fp_cairo_surface_destroy(surface);
+        surface = NULL;
+    }
+
+    if (gtk3_window != NULL) {
+        /* Destroying toplevel widget will destroy all contained widgets */
+        (*fp_gtk_widget_destroy)(gtk3_window);
+
+        /* Unset some static data so they get reinitialized on next load */
+        gtk3_window = NULL;
+    }
+
+    dlerror();
+    dlclose(gtk3_libhandle);
+    if ((gtk3_error = dlerror()) != NULL)
+    {
+        return FALSE;
+    }
+    return TRUE;
+}
+
+/* Dispatch all pending events from the GTK event loop.
+ * This is needed to catch theme change and update widgets' style.
+ */
+static void flush_gtk_event_loop()
+{
+    while((*fp_g_main_context_iteration)(NULL));
+}
+
+/*
+ * Initialize components of containment hierarchy. This creates a GtkFixed
+ * inside a GtkWindow. All widgets get realized.
+ */
+static void init_containers()
+{
+    if (gtk3_window == NULL)
+    {
+        gtk3_window = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+        gtk3_fixed = (GtkFixed *)(*fp_gtk_fixed_new)();
+        (*fp_gtk_container_add)((GtkContainer*)gtk3_window,
+                                (GtkWidget *)gtk3_fixed);
+        (*fp_gtk_widget_realize)(gtk3_window);
+        (*fp_gtk_widget_realize)((GtkWidget *)gtk3_fixed);
+
+        GtkSettings* settings = fp_gtk_settings_get_for_screen(
+                                         fp_gtk_widget_get_screen(gtk3_window));
+        gchar*  strval = NULL;
+        fp_g_object_get(settings, "gtk-theme-name", &strval, NULL);
+        gtk3_css = fp_gtk_css_provider_get_named(strval, NULL);
+    }
+}
+
+/*
+ * Ensure everything is ready for drawing an element of the specified width
+ * and height.
+ *
+ * We should somehow handle translucent images. GTK can draw to X Drawables
+ * only, which don't support alpha. When we retrieve the image back from
+ * the server, translucency information is lost. There're several ways to
+ * work around this:
+ * 1) Subclass GdkPixmap and cache translucent objects on client side. This
+ * requires us to implement parts of X server drawing logic on client side.
+ * Many X requests can potentially be "translucent"; e.g. XDrawLine with
+ * fill=tile and a translucent tile is a "translucent" operation, whereas
+ * XDrawLine with fill=solid is an "opaque" one. Moreover themes can (and some
+ * do) intermix transparent and opaque operations which makes caching even
+ * more problematic.
+ * 2) Use Xorg 32bit ARGB visual when available. GDK has no native support
+ * for it (as of version 2.6). Also even in JDS 3 Xorg does not support
+ * these visuals by default, which makes optimizing for them pointless.
+ * We can consider doing this at a later point when ARGB visuals become more
+ * popular.
+ * 3') GTK has plans to use Cairo as its graphical backend (presumably in
+ * 2.8), and Cairo supports alpha. With it we could also get rid of the
+ * unnecessary round trip to server and do all the drawing on client side.
+ * 4) For now we draw to two different pixmaps and restore alpha channel by
+ * comparing results. This can be optimized by using subclassed pixmap and
+*/
+static void gtk3_init_painting(JNIEnv *env, gint width, gint height)
+{
+    init_containers();
+
+    if (cr) {
+        fp_cairo_destroy(cr);
+    }
+
+    if (surface != NULL) {
+        /* free old stuff */
+        fp_cairo_surface_destroy(surface);
+
+    }
+
+    if (gtk3_version_3_10) {
+        surface = fp_gdk_window_create_similar_image_surface(
+                           fp_gtk_widget_get_window(gtk3_window),
+                                         CAIRO_FORMAT_ARGB32, width, height, 1);
+    } else {
+        surface = fp_cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+                                                                 width, height);
+    }
+
+    cr = fp_cairo_create(surface);
+}
+
+/*
+ * Restore image from white and black pixmaps and copy it into destination
+ * buffer. This method compares two pixbufs taken from white and black
+ * pixmaps and decodes color and alpha components. Pixbufs are RGB without
+ * alpha, destination buffer is ABGR.
+ *
+ * The return value is the transparency type of the resulting image, either
+ * one of java_awt_Transparency_OPAQUE, java_awt_Transparency_BITMASK, and
+ * java_awt_Transparency_TRANSLUCENT.
+ */
+static gint gtk3_copy_image(gint *dst, gint width, gint height)
+{
+    gint i, j, r, g, b;
+    guchar *data;
+    gint stride, padding;
+
+    fp_cairo_surface_flush(surface);
+    data = (*fp_cairo_image_surface_get_data)(surface);
+    stride = (*fp_cairo_image_surface_get_stride)(surface);
+    padding = stride - width * 4;
+
+    for (i = 0; i < height; i++) {
+        for (j = 0; j < width; j++) {
+            int r = *data++;
+            int g = *data++;
+            int b = *data++;
+            int a = *data++;
+            *dst++ = (a << 24 | b << 16 | g << 8 | r);
+        }
+        data += padding;
+    }
+    return java_awt_Transparency_TRANSLUCENT;
+}
+
+static void gtk3_set_direction(GtkWidget *widget, GtkTextDirection dir)
+{
+    /*
+     * Some engines (inexplicably) look at the direction of the widget's
+     * parent, so we need to set the direction of both the widget and its
+     * parent.
+     */
+    (*fp_gtk_widget_set_direction)(widget, dir);
+    GtkWidget* parent = fp_gtk_widget_get_parent(widget);
+    if (parent != NULL) {
+        fp_gtk_widget_set_direction(parent, dir);
+    }
+}
+
+/* GTK state_type filter */
+static GtkStateType get_gtk_state_type(WidgetType widget_type, gint synth_state)
+{
+    GtkStateType result = GTK_STATE_NORMAL;
+
+    if ((synth_state & DISABLED) != 0) {
+        result = GTK_STATE_INSENSITIVE;
+    } else if ((synth_state & PRESSED) != 0) {
+        result = GTK_STATE_ACTIVE;
+    } else if ((synth_state & MOUSE_OVER) != 0) {
+        result = GTK_STATE_PRELIGHT;
+    }
+    return result;
+}
+
+static GtkStateFlags get_gtk_state_flags(gint synth_state)
+{
+    GtkStateFlags flags = 0;
+
+    if ((synth_state & DISABLED) != 0) {
+        flags |= GTK_STATE_FLAG_INSENSITIVE;
+    }
+    if (((synth_state & PRESSED) != 0 || (synth_state & SELECTED) != 0)) {
+        flags |= GTK_STATE_FLAG_ACTIVE;
+    }
+    if ((synth_state & MOUSE_OVER) != 0) {
+        flags |= GTK_STATE_FLAG_PRELIGHT;
+    }
+    if ((synth_state & FOCUSED) != 0) {
+        flags |= GTK_STATE_FLAG_FOCUSED;
+    }
+    return flags;
+}
+
+static GtkStateFlags get_gtk_flags(GtkStateType state_type) {
+    GtkStateFlags flags = 0;
+    switch (state_type)
+    {
+        case GTK_STATE_PRELIGHT:
+          flags |= GTK_STATE_FLAG_PRELIGHT;
+          break;
+        case GTK_STATE_SELECTED:
+          flags |= GTK_STATE_FLAG_SELECTED;
+          break;
+        case GTK_STATE_INSENSITIVE:
+          flags |= GTK_STATE_FLAG_INSENSITIVE;
+          break;
+        case GTK_STATE_ACTIVE:
+          flags |= GTK_STATE_FLAG_ACTIVE;
+          break;
+        case GTK_STATE_FOCUSED:
+          flags |= GTK_STATE_FLAG_FOCUSED;
+          break;
+        default:
+          break;
+    }
+    return flags;
+}
+
+/* GTK shadow_type filter */
+static GtkShadowType get_gtk_shadow_type(WidgetType widget_type,
+                                                               gint synth_state)
+{
+    GtkShadowType result = GTK_SHADOW_OUT;
+
+    if ((synth_state & SELECTED) != 0) {
+        result = GTK_SHADOW_IN;
+    }
+    return result;
+}
+
+
+static GtkWidget* gtk3_get_arrow(GtkArrowType arrow_type,
+                                                      GtkShadowType shadow_type)
+{
+    GtkWidget *arrow = NULL;
+    if (NULL == gtk3_widgets[_GTK_ARROW_TYPE])
+    {
+        gtk3_widgets[_GTK_ARROW_TYPE] = (*fp_gtk_arrow_new)(arrow_type,
+                                                                   shadow_type);
+        (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed,
+                                                 gtk3_widgets[_GTK_ARROW_TYPE]);
+        (*fp_gtk_widget_realize)(gtk3_widgets[_GTK_ARROW_TYPE]);
+    }
+    arrow = gtk3_widgets[_GTK_ARROW_TYPE];
+
+    (*fp_gtk_arrow_set)(arrow, arrow_type, shadow_type);
+    return arrow;
+}
+
+static GtkAdjustment* create_adjustment()
+{
+    return (GtkAdjustment *)
+            (*fp_gtk_adjustment_new)(50.0, 0.0, 100.0, 10.0, 20.0, 20.0);
+}
+
+/**
+ * Returns a pointer to the cached native widget for the specified widget
+ * type.
+ */
+static GtkWidget *gtk3_get_widget(WidgetType widget_type)
+{
+    gboolean init_result = FALSE;
+    GtkWidget *result = NULL;
+    switch (widget_type)
+    {
+        case BUTTON:
+        case TABLE_HEADER:
+            if (init_result = (NULL == gtk3_widgets[_GTK_BUTTON_TYPE]))
+            {
+                gtk3_widgets[_GTK_BUTTON_TYPE] = (*fp_gtk_button_new)();
+            }
+            result = gtk3_widgets[_GTK_BUTTON_TYPE];
+            break;
+        case CHECK_BOX:
+            if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_BUTTON_TYPE]))
+            {
+                gtk3_widgets[_GTK_CHECK_BUTTON_TYPE] =
+                    (*fp_gtk_check_button_new)();
+            }
+            result = gtk3_widgets[_GTK_CHECK_BUTTON_TYPE];
+            break;
+        case CHECK_BOX_MENU_ITEM:
+            if (init_result = (NULL == gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE]))
+            {
+                gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE] =
+                    (*fp_gtk_check_menu_item_new)();
+            }
+            result = gtk3_widgets[_GTK_CHECK_MENU_ITEM_TYPE];
+            break;
+        /************************************************************
+         *    Creation a dedicated color chooser is dangerous because
+         * it deadlocks the EDT
+         ************************************************************/
+/*        case COLOR_CHOOSER:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE]))
+            {
+                gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE] =
+                    (*fp_gtk_color_selection_dialog_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_COLOR_SELECTION_DIALOG_TYPE];
+            break;*/
+        case COMBO_BOX:
+            if (init_result = (NULL == gtk3_widgets[_GTK_COMBO_BOX_TYPE]))
+            {
+                gtk3_widgets[_GTK_COMBO_BOX_TYPE] =
+                    (*fp_gtk_combo_box_new)();
+            }
+            result = gtk3_widgets[_GTK_COMBO_BOX_TYPE];
+            break;
+        case COMBO_BOX_ARROW_BUTTON:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE]))
+            {
+                gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE] =
+                     (*fp_gtk_toggle_button_new)();
+            }
+            result = gtk3_widgets[_GTK_COMBO_BOX_ARROW_BUTTON_TYPE];
+            break;
+        case COMBO_BOX_TEXT_FIELD:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE]))
+            {
+                result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE] =
+                     (*fp_gtk_entry_new)();
+            }
+            result = gtk3_widgets[_GTK_COMBO_BOX_TEXT_FIELD_TYPE];
+            break;
+        case DESKTOP_ICON:
+        case INTERNAL_FRAME_TITLE_PANE:
+        case LABEL:
+            if (init_result = (NULL == gtk3_widgets[_GTK_LABEL_TYPE]))
+            {
+                gtk3_widgets[_GTK_LABEL_TYPE] =
+                    (*fp_gtk_label_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_LABEL_TYPE];
+            break;
+        case DESKTOP_PANE:
+        case PANEL:
+        case ROOT_PANE:
+            if (init_result = (NULL == gtk3_widgets[_GTK_CONTAINER_TYPE]))
+            {
+                /* There is no constructor for a container type.  I've
+                 * chosen GtkFixed container since it has a default
+                 * constructor.
+                 */
+                gtk3_widgets[_GTK_CONTAINER_TYPE] =
+                    (*fp_gtk_fixed_new)();
+            }
+            result = gtk3_widgets[_GTK_CONTAINER_TYPE];
+            break;
+        case EDITOR_PANE:
+        case TEXT_AREA:
+        case TEXT_PANE:
+            if (init_result = (NULL == gtk3_widgets[_GTK_TEXT_VIEW_TYPE]))
+            {
+                gtk3_widgets[_GTK_TEXT_VIEW_TYPE] =
+                    (*fp_gtk_text_view_new)();
+            }
+            result = gtk3_widgets[_GTK_TEXT_VIEW_TYPE];
+            break;
+        case FORMATTED_TEXT_FIELD:
+        case PASSWORD_FIELD:
+        case TEXT_FIELD:
+            if (init_result = (NULL == gtk3_widgets[_GTK_ENTRY_TYPE]))
+            {
+                gtk3_widgets[_GTK_ENTRY_TYPE] =
+                    (*fp_gtk_entry_new)();
+            }
+            result = gtk3_widgets[_GTK_ENTRY_TYPE];
+            break;
+        case HANDLE_BOX:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HANDLE_BOX_TYPE]))
+            {
+                gtk3_widgets[_GTK_HANDLE_BOX_TYPE] =
+                    (*fp_gtk_handle_box_new)();
+            }
+            result = gtk3_widgets[_GTK_HANDLE_BOX_TYPE];
+            break;
+        case HSCROLL_BAR:
+        case HSCROLL_BAR_BUTTON_LEFT:
+        case HSCROLL_BAR_BUTTON_RIGHT:
+        case HSCROLL_BAR_TRACK:
+        case HSCROLL_BAR_THUMB:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HSCROLLBAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_HSCROLLBAR_TYPE] =
+                    (*fp_gtk_hscrollbar_new)(create_adjustment());
+            }
+            result = gtk3_widgets[_GTK_HSCROLLBAR_TYPE];
+            break;
+        case HSEPARATOR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HSEPARATOR_TYPE]))
+            {
+                gtk3_widgets[_GTK_HSEPARATOR_TYPE] =
+                    (*fp_gtk_hseparator_new)();
+            }
+            result = gtk3_widgets[_GTK_HSEPARATOR_TYPE];
+            break;
+        case HSLIDER:
+        case HSLIDER_THUMB:
+        case HSLIDER_TRACK:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HSCALE_TYPE]))
+            {
+                gtk3_widgets[_GTK_HSCALE_TYPE] =
+                    (*fp_gtk_scale_new)(GTK_ORIENTATION_HORIZONTAL, NULL);
+            }
+            result = gtk3_widgets[_GTK_HSCALE_TYPE];
+            break;
+        case HSPLIT_PANE_DIVIDER:
+        case SPLIT_PANE:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HPANED_TYPE]))
+            {
+                gtk3_widgets[_GTK_HPANED_TYPE] = (*fp_gtk_hpaned_new)();
+            }
+            result = gtk3_widgets[_GTK_HPANED_TYPE];
+            break;
+        case IMAGE:
+            if (init_result = (NULL == gtk3_widgets[_GTK_IMAGE_TYPE]))
+            {
+                gtk3_widgets[_GTK_IMAGE_TYPE] = (*fp_gtk_image_new)();
+            }
+            result = gtk3_widgets[_GTK_IMAGE_TYPE];
+            break;
+        case INTERNAL_FRAME:
+            if (init_result = (NULL == gtk3_widgets[_GTK_WINDOW_TYPE]))
+            {
+                gtk3_widgets[_GTK_WINDOW_TYPE] =
+                    (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+            }
+            result = gtk3_widgets[_GTK_WINDOW_TYPE];
+            break;
+        case TOOL_TIP:
+            if (init_result = (NULL == gtk3_widgets[_GTK_TOOLTIP_TYPE]))
+            {
+                result = (*fp_gtk_window_new)(GTK_WINDOW_TOPLEVEL);
+                gtk3_widgets[_GTK_TOOLTIP_TYPE] = result;
+            }
+            result = gtk3_widgets[_GTK_TOOLTIP_TYPE];
+            break;
+        case LIST:
+        case TABLE:
+        case TREE:
+        case TREE_CELL:
+            if (init_result = (NULL == gtk3_widgets[_GTK_TREE_VIEW_TYPE]))
+            {
+                gtk3_widgets[_GTK_TREE_VIEW_TYPE] =
+                    (*fp_gtk_tree_view_new)();
+            }
+            result = gtk3_widgets[_GTK_TREE_VIEW_TYPE];
+            break;
+        case TITLED_BORDER:
+            if (init_result = (NULL == gtk3_widgets[_GTK_FRAME_TYPE]))
+            {
+                gtk3_widgets[_GTK_FRAME_TYPE] = fp_gtk_frame_new(NULL);
+            }
+            result = gtk3_widgets[_GTK_FRAME_TYPE];
+            break;
+        case POPUP_MENU:
+            if (init_result = (NULL == gtk3_widgets[_GTK_MENU_TYPE]))
+            {
+                gtk3_widgets[_GTK_MENU_TYPE] =
+                    (*fp_gtk_menu_new)();
+            }
+            result = gtk3_widgets[_GTK_MENU_TYPE];
+            break;
+        case MENU:
+        case MENU_ITEM:
+        case MENU_ITEM_ACCELERATOR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_MENU_ITEM_TYPE]))
+            {
+                gtk3_widgets[_GTK_MENU_ITEM_TYPE] =
+                    (*fp_gtk_menu_item_new)();
+            }
+            result = gtk3_widgets[_GTK_MENU_ITEM_TYPE];
+            break;
+        case MENU_BAR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_MENU_BAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_MENU_BAR_TYPE] =
+                    (*fp_gtk_menu_bar_new)();
+            }
+            result = gtk3_widgets[_GTK_MENU_BAR_TYPE];
+            break;
+        case COLOR_CHOOSER:
+        case OPTION_PANE:
+            if (init_result = (NULL == gtk3_widgets[_GTK_DIALOG_TYPE]))
+            {
+                gtk3_widgets[_GTK_DIALOG_TYPE] =
+                    (*fp_gtk_dialog_new)();
+            }
+            result = gtk3_widgets[_GTK_DIALOG_TYPE];
+            break;
+        case POPUP_MENU_SEPARATOR:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE]))
+            {
+                gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE] =
+                    (*fp_gtk_separator_menu_item_new)();
+            }
+            result = gtk3_widgets[_GTK_SEPARATOR_MENU_ITEM_TYPE];
+            break;
+        case HPROGRESS_BAR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE] =
+                    (*fp_gtk_progress_bar_new)();
+            }
+            result = gtk3_widgets[_GTK_HPROGRESS_BAR_TYPE];
+            break;
+        case VPROGRESS_BAR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE] =
+                    (*fp_gtk_progress_bar_new)();
+                /*
+                 * Vertical JProgressBars always go bottom-to-top,
+                 * regardless of the ComponentOrientation.
+                 */
+                (*fp_gtk_progress_bar_set_orientation)(
+                    (GtkProgressBar *)gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE],
+                    GTK_PROGRESS_BOTTOM_TO_TOP);
+            }
+            result = gtk3_widgets[_GTK_VPROGRESS_BAR_TYPE];
+            break;
+        case RADIO_BUTTON:
+            if (init_result = (NULL == gtk3_widgets[_GTK_RADIO_BUTTON_TYPE]))
+            {
+                gtk3_widgets[_GTK_RADIO_BUTTON_TYPE] =
+                    (*fp_gtk_radio_button_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_RADIO_BUTTON_TYPE];
+            break;
+        case RADIO_BUTTON_MENU_ITEM:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE]))
+            {
+                gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE] =
+                    (*fp_gtk_radio_menu_item_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_RADIO_MENU_ITEM_TYPE];
+            break;
+        case SCROLL_PANE:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE]))
+            {
+                gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE] =
+                    (*fp_gtk_scrolled_window_new)(NULL, NULL);
+            }
+            result = gtk3_widgets[_GTK_SCROLLED_WINDOW_TYPE];
+            break;
+        case SPINNER:
+        case SPINNER_ARROW_BUTTON:
+        case SPINNER_TEXT_FIELD:
+            if (init_result = (NULL == gtk3_widgets[_GTK_SPIN_BUTTON_TYPE]))
+            {
+                result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE] =
+                    (*fp_gtk_spin_button_new)(NULL, 0, 0);
+            }
+            result = gtk3_widgets[_GTK_SPIN_BUTTON_TYPE];
+            break;
+        case TABBED_PANE:
+        case TABBED_PANE_TAB_AREA:
+        case TABBED_PANE_CONTENT:
+        case TABBED_PANE_TAB:
+            if (init_result = (NULL == gtk3_widgets[_GTK_NOTEBOOK_TYPE]))
+            {
+                gtk3_widgets[_GTK_NOTEBOOK_TYPE] =
+                    (*fp_gtk_notebook_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_NOTEBOOK_TYPE];
+            break;
+        case TOGGLE_BUTTON:
+            if (init_result = (NULL == gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE]))
+            {
+                gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE] =
+                    (*fp_gtk_toggle_button_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_TOGGLE_BUTTON_TYPE];
+            break;
+        case TOOL_BAR:
+        case TOOL_BAR_DRAG_WINDOW:
+            if (init_result = (NULL == gtk3_widgets[_GTK_TOOLBAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_TOOLBAR_TYPE] =
+                    (*fp_gtk_toolbar_new)(NULL);
+            }
+            result = gtk3_widgets[_GTK_TOOLBAR_TYPE];
+            break;
+        case TOOL_BAR_SEPARATOR:
+            if (init_result =
+                    (NULL == gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE]))
+            {
+                gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE] =
+                    (*fp_gtk_separator_tool_item_new)();
+            }
+            result = gtk3_widgets[_GTK_SEPARATOR_TOOL_ITEM_TYPE];
+            break;
+        case VIEWPORT:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VIEWPORT_TYPE]))
+            {
+                GtkAdjustment *adjustment = create_adjustment();
+                gtk3_widgets[_GTK_VIEWPORT_TYPE] =
+                    (*fp_gtk_viewport_new)(adjustment, adjustment);
+            }
+            result = gtk3_widgets[_GTK_VIEWPORT_TYPE];
+            break;
+        case VSCROLL_BAR:
+        case VSCROLL_BAR_BUTTON_UP:
+        case VSCROLL_BAR_BUTTON_DOWN:
+        case VSCROLL_BAR_TRACK:
+        case VSCROLL_BAR_THUMB:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VSCROLLBAR_TYPE]))
+            {
+                gtk3_widgets[_GTK_VSCROLLBAR_TYPE] =
+                    (*fp_gtk_vscrollbar_new)(create_adjustment());
+            }
+            result = gtk3_widgets[_GTK_VSCROLLBAR_TYPE];
+            break;
+        case VSEPARATOR:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VSEPARATOR_TYPE]))
+            {
+                gtk3_widgets[_GTK_VSEPARATOR_TYPE] =
+                    (*fp_gtk_vseparator_new)();
+            }
+            result = gtk3_widgets[_GTK_VSEPARATOR_TYPE];
+            break;
+        case VSLIDER:
+        case VSLIDER_THUMB:
+        case VSLIDER_TRACK:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VSCALE_TYPE]))
+            {
+                gtk3_widgets[_GTK_VSCALE_TYPE] =
+                    (*fp_gtk_scale_new)(GTK_ORIENTATION_VERTICAL, NULL);
+            }
+            result = gtk3_widgets[_GTK_VSCALE_TYPE];
+            /*
+             * Vertical JSliders start at the bottom, while vertical
+             * GtkVScale widgets start at the top (by default), so to fix
+             * this we set the "inverted" flag to get the Swing behavior.
+             */
+             fp_gtk_range_set_inverted((GtkRange*)result, TRUE);
+            break;
+        case VSPLIT_PANE_DIVIDER:
+            if (init_result = (NULL == gtk3_widgets[_GTK_VPANED_TYPE]))
+            {
+                gtk3_widgets[_GTK_VPANED_TYPE] = (*fp_gtk_vpaned_new)();
+            }
+            result = gtk3_widgets[_GTK_VPANED_TYPE];
+            break;
+        default:
+            result = NULL;
+            break;
+    }
+
+    if (result != NULL && init_result)
+    {
+        if (widget_type == RADIO_BUTTON_MENU_ITEM ||
+                widget_type == CHECK_BOX_MENU_ITEM ||
+                widget_type == MENU_ITEM ||
+                widget_type == MENU ||
+                widget_type == POPUP_MENU_SEPARATOR)
+        {
+            GtkWidget *menu = gtk3_get_widget(POPUP_MENU);
+            (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu, result);
+        }
+        else if (widget_type == POPUP_MENU)
+        {
+            GtkWidget *menu_bar = gtk3_get_widget(MENU_BAR);
+            GtkWidget *root_menu = (*fp_gtk_menu_item_new)();
+            (*fp_gtk_menu_item_set_submenu)((GtkMenuItem*)root_menu, result);
+            (*fp_gtk_menu_shell_append)((GtkMenuShell *)menu_bar, root_menu);
+        }
+        else if (widget_type == COMBO_BOX_TEXT_FIELD )
+        {
+            GtkWidget* combo = gtk3_get_widget(COMBO_BOX);
+
+            /*
+            * We add a regular GtkButton/GtkEntry to a GtkComboBoxEntry
+            * in order to trick engines into thinking it's a real combobox
+            * arrow button/text field.
+            */
+
+            fp_gtk_container_add ((GtkContainer*)(combo), result);
+            GtkStyleContext* context = fp_gtk_widget_get_style_context (combo);
+            fp_gtk_style_context_add_class (context, "combobox-entry");
+            context = fp_gtk_widget_get_style_context (result);
+            fp_gtk_style_context_add_class (context, "combobox");
+            fp_gtk_style_context_add_class (context, "entry");
+        }
+        else if (widget_type == COMBO_BOX_ARROW_BUTTON )
+        {
+            GtkWidget* combo = gtk3_get_widget(COMBO_BOX);
+            fp_gtk_widget_set_parent(result, combo);
+        }
+        else if (widget_type != TOOL_TIP &&
+                 widget_type != INTERNAL_FRAME &&
+                 widget_type != OPTION_PANE)
+        {
+            (*fp_gtk_container_add)((GtkContainer *)gtk3_fixed, result);
+        }
+        (*fp_gtk_widget_realize)(result);
+    }
+    return result;
+}
+
+static void gtk3_paint_arrow(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height,
+        GtkArrowType arrow_type, gboolean fill)
+{
+    gdouble xx, yy, a = G_PI;
+    int s = width;
+    gtk3_widget = gtk3_get_arrow(arrow_type, shadow_type);
+
+    switch (widget_type)
+    {
+        case SPINNER_ARROW_BUTTON:
+            s = (int)(0.4 * width + 0.5) + 1;
+            if (arrow_type == GTK_ARROW_UP) {
+                a = 0;
+            } else if (arrow_type == GTK_ARROW_DOWN) {
+                a = G_PI;
+            }
+            break;
+
+        case HSCROLL_BAR_BUTTON_LEFT:
+            s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;
+            a = 3 * G_PI / 2;
+            break;
+
+        case HSCROLL_BAR_BUTTON_RIGHT:
+            s = (int)(0.5 * MIN(height, width * 2) + 0.5) + 1;
+            a = G_PI / 2;
+            break;
+
+        case VSCROLL_BAR_BUTTON_UP:
+            s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;
+            a = 0;
+            break;
+
+        case VSCROLL_BAR_BUTTON_DOWN:
+            s = (int)(0.5 * MIN(height * 2, width) + 0.5) + 1;
+            a = G_PI;
+            break;
+
+        case COMBO_BOX_ARROW_BUTTON:
+            s = (int)(0.3 * height + 0.5) + 1;
+            a = G_PI;
+            break;
+
+        case TABLE:
+            s = (int)(0.8 * height + 0.5) + 1;
+            if (arrow_type == GTK_ARROW_UP) {
+                a = G_PI;
+            } else if (arrow_type == GTK_ARROW_DOWN) {
+                a = 0;
+            }
+            break;
+
+        case MENU_ITEM:
+            if (arrow_type == GTK_ARROW_UP) {
+                a = G_PI;
+            } else if (arrow_type == GTK_ARROW_DOWN) {
+                a = 0;
+            } else if (arrow_type == GTK_ARROW_RIGHT) {
+                a = G_PI / 2;
+            } else if (arrow_type == GTK_ARROW_LEFT) {
+                a = 3 * G_PI / 2;
+            }
+            break;
+
+        default:
+            if (arrow_type == GTK_ARROW_UP) {
+                a = G_PI;
+            } else if (arrow_type == GTK_ARROW_DOWN) {
+                a = 0;
+            } else if (arrow_type == GTK_ARROW_RIGHT) {
+                a = G_PI / 2;
+            } else if (arrow_type == GTK_ARROW_LEFT) {
+                a = 3 * G_PI / 2;
+            }
+            break;
+    }
+
+    if (s < width && s < height) {
+        xx = x + (0.5 * (width - s) + 0.5);
+        yy = y + (0.5 * (height - s) + 0.5);
+    } else {
+        xx = x;
+        yy = y;
+    }
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    fp_gtk_style_context_save (context);
+
+
+    if (detail != NULL) {
+        transform_detail_string(detail, context);
+    }
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    (*fp_gtk_render_arrow)(context, cr, a, xx, yy, s);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_box(WidgetType widget_type, GtkStateType state_type,
+                    GtkShadowType shadow_type, const gchar *detail,
+                    gint x, gint y, gint width, gint height,
+                    gint synth_state, GtkTextDirection dir)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    if (widget_type == HSLIDER_TRACK) {
+        /*
+         * For horizontal JSliders with right-to-left orientation, we need
+         * to set the "inverted" flag to match the native GTK behavior where
+         * the foreground highlight is on the right side of the slider thumb.
+         * This is needed especially for the ubuntulooks engine, which looks
+         * exclusively at the "inverted" flag to determine on which side of
+         * the thumb to paint the highlight...
+         */
+        fp_gtk_range_set_inverted((GtkRange*)gtk3_widget, dir ==
+                                                              GTK_TEXT_DIR_RTL);
+
+        /*
+         * Note however that other engines like clearlooks will look at both
+         * the "inverted" field and the text direction to determine how
+         * the foreground highlight is painted:
+         *     !inverted && ltr --> paint highlight on left side
+         *     !inverted && rtl --> paint highlight on right side
+         *      inverted && ltr --> paint highlight on right side
+         *      inverted && rtl --> paint highlight on left side
+         * So the only way to reliably get the desired results for horizontal
+         * JSlider (i.e., highlight on left side for LTR ComponentOrientation
+         * and highlight on right side for RTL ComponentOrientation) is to
+         * always override text direction as LTR, and then set the "inverted"
+         * flag accordingly (as we have done above).
+         */
+        dir = GTK_TEXT_DIR_LTR;
+    }
+
+    /*
+     * Some engines (e.g. clearlooks) will paint the shadow of certain
+     * widgets (e.g. COMBO_BOX_ARROW_BUTTON) differently depending on the
+     * the text direction.
+     */
+    gtk3_set_direction(gtk3_widget, dir);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    fp_gtk_style_context_save (context);
+
+    transform_detail_string(detail, context);
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    if (shadow_type == GTK_SHADOW_IN && widget_type != COMBO_BOX_ARROW_BUTTON) {
+        flags |= GTK_STATE_FLAG_ACTIVE;
+    }
+
+    if (synth_state & MOUSE_OVER) {
+        flags |= GTK_STATE_FLAG_PRELIGHT;
+    }
+
+    if (synth_state & FOCUSED) {
+        flags |= GTK_STATE_FLAG_FOCUSED;
+    }
+
+    if (synth_state & DEFAULT) {
+        fp_gtk_style_context_add_class (context, "default");
+    }
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    if (fp_gtk_style_context_has_class(context, "progressbar")) {
+        fp_gtk_render_activity (context, cr, x, y, width, height);
+    } else {
+        fp_gtk_render_background (context, cr, x, y, width, height);
+        if (shadow_type != GTK_SHADOW_NONE) {
+            fp_gtk_render_frame(context, cr, x, y, width, height);
+        }
+    }
+
+    fp_gtk_style_context_restore (context);
+    /*
+     * Reset the text direction to the default value so that we don't
+     * accidentally affect other operations and widgets.
+     */
+    gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);
+}
+
+static void gtk3_paint_box_gap(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height,
+        GtkPositionType gap_side, gint gap_x, gint gap_width)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+    fp_gtk_style_context_set_state(context, flags);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+    fp_gtk_render_background(context, cr, x, y, width, height);
+
+    if (shadow_type != GTK_SHADOW_NONE) {
+        fp_gtk_render_frame_gap(context, cr, x, y, width, height, gap_side,
+                                    (gdouble)gap_x, (gdouble)gap_x + gap_width);
+    }
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_check(WidgetType widget_type, gint synth_state,
+        const gchar *detail, gint x, gint y, gint width, gint height)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = get_gtk_state_flags(synth_state);
+    if (gtk3_version_3_14 && (synth_state & SELECTED)) {
+        flags = GTK_STATE_FLAG_CHECKED;
+    }
+    fp_gtk_style_context_set_state(context, flags);
+
+    fp_gtk_style_context_add_class (context, "check");
+
+    fp_gtk_render_check (context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+
+static void gtk3_paint_expander(WidgetType widget_type, GtkStateType state_type,
+        const gchar *detail, gint x, gint y, gint width, gint height,
+        GtkExpanderStyle expander_style)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+    fp_gtk_style_context_set_state(context, flags);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+
+    fp_gtk_render_expander (context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_extension(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height, GtkPositionType gap_side)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = GTK_STATE_FLAG_NORMAL;
+
+    if (state_type == 0) {
+        flags = GTK_STATE_FLAG_ACTIVE;
+    }
+
+    fp_gtk_style_context_set_state(context, flags);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+    switch(gap_side) {
+      case GTK_POS_LEFT:
+        fp_gtk_style_context_add_class(context, "right");
+        break;
+      case GTK_POS_RIGHT:
+        fp_gtk_style_context_add_class(context, "left");
+        break;
+      case GTK_POS_TOP:
+        fp_gtk_style_context_add_class(context, "bottom");
+        break;
+      case GTK_POS_BOTTOM:
+        fp_gtk_style_context_add_class(context, "top");
+        break;
+      default:
+        break;
+    }
+
+    fp_gtk_render_extension(context, cr, x, y, width, height, gap_side);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_flat_box(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height, gboolean has_focus)
+{
+    if (state_type == GTK_STATE_PRELIGHT &&
+        (widget_type == CHECK_BOX || widget_type == RADIO_BUTTON)) {
+        return;
+    }
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    if (has_focus) {
+        flags |= GTK_STATE_FLAG_FOCUSED;
+    }
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    if (widget_type == COMBO_BOX_TEXT_FIELD) {
+        width += height /2;
+    }
+
+    fp_gtk_render_background (context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_focus(WidgetType widget_type, GtkStateType state_type,
+        const char *detail, gint x, gint y, gint width, gint height)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    fp_gtk_style_context_save (context);
+
+    transform_detail_string(detail, context);
+    fp_gtk_render_focus (context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+
+}
+
+static void gtk3_paint_handle(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height, GtkOrientation orientation)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+    fp_gtk_style_context_set_state(context, GTK_STATE_FLAG_PRELIGHT);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+        fp_gtk_style_context_add_class (context, "handlebox_bin");
+    }
+
+    fp_gtk_render_handle(context, cr, x, y, width, height);
+    fp_gtk_render_background(context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_hline(WidgetType widget_type, GtkStateType state_type,
+        const gchar *detail, gint x, gint y, gint width, gint height)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+
+    fp_gtk_render_line(context, cr, x, y, x + width, y);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_vline(WidgetType widget_type, GtkStateType state_type,
+        const gchar *detail, gint x, gint y, gint width, gint height)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    if (detail != 0) {
+        transform_detail_string(detail, context);
+    }
+
+    fp_gtk_render_line(context, cr, x, y, x, y + height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_option(WidgetType widget_type, gint synth_state,
+        const gchar *detail, gint x, gint y, gint width, gint height)
+{
+     gtk3_widget = gtk3_get_widget(widget_type);
+
+     GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+     fp_gtk_style_context_save (context);
+
+     GtkStateFlags flags = get_gtk_state_flags(synth_state);
+     if (gtk3_version_3_14 && (synth_state & SELECTED)) {
+         flags = GTK_STATE_FLAG_CHECKED;
+     }
+     fp_gtk_style_context_set_state(context, flags);
+
+     if (detail != 0) {
+         transform_detail_string(detail, context);
+     }
+
+     fp_gtk_render_option(context, cr, x, y, width, height);
+
+     fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_shadow(WidgetType widget_type, GtkStateType state_type,
+                       GtkShadowType shadow_type, const gchar *detail,
+                       gint x, gint y, gint width, gint height,
+                       gint synth_state, GtkTextDirection dir)
+{
+    if (shadow_type == GTK_SHADOW_NONE) {
+        return;
+    }
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    /*
+     * Some engines (e.g. clearlooks) will paint the shadow of certain
+     * widgets (e.g. COMBO_BOX_TEXT_FIELD) differently depending on the
+     * the text direction.
+     */
+    gtk3_set_direction(gtk3_widget, dir);
+
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    fp_gtk_style_context_save (context);
+
+    if (detail) {
+        transform_detail_string(detail, context);
+    }
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    if (synth_state & MOUSE_OVER) {
+        flags |= GTK_STATE_FLAG_PRELIGHT;
+    }
+
+    if (synth_state & FOCUSED) {
+        flags |= GTK_STATE_FLAG_FOCUSED;
+    }
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    if (widget_type == COMBO_BOX_TEXT_FIELD) {
+        width += height / 2;
+    }
+    fp_gtk_render_frame(context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+
+    /*
+     * Reset the text direction to the default value so that we don't
+     * accidentally affect other operations and widgets.
+     */
+    gtk3_set_direction(gtk3_widget, GTK_TEXT_DIR_LTR);
+}
+
+static void gtk3_paint_slider(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height, GtkOrientation orientation,
+        gboolean has_focus)
+{
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+
+    fp_gtk_style_context_save (context);
+
+    if (detail) {
+       transform_detail_string(detail, context);
+    }
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    if (state_type == GTK_STATE_ACTIVE) {
+        flags |= GTK_STATE_FLAG_PRELIGHT;
+    }
+
+    if (has_focus) {
+        flags |= GTK_STATE_FLAG_FOCUSED;
+    }
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    (*fp_gtk_render_slider)(context, cr, x, y, width, height, orientation);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static void gtk3_paint_background(WidgetType widget_type,
+             GtkStateType state_type, gint x, gint y, gint width, gint height) {
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    fp_gtk_style_context_save (context);
+
+    GtkStateFlags flags = get_gtk_flags(state_type);
+
+    fp_gtk_style_context_set_state (context, flags);
+
+    fp_gtk_render_background (context, cr, x, y, width, height);
+
+    fp_gtk_style_context_restore (context);
+}
+
+static GdkPixbuf *gtk3_get_stock_icon(gint widget_type, const gchar *stock_id,
+        GtkIconSize size, GtkTextDirection direction, const char *detail)
+{
+    int sz;
+
+    switch(size) {
+      case GTK_ICON_SIZE_MENU:
+        sz = 16;
+        break;
+      case GTK_ICON_SIZE_SMALL_TOOLBAR:
+        sz = 18;
+        break;
+      case GTK_ICON_SIZE_LARGE_TOOLBAR:
+        sz = 24;
+        break;
+      case GTK_ICON_SIZE_BUTTON:
+        sz = 20;
+        break;
+      case GTK_ICON_SIZE_DND:
+        sz = 32;
+        break;
+      case GTK_ICON_SIZE_DIALOG:
+        sz = 48;
+        break;
+      default:
+        sz = 0;
+        break;
+    }
+
+    init_containers();
+    gtk3_widget = gtk3_get_widget((widget_type < 0) ? IMAGE : widget_type);
+    (*fp_gtk_widget_set_direction)(gtk3_widget, direction);
+    GtkIconTheme *icon_theme = fp_gtk_icon_theme_get_default();
+    GdkPixbuf *result = fp_gtk_icon_theme_load_icon(icon_theme, stock_id, sz,
+                                             GTK_ICON_LOOKUP_USE_BUILTIN, NULL);
+    return result;
+}
+
+static jboolean gtk3_get_pixbuf_data(JNIEnv *env, GdkPixbuf* pixbuf,
+                              jmethodID icon_upcall_method, jobject this) {
+    if (!pixbuf) {
+        return JNI_FALSE;
+    }
+    guchar *pixbuf_data = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+    if (pixbuf_data) {
+        int row_stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+        int width = (*fp_gdk_pixbuf_get_width)(pixbuf);
+        int height = (*fp_gdk_pixbuf_get_height)(pixbuf);
+        int bps = (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf);
+        int channels = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+        gboolean alpha = (*fp_gdk_pixbuf_get_has_alpha)(pixbuf);
+
+        jbyteArray data = (*env)->NewByteArray(env, (row_stride * height));
+        JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
+
+        (*env)->SetByteArrayRegion(env, data, 0, (row_stride * height),
+                                   (jbyte *)pixbuf_data);
+        (*fp_g_object_unref)(pixbuf);
+
+        /* Call the callback method to create the image on the Java side. */
+        (*env)->CallVoidMethod(env, this, icon_upcall_method, data,
+                width, height, row_stride, bps, channels, alpha);
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+static jboolean gtk3_get_file_icon_data(JNIEnv *env, const char *filename,
+                 GError **error, jmethodID icon_upcall_method, jobject this) {
+    GdkPixbuf* pixbuf = fp_gdk_pixbuf_new_from_file(filename, error);
+    return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+static jboolean gtk3_get_icon_data(JNIEnv *env, gint widget_type,
+                              const gchar *stock_id, GtkIconSize size,
+                              GtkTextDirection direction, const char *detail,
+                              jmethodID icon_upcall_method, jobject this) {
+    GdkPixbuf* pixbuf = gtk3_get_stock_icon(widget_type, stock_id, size,
+                                       direction, detail);
+    return gtk3_get_pixbuf_data(env, pixbuf, icon_upcall_method, this);
+}
+
+/*************************************************/
+static gint gtk3_get_xthickness(JNIEnv *env, WidgetType widget_type)
+{
+    init_containers();
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    if (context) {
+        GtkBorder padding;
+        fp_gtk_style_context_get_padding(context, 0, &padding);
+        return padding.left + 1;
+    }
+    return 0;
+}
+
+static gint gtk3_get_ythickness(JNIEnv *env, WidgetType widget_type)
+{
+    init_containers();
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    if (context) {
+        GtkBorder padding;
+        fp_gtk_style_context_get_padding(context, 0, &padding);
+        return padding.top + 1;
+    }
+    return 0;
+}
+
+/*************************************************/
+static guint8 recode_color(gdouble channel)
+{
+    guint16 result = (guint16)(channel * 65535);
+    if (result < 0) {
+        result = 0;
+    } else if (result > 65535) {
+        result = 65535;
+    }
+    return (guint8)( result >> 8);
+}
+
+static GtkStateFlags gtk3_get_state_flags(GtkStateType state_type) {
+    switch (state_type)
+    {
+        case GTK_STATE_NORMAL:
+            return GTK_STATE_FLAG_NORMAL;
+        case GTK_STATE_ACTIVE:
+            return GTK_STATE_FLAG_ACTIVE;
+        case GTK_STATE_PRELIGHT:
+            return GTK_STATE_FLAG_PRELIGHT;
+        case GTK_STATE_SELECTED:
+            return GTK_STATE_FLAG_SELECTED;
+        case GTK_STATE_INSENSITIVE:
+            return GTK_STATE_FLAG_INSENSITIVE;
+        case GTK_STATE_INCONSISTENT:
+            return GTK_STATE_FLAG_INCONSISTENT;
+        case GTK_STATE_FOCUSED:
+            return GTK_STATE_FLAG_FOCUSED;
+    }
+    return 0;
+}
+
+
+static void rgb_to_hls (gdouble *r, gdouble *g, gdouble *b) {
+  gdouble min;
+  gdouble max;
+  gdouble red;
+  gdouble green;
+  gdouble blue;
+  gdouble h, l, s;
+  gdouble delta;
+
+  red = *r;
+  green = *g;
+  blue = *b;
+
+  if (red > green)
+    {
+      if (red > blue)
+        max = red;
+      else
+        max = blue;
+
+      if (green < blue)
+        min = green;
+      else
+        min = blue;
+    }
+  else
+    {
+      if (green > blue)
+        max = green;
+      else
+        max = blue;
+
+      if (red < blue)
+        min = red;
+      else
+        min = blue;
+    }
+
+  l = (max + min) / 2;
+  s = 0;
+  h = 0;
+
+  if (max != min)
+    {
+      if (l <= 0.5)
+        s = (max - min) / (max + min);
+      else
+        s = (max - min) / (2 - max - min);
+
+      delta = max -min;
+      if (red == max)
+        h = (green - blue) / delta;
+      else if (green == max)
+        h = 2 + (blue - red) / delta;
+      else if (blue == max)
+        h = 4 + (red - green) / delta;
+
+      h *= 60;
+      if (h < 0.0)
+        h += 360;
+    }
+
+  *r = h;
+  *g = l;
+  *b = s;
+}
+
+static void hls_to_rgb (gdouble *h, gdouble *l, gdouble *s)
+{
+  gdouble hue;
+  gdouble lightness;
+  gdouble saturation;
+  gdouble m1, m2;
+  gdouble r, g, b;
+
+  lightness = *l;
+  saturation = *s;
+
+  if (lightness <= 0.5)
+    m2 = lightness * (1 + saturation);
+  else
+    m2 = lightness + saturation - lightness * saturation;
+  m1 = 2 * lightness - m2;
+
+  if (saturation == 0)
+    {
+      *h = lightness;
+      *l = lightness;
+      *s = lightness;
+    }
+  else
+    {
+      hue = *h + 120;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+
+      if (hue < 60)
+        r = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        r = m2;
+      else if (hue < 240)
+        r = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        r = m1;
+
+      hue = *h;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+
+      if (hue < 60)
+        g = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        g = m2;
+      else if (hue < 240)
+        g = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        g = m1;
+
+      hue = *h - 120;
+      while (hue > 360)
+        hue -= 360;
+      while (hue < 0)
+        hue += 360;
+
+      if (hue < 60)
+        b = m1 + (m2 - m1) * hue / 60;
+      else if (hue < 180)
+        b = m2;
+      else if (hue < 240)
+        b = m1 + (m2 - m1) * (240 - hue) / 60;
+      else
+        b = m1;
+
+      *h = r;
+      *l = g;
+      *s = b;
+    }
+}
+
+
+
+static void gtk3_style_shade (const GdkRGBA *a, GdkRGBA *b, gdouble k) {
+  gdouble red = a->red;
+  gdouble green = a->green;
+  gdouble blue = a->blue;
+
+  rgb_to_hls (&red, &green, &blue);
+
+  green *= k;
+  if (green > 1.0)
+    green = 1.0;
+  else if (green < 0.0)
+    green = 0.0;
+
+  blue *= k;
+  if (blue > 1.0)
+    blue = 1.0;
+  else if (blue < 0.0)
+    blue = 0.0;
+
+  hls_to_rgb (&red, &green, &blue);
+
+  b->red = red;
+  b->green = green;
+  b->blue = blue;
+}
+
+static GdkRGBA gtk3_get_color_for_flags(GtkStyleContext* context,
+                                  GtkStateFlags flags, ColorType color_type) {
+    GdkRGBA c, color;
+
+    switch (color_type)
+    {
+        case FOREGROUND:
+        case TEXT_FOREGROUND:
+            fp_gtk_style_context_get_color(context, flags, &color);
+            break;
+        case BACKGROUND:
+        case TEXT_BACKGROUND:
+            fp_gtk_style_context_get_background_color(context, flags, &color);
+            break;
+        case LIGHT:
+            c = gtk3_get_color_for_flags(context, flags, BACKGROUND);
+            gtk3_style_shade(&c, &color, LIGHTNESS_MULT);
+            break;
+        case DARK:
+            c = gtk3_get_color_for_flags(context, flags, BACKGROUND);
+            gtk3_style_shade (&c, &color, DARKNESS_MULT);
+            break;
+        case MID:
+            {
+                GdkRGBA c1 = gtk3_get_color_for_flags(context, flags, LIGHT);
+                GdkRGBA c2 = gtk3_get_color_for_flags(context, flags, DARK);
+                color.red = (c1.red + c2.red) / 2;
+                color.green = (c1.green + c2.green) / 2;
+                color.blue = (c1.blue + c2.blue) / 2;
+            }
+            break;
+        case FOCUS:
+        case BLACK:
+            color.red = 0;
+            color.green = 0;
+            color.blue = 0;
+            break;
+        case WHITE:
+            color.red = 1;
+            color.green = 1;
+            color.blue = 1;
+            break;
+    }
+    return color;
+}
+
+static gint gtk3_get_color_for_state(JNIEnv *env, WidgetType widget_type,
+                              GtkStateType state_type, ColorType color_type)
+{
+
+    gint result = 0;
+    GdkRGBA color;
+
+    GtkStateFlags flags = gtk3_get_state_flags(state_type);
+
+    init_containers();
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GtkStyleContext* context = fp_gtk_widget_get_style_context(gtk3_widget);
+
+    if (widget_type == TOOL_TIP) {
+        fp_gtk_style_context_add_class(context, "tooltip");
+    }
+    if (widget_type == CHECK_BOX_MENU_ITEM
+     || widget_type == RADIO_BUTTON_MENU_ITEM) {
+        flags &= GTK_STATE_FLAG_NORMAL | GTK_STATE_FLAG_SELECTED
+                  | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED;
+    }
+
+    color = gtk3_get_color_for_flags(context, flags, color_type);
+
+    if (recode_color(color.alpha) == 0) {
+        color = gtk3_get_color_for_flags(
+        fp_gtk_widget_get_style_context(gtk3_get_widget(INTERNAL_FRAME)),
+        0, BACKGROUND);
+    }
+
+    result = recode_color(color.alpha) << 24 | recode_color(color.red) << 16 |
+             recode_color(color.green) << 8 | recode_color(color.blue);
+
+    return result;
+}
+
+/*************************************************/
+static jobject create_Boolean(JNIEnv *env, jboolean boolean_value);
+static jobject create_Integer(JNIEnv *env, jint int_value);
+static jobject create_Long(JNIEnv *env, jlong long_value);
+static jobject create_Float(JNIEnv *env, jfloat float_value);
+static jobject create_Double(JNIEnv *env, jdouble double_value);
+static jobject create_Character(JNIEnv *env, jchar char_value);
+static jobject create_Insets(JNIEnv *env, GtkBorder *border);
+
+static jobject gtk3_get_class_value(JNIEnv *env, WidgetType widget_type,
+                                                     const char* key)
+{
+    init_containers();
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    GValue value = { 0, { { 0 } } };
+
+    GParamSpec* param = (*fp_gtk_widget_class_find_style_property)(
+                                    ((GTypeInstance*)gtk3_widget)->g_class, key);
+    if ( param )
+    {
+        (*fp_g_value_init)( &value, param->value_type );
+        (*fp_gtk_widget_style_get_property)(gtk3_widget, key, &value);
+
+        if ((*fp_g_type_is_a)( param->value_type, G_TYPE_BOOLEAN ))
+        {
+            gboolean val = (*fp_g_value_get_boolean)(&value);
+            return create_Boolean(env, (jboolean)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_CHAR ))
+        {
+            gchar val = (*fp_g_value_get_char)(&value);
+            return create_Character(env, (jchar)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UCHAR ))
+        {
+            guchar val = (*fp_g_value_get_uchar)(&value);
+            return create_Character(env, (jchar)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT ))
+        {
+            gint val = (*fp_g_value_get_int)(&value);
+            return create_Integer(env, (jint)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT ))
+        {
+            guint val = (*fp_g_value_get_uint)(&value);
+                    return create_Integer(env, (jint)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_LONG ))
+        {
+            glong val = (*fp_g_value_get_long)(&value);
+            return create_Long(env, (jlong)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ULONG ))
+        {
+            gulong val = (*fp_g_value_get_ulong)(&value);
+            return create_Long(env, (jlong)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_INT64 ))
+        {
+            gint64 val = (*fp_g_value_get_int64)(&value);
+            return create_Long(env, (jlong)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_UINT64 ))
+        {
+            guint64 val = (*fp_g_value_get_uint64)(&value);
+            return create_Long(env, (jlong)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLOAT ))
+        {
+            gfloat val = (*fp_g_value_get_float)(&value);
+            return create_Float(env, (jfloat)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_DOUBLE ))
+        {
+            gdouble val = (*fp_g_value_get_double)(&value);
+            return create_Double(env, (jdouble)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_ENUM ))
+        {
+            gint val = (*fp_g_value_get_enum)(&value);
+            return create_Integer(env, (jint)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_FLAGS ))
+        {
+            guint val = (*fp_g_value_get_flags)(&value);
+            return create_Integer(env, (jint)val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, G_TYPE_STRING ))
+        {
+            const gchar* val = (*fp_g_value_get_string)(&value);
+
+            /* We suppose that all values come in C locale and
+             * utf-8 representation of a string is the same as
+             * the string itself. If this isn't so we should
+             * use g_convert.
+             */
+            return (*env)->NewStringUTF(env, val);
+        }
+        else if ((*fp_g_type_is_a)( param->value_type, GTK_TYPE_BORDER ))
+        {
+            GtkBorder *border = (GtkBorder*)(*fp_g_value_get_boxed)(&value);
+            return border ? create_Insets(env, border) : NULL;
+        }
+
+        /*      TODO: Other types are not supported yet.*/
+/*        else if((*fp_g_type_is_a)( param->value_type, G_TYPE_PARAM ))
+        {
+            GParamSpec* val = (*fp_g_value_get_param)(&value);
+            printf( "Param: %p\n", val );
+        }
+        else if((*fp_g_type_is_a)( param->value_type, G_TYPE_BOXED ))
+        {
+            gpointer* val = (*fp_g_value_get_boxed)(&value);
+            printf( "Boxed: %p\n", val );
+        }
+        else if((*fp_g_type_is_a)( param->value_type, G_TYPE_POINTER ))
+        {
+            gpointer* val = (*fp_g_value_get_pointer)(&value);
+            printf( "Pointer: %p\n", val );
+        }
+        else if((*fp_g_type_is_a)( param->value_type, G_TYPE_OBJECT ))
+        {
+            GObject* val = (GObject*)(*fp_g_value_get_object)(&value);
+            printf( "Object: %p\n", val );
+        }*/
+    }
+
+    return NULL;
+}
+
+static void gtk3_set_range_value(WidgetType widget_type, jdouble value,
+                          jdouble min, jdouble max, jdouble visible)
+{
+    GtkAdjustment *adj;
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+
+    adj = (*fp_gtk_range_get_adjustment)((GtkRange *)gtk3_widget);
+
+    fp_gtk_adjustment_set_value(adj, value);
+    fp_gtk_adjustment_set_lower(adj, min);
+    fp_gtk_adjustment_set_upper(adj, max);
+    fp_gtk_adjustment_set_page_size(adj, visible);
+}
+
+/*************************************************/
+static jobject create_Object(JNIEnv *env, jmethodID *cid,
+                             const char* class_name,
+                             const char* signature,
+                             jvalue* value)
+{
+    jclass  class;
+    jobject result;
+
+    class = (*env)->FindClass(env, class_name);
+    if (class == NULL)
+        return NULL; /* can't find/load the class, exception thrown */
+
+    if (*cid == NULL)
+    {
+        *cid = (*env)->GetMethodID(env, class, "<init>", signature);
+        if (*cid == NULL)
+        {
+            (*env)->DeleteLocalRef(env, class);
+            return NULL; /* can't find/get the method, exception thrown */
+        }
+    }
+
+    result = (*env)->NewObjectA(env, class, *cid, value);
+
+    (*env)->DeleteLocalRef(env, class);
+    return result;
+}
+
+jobject create_Boolean(JNIEnv *env, jboolean boolean_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.z = boolean_value;
+
+    return create_Object(env, &cid, "java/lang/Boolean", "(Z)V", &value);
+}
+
+jobject create_Integer(JNIEnv *env, jint int_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.i = int_value;
+
+    return create_Object(env, &cid, "java/lang/Integer", "(I)V", &value);
+}
+
+jobject create_Long(JNIEnv *env, jlong long_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.j = long_value;
+
+    return create_Object(env, &cid, "java/lang/Long", "(J)V", &value);
+}
+
+jobject create_Float(JNIEnv *env, jfloat float_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.f = float_value;
+
+    return create_Object(env, &cid, "java/lang/Float", "(F)V", &value);
+}
+
+jobject create_Double(JNIEnv *env, jdouble double_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.d = double_value;
+
+    return create_Object(env, &cid, "java/lang/Double", "(D)V", &value);
+}
+
+jobject create_Character(JNIEnv *env, jchar char_value)
+{
+    static jmethodID cid = NULL;
+    jvalue value;
+
+    value.c = char_value;
+
+    return create_Object(env, &cid, "java/lang/Character", "(C)V", &value);
+}
+
+
+jobject create_Insets(JNIEnv *env, GtkBorder *border)
+{
+    static jmethodID cid = NULL;
+    jvalue values[4];
+
+    values[0].i = border->top;
+    values[1].i = border->left;
+    values[2].i = border->bottom;
+    values[3].i = border->right;
+
+    return create_Object(env, &cid, "java/awt/Insets", "(IIII)V", values);
+}
+
+/*********************************************/
+static jstring gtk3_get_pango_font_name(JNIEnv *env, WidgetType widget_type)
+{
+    init_containers();
+
+    gtk3_widget = gtk3_get_widget(widget_type);
+    jstring  result = NULL;
+    GtkStyleContext* context = fp_gtk_widget_get_style_context (gtk3_widget);
+    if (context)
+    {
+        PangoFontDescription* fd = fp_gtk_style_context_get_font(context, 0);
+        gchar* val = (*fp_pango_font_description_to_string)(fd);
+        result = (*env)->NewStringUTF(env, val);
+        (*fp_g_free)( val );
+    }
+
+    return result;
+}
+
+/***********************************************/
+static jobject get_string_property(JNIEnv *env, GtkSettings* settings,
+                                                             const gchar* key) {
+    jobject result = NULL;
+    gchar*  strval = NULL;
+
+    (*fp_g_object_get)(settings, key, &strval, NULL);
+    result = (*env)->NewStringUTF(env, strval);
+    (*fp_g_free)(strval);
+
+    return result;
+}
+
+static jobject get_integer_property(JNIEnv *env, GtkSettings* settings,
+                                                             const gchar* key) {
+    gint intval = 0;
+    (*fp_g_object_get)(settings, key, &intval, NULL);
+    return create_Integer(env, intval);
+}
+
+static jobject get_boolean_property(JNIEnv *env, GtkSettings* settings,
+                                                             const gchar* key) {
+    gint intval = 0;
+    (*fp_g_object_get)(settings, key, &intval, NULL);
+    return create_Boolean(env, intval);
+}
+
+static jobject gtk3_get_setting(JNIEnv *env, Setting property)
+{
+    GtkSettings* settings = (*fp_gtk_settings_get_default)();
+
+    switch (property)
+    {
+        case GTK_FONT_NAME:
+            return get_string_property(env, settings, "gtk-font-name");
+        case GTK_ICON_SIZES:
+            return get_string_property(env, settings, "gtk-icon-sizes");
+        case GTK_CURSOR_BLINK:
+            return get_boolean_property(env, settings, "gtk-cursor-blink");
+        case GTK_CURSOR_BLINK_TIME:
+            return get_integer_property(env, settings, "gtk-cursor-blink-time");
+    }
+
+    return NULL;
+}
+
+static void transform_detail_string (const gchar *detail,
+                                                     GtkStyleContext *context) {
+  if (!detail)
+    return;
+
+  if (strcmp (detail, "arrow") == 0)
+    fp_gtk_style_context_add_class (context, "arrow");
+  else if (strcmp (detail, "button") == 0)
+    fp_gtk_style_context_add_class (context, "button");
+  else if (strcmp (detail, "buttondefault") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "button");
+      fp_gtk_style_context_add_class (context, "default");
+    }
+  else if (strcmp (detail, "calendar") == 0)
+    fp_gtk_style_context_add_class (context, "calendar");
+  else if (strcmp (detail, "cellcheck") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "cell");
+      fp_gtk_style_context_add_class (context, "check");
+    }
+  else if (strcmp (detail, "cellradio") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "cell");
+      fp_gtk_style_context_add_class (context, "radio");
+    }
+  else if (strcmp (detail, "checkbutton") == 0)
+    fp_gtk_style_context_add_class (context, "check");
+  else if (strcmp (detail, "check") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "check");
+      fp_gtk_style_context_add_class (context, "menu");
+    }
+  else if (strcmp (detail, "radiobutton") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "radio");
+    }
+  else if (strcmp (detail, "option") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "radio");
+      fp_gtk_style_context_add_class (context, "menu");
+    }
+  else if (strcmp (detail, "entry") == 0 ||
+           strcmp (detail, "entry_bg") == 0)
+    fp_gtk_style_context_add_class (context, "entry");
+  else if (strcmp (detail, "expander") == 0)
+    fp_gtk_style_context_add_class (context, "expander");
+  else if (strcmp (detail, "tooltip") == 0)
+    fp_gtk_style_context_add_class (context, "tooltip");
+  else if (strcmp (detail, "frame") == 0)
+    fp_gtk_style_context_add_class (context, "frame");
+  else if (strcmp (detail, "scrolled_window") == 0)
+    fp_gtk_style_context_add_class (context, "scrolled-window");
+  else if (strcmp (detail, "viewport") == 0 ||
+           strcmp (detail, "viewportbin") == 0)
+    fp_gtk_style_context_add_class (context, "viewport");
+  else if (strncmp (detail, "trough", 6) == 0)
+    fp_gtk_style_context_add_class (context, "trough");
+  else if (strcmp (detail, "spinbutton") == 0)
+    fp_gtk_style_context_add_class (context, "spinbutton");
+  else if (strcmp (detail, "spinbutton_up") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "spinbutton");
+      fp_gtk_style_context_add_class (context, "button");
+      fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_BOTTOM);
+    }
+  else if (strcmp (detail, "spinbutton_down") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "spinbutton");
+      fp_gtk_style_context_add_class (context, "button");
+      fp_gtk_style_context_set_junction_sides (context, GTK_JUNCTION_TOP);
+    }
+  else if ((detail[0] == 'h' || detail[0] == 'v') &&
+           strncmp (&detail[1], "scrollbar_", 9) == 0)
+    {
+      fp_gtk_style_context_add_class (context, "button");
+      fp_gtk_style_context_add_class (context, "scrollbar");
+    }
+  else if (strcmp (detail, "slider") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "slider");
+      fp_gtk_style_context_add_class (context, "scrollbar");
+    }
+  else if (strcmp (detail, "vscale") == 0 ||
+           strcmp (detail, "hscale") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "slider");
+      fp_gtk_style_context_add_class (context, "scale");
+    }
+  else if (strcmp (detail, "menuitem") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "menuitem");
+      fp_gtk_style_context_add_class (context, "menu");
+    }
+  else if (strcmp (detail, "menu") == 0)
+    {
+      fp_gtk_style_context_add_class (context, "popup");
+      fp_gtk_style_context_add_class (context, "menu");
+    }
+  else if (strcmp (detail, "accellabel") == 0)
+    fp_gtk_style_context_add_class (context, "accelerator");
+  else if (strcmp (detail, "menubar") == 0)
+    fp_gtk_style_context_add_class (context, "menubar");
+  else if (strcmp (detail, "base") == 0)
+    fp_gtk_style_context_add_class (context, "background");
+  else if (strcmp (detail, "bar") == 0 ||
+           strcmp (detail, "progressbar") == 0)
+    fp_gtk_style_context_add_class (context, "progressbar");
+  else if (strcmp (detail, "toolbar") == 0)
+    fp_gtk_style_context_add_class (context, "toolbar");
+  else if (strcmp (detail, "handlebox_bin") == 0)
+    fp_gtk_style_context_add_class (context, "dock");
+  else if (strcmp (detail, "notebook") == 0)
+    fp_gtk_style_context_add_class (context, "notebook");
+  else if (strcmp (detail, "tab") == 0)
+  {
+      fp_gtk_style_context_add_class (context, "notebook");
+      fp_gtk_style_context_add_region (context, "tab", 0);
+  } else if (strcmp (detail, "paned") == 0) {
+      fp_gtk_style_context_add_class (context, "pane-separator");
+  }
+  else if (fp_g_str_has_prefix (detail, "cell"))
+    {
+      GtkRegionFlags row, col;
+      gboolean ruled = FALSE;
+      gchar** tokens;
+      guint i;
+
+      tokens = fp_g_strsplit (detail, "_", -1);
+      row = col = 0;
+      i = 0;
+
+      while (tokens[i])
+        {
+          if (strcmp (tokens[i], "even") == 0)
+            row |= GTK_REGION_EVEN;
+          else if (strcmp (tokens[i], "odd") == 0)
+            row |= GTK_REGION_ODD;
+          else if (strcmp (tokens[i], "start") == 0)
+            col |= GTK_REGION_FIRST;
+          else if (strcmp (tokens[i], "end") == 0)
+            col |= GTK_REGION_LAST;
+          else if (strcmp (tokens[i], "ruled") == 0)
+            ruled = TRUE;
+          else if (strcmp (tokens[i], "sorted") == 0)
+            col |= GTK_REGION_SORTED;
+
+          i++;
+        }
+
+      if (!ruled)
+        row &= ~(GTK_REGION_EVEN | GTK_REGION_ODD);
+
+      fp_gtk_style_context_add_class (context, "cell");
+      fp_gtk_style_context_add_region (context, "row", row);
+      fp_gtk_style_context_add_region (context, "column", col);
+
+      fp_g_strfreev (tokens);
+    }
+}
+
+static gboolean gtk3_get_drawable_data(JNIEnv *env, jintArray pixelArray,
+     int x, jint y, jint width, jint height, jint jwidth, int dx, int dy,
+                                                                   jint scale) {
+    GdkPixbuf *pixbuf;
+    jint *ary;
+
+    GdkWindow *root = (*fp_gdk_get_default_root_window)();
+    pixbuf = (*fp_gdk_pixbuf_get_from_drawable)(root, x, y, width, height);
+    if (pixbuf && scale != 1) {
+        GdkPixbuf *scaledPixbuf;
+        x /= scale;
+        y /= scale;
+        width /= scale;
+        height /= scale;
+        dx /= scale;
+        dy /= scale;
+        scaledPixbuf = (*fp_gdk_pixbuf_scale_simple)(pixbuf, width, height,
+                                                     GDK_INTERP_BILINEAR);
+        (*fp_g_object_unref)(pixbuf);
+        pixbuf = scaledPixbuf;
+    }
+
+    if (pixbuf) {
+        int nchan = (*fp_gdk_pixbuf_get_n_channels)(pixbuf);
+        int stride = (*fp_gdk_pixbuf_get_rowstride)(pixbuf);
+        if ((*fp_gdk_pixbuf_get_width)(pixbuf) == width
+                && (*fp_gdk_pixbuf_get_height)(pixbuf) == height
+                && (*fp_gdk_pixbuf_get_bits_per_sample)(pixbuf) == 8
+                && (*fp_gdk_pixbuf_get_colorspace)(pixbuf) == GDK_COLORSPACE_RGB
+                && nchan >= 3
+                ) {
+            guchar *p, *pix = (*fp_gdk_pixbuf_get_pixels)(pixbuf);
+            ary = (*env)->GetPrimitiveArrayCritical(env, pixelArray, NULL);
+            if (ary) {
+                jint _x, _y;
+                int index;
+                for (_y = 0; _y < height; _y++) {
+                    for (_x = 0; _x < width; _x++) {
+                        p = pix + _y * stride + _x * nchan;
+
+                        index = (_y + dy) * jwidth + (_x + dx);
+                        ary[index] = 0xff000000
+                                        | (p[0] << 16)
+                                        | (p[1] << 8)
+                                        | (p[2]);
+
+                    }
+                }
+                (*env)->ReleasePrimitiveArrayCritical(env, pixelArray, ary, 0);
+            }
+        }
+        (*fp_g_object_unref)(pixbuf);
+    }
+    return JNI_FALSE;
+}
+
+static GdkWindow* gtk3_get_window(void *widget) {
+    return fp_gtk_widget_get_window((GtkWidget*)widget);
+}
+
+static void gtk3_init(GtkApi* gtk) {
+    gtk->version = GTK_3;
+
+    gtk->show_uri_load = &gtk3_show_uri_load;
+    gtk->unload = &gtk3_unload;
+    gtk->flush_event_loop = &flush_gtk_event_loop;
+    gtk->gtk_check_version = fp_gtk_check_version;
+    gtk->get_setting = &gtk3_get_setting;
+
+    gtk->paint_arrow = &gtk3_paint_arrow;
+    gtk->paint_box = &gtk3_paint_box;
+    gtk->paint_box_gap = &gtk3_paint_box_gap;
+    gtk->paint_expander = &gtk3_paint_expander;
+    gtk->paint_extension = &gtk3_paint_extension;
+    gtk->paint_flat_box = &gtk3_paint_flat_box;
+    gtk->paint_focus = &gtk3_paint_focus;
+    gtk->paint_handle = &gtk3_paint_handle;
+    gtk->paint_hline = &gtk3_paint_hline;
+    gtk->paint_vline = &gtk3_paint_vline;
+    gtk->paint_option = &gtk3_paint_option;
+    gtk->paint_shadow = &gtk3_paint_shadow;
+    gtk->paint_slider = &gtk3_paint_slider;
+    gtk->paint_background = &gtk3_paint_background;
+    gtk->paint_check = &gtk3_paint_check;
+    gtk->set_range_value = &gtk3_set_range_value;
+
+    gtk->init_painting = &gtk3_init_painting;
+    gtk->copy_image = &gtk3_copy_image;
+
+    gtk->get_xthickness = &gtk3_get_xthickness;
+    gtk->get_ythickness = &gtk3_get_ythickness;
+    gtk->get_color_for_state = &gtk3_get_color_for_state;
+    gtk->get_class_value = &gtk3_get_class_value;
+
+    gtk->get_pango_font_name = &gtk3_get_pango_font_name;
+    gtk->get_icon_data = &gtk3_get_icon_data;
+    gtk->get_file_icon_data = &gtk3_get_file_icon_data;
+    gtk->gdk_threads_enter = fp_gdk_threads_enter;
+    gtk->gdk_threads_leave = fp_gdk_threads_leave;
+    gtk->gtk_show_uri = fp_gtk_show_uri;
+    gtk->get_drawable_data = &gtk3_get_drawable_data;
+    gtk->g_free = fp_g_free;
+
+    gtk->gtk_file_chooser_get_filename = fp_gtk_file_chooser_get_filename;
+    gtk->gtk_widget_hide = fp_gtk_widget_hide;
+    gtk->gtk_main_quit = fp_gtk_main_quit;
+    gtk->gtk_file_chooser_dialog_new = fp_gtk_file_chooser_dialog_new;
+    gtk->gtk_file_chooser_set_current_folder =
+                          fp_gtk_file_chooser_set_current_folder;
+    gtk->gtk_file_chooser_set_filename = fp_gtk_file_chooser_set_filename;
+    gtk->gtk_file_chooser_set_current_name =
+                          fp_gtk_file_chooser_set_current_name;
+    gtk->gtk_file_filter_add_custom = fp_gtk_file_filter_add_custom;
+    gtk->gtk_file_chooser_set_filter = fp_gtk_file_chooser_set_filter;
+    gtk->gtk_file_chooser_get_type = fp_gtk_file_chooser_get_type;
+    gtk->gtk_file_filter_new = fp_gtk_file_filter_new;
+    gtk->gtk_file_chooser_set_do_overwrite_confirmation =
+                          fp_gtk_file_chooser_set_do_overwrite_confirmation;
+    gtk->gtk_file_chooser_set_select_multiple =
+                          fp_gtk_file_chooser_set_select_multiple;
+    gtk->gtk_file_chooser_get_current_folder =
+                          fp_gtk_file_chooser_get_current_folder;
+    gtk->gtk_file_chooser_get_filenames = fp_gtk_file_chooser_get_filenames;
+    gtk->gtk_g_slist_length = fp_gtk_g_slist_length;
+    gtk->g_signal_connect_data = fp_g_signal_connect_data;
+    gtk->gtk_widget_show = fp_gtk_widget_show;
+    gtk->gtk_main = fp_gtk_main;
+    gtk->gtk_main_level = fp_gtk_main_level;
+    gtk->g_path_get_dirname = fp_g_path_get_dirname;
+    gtk->gdk_x11_drawable_get_xid = fp_gdk_x11_drawable_get_xid;
+    gtk->gtk_widget_destroy = fp_gtk_widget_destroy;
+    gtk->gtk_window_present = fp_gtk_window_present;
+    gtk->gtk_window_move = fp_gtk_window_move;
+    gtk->gtk_window_resize = fp_gtk_window_resize;
+    gtk->get_window = &gtk3_get_window;
+
+    gtk->g_object_unref = fp_g_object_unref;
+    gtk->g_list_append = fp_g_list_append;
+    gtk->g_list_free = fp_g_list_free;
+    gtk->g_list_free_full = fp_g_list_free_full;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.h	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifndef _GTK3_INTERFACE_H
+#define _GTK3_INTERFACE_H
+
+#include <stdlib.h>
+#include <jni.h>
+#include <X11/X.h>
+#include "gtk_interface.h"
+
+#define LIGHTNESS_MULT  1.3
+#define DARKNESS_MULT   0.7
+
+#define G_PI    3.1415926535897932384626433832795028841971693993751
+
+typedef enum
+{
+  GTK_STATE_FLAG_NORMAL       = 0,
+  GTK_STATE_FLAG_ACTIVE       = 1 << 0,
+  GTK_STATE_FLAG_PRELIGHT     = 1 << 1,
+  GTK_STATE_FLAG_SELECTED     = 1 << 2,
+  GTK_STATE_FLAG_INSENSITIVE  = 1 << 3,
+  GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
+  GTK_STATE_FLAG_FOCUSED      = 1 << 5,
+  GTK_STATE_FLAG_BACKDROP     = 1 << 6,
+  GTK_STATE_FLAG_DIR_LTR      = 1 << 7,
+  GTK_STATE_FLAG_DIR_RTL      = 1 << 8,
+  GTK_STATE_FLAG_LINK         = 1 << 9,
+  GTK_STATE_FLAG_VISITED      = 1 << 10,
+  GTK_STATE_FLAG_CHECKED      = 1 << 11
+} GtkStateFlags;
+
+typedef enum {
+  GTK_JUNCTION_NONE = 0,
+  GTK_JUNCTION_CORNER_TOPLEFT = 1 << 0,
+  GTK_JUNCTION_CORNER_TOPRIGHT = 1 << 1,
+  GTK_JUNCTION_CORNER_BOTTOMLEFT = 1 << 2,
+  GTK_JUNCTION_CORNER_BOTTOMRIGHT = 1 << 3,
+  GTK_JUNCTION_TOP =
+                   (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_TOPRIGHT),
+  GTK_JUNCTION_BOTTOM =
+             (GTK_JUNCTION_CORNER_BOTTOMLEFT | GTK_JUNCTION_CORNER_BOTTOMRIGHT),
+  GTK_JUNCTION_LEFT =
+                 (GTK_JUNCTION_CORNER_TOPLEFT | GTK_JUNCTION_CORNER_BOTTOMLEFT),
+  GTK_JUNCTION_RIGHT =
+               (GTK_JUNCTION_CORNER_TOPRIGHT | GTK_JUNCTION_CORNER_BOTTOMRIGHT)
+} GtkJunctionSides;
+
+typedef enum {
+  GTK_REGION_EVEN    = 1 << 0,
+  GTK_REGION_ODD     = 1 << 1,
+  GTK_REGION_FIRST   = 1 << 2,
+  GTK_REGION_LAST    = 1 << 3,
+  GTK_REGION_ONLY    = 1 << 4,
+  GTK_REGION_SORTED  = 1 << 5
+} GtkRegionFlags;
+
+typedef enum
+{
+  GTK_WINDOW_TOPLEVEL,
+  GTK_WINDOW_POPUP
+} GtkWindowType;
+
+typedef enum
+{
+  G_PARAM_READABLE            = 1 << 0,
+  G_PARAM_WRITABLE            = 1 << 1,
+  G_PARAM_CONSTRUCT           = 1 << 2,
+  G_PARAM_CONSTRUCT_ONLY      = 1 << 3,
+  G_PARAM_LAX_VALIDATION      = 1 << 4,
+  G_PARAM_STATIC_NAME         = 1 << 5
+} GParamFlags;
+
+typedef enum
+{
+  GTK_ICON_LOOKUP_NO_SVG           = 1 << 0,
+  GTK_ICON_LOOKUP_FORCE_SVG        = 1 << 1,
+  GTK_ICON_LOOKUP_USE_BUILTIN      = 1 << 2,
+  GTK_ICON_LOOKUP_GENERIC_FALLBACK = 1 << 3,
+  GTK_ICON_LOOKUP_FORCE_SIZE       = 1 << 4
+} GtkIconLookupFlags;
+
+typedef enum
+{
+  GTK_UPDATE_CONTINUOUS,
+  GTK_UPDATE_DISCONTINUOUS,
+  GTK_UPDATE_DELAYED
+} GtkUpdateType;
+
+typedef enum
+{
+  GTK_PROGRESS_CONTINUOUS,
+  GTK_PROGRESS_DISCRETE
+} GtkProgressBarStyle;
+
+typedef enum
+{
+  GTK_PROGRESS_LEFT_TO_RIGHT,
+  GTK_PROGRESS_RIGHT_TO_LEFT,
+  GTK_PROGRESS_BOTTOM_TO_TOP,
+  GTK_PROGRESS_TOP_TO_BOTTOM
+} GtkProgressBarOrientation;
+
+typedef enum {
+    CAIRO_FORMAT_INVALID   = -1,
+    CAIRO_FORMAT_ARGB32    = 0,
+    CAIRO_FORMAT_RGB24     = 1,
+    CAIRO_FORMAT_A8        = 2,
+    CAIRO_FORMAT_A1        = 3,
+    CAIRO_FORMAT_RGB16_565 = 4
+} cairo_format_t;
+
+/* We define all structure pointers to be void* */
+typedef void GdkPixbuf;
+typedef void GMainContext;
+typedef void GVfs;
+
+typedef void GdkColormap;
+typedef void GdkDrawable;
+typedef void GdkGC;
+typedef void GdkPixmap;
+typedef void GtkStyleContext;
+typedef void GtkFixed;
+typedef void GtkMenuItem;
+typedef void GtkMenuShell;
+typedef void GtkWidgetClass;
+typedef void PangoFontDescription;
+typedef void GtkSettings;
+typedef void GtkStyleProvider;
+typedef void cairo_pattern_t;
+typedef void cairo_t;
+typedef void cairo_surface_t;
+typedef void GtkScrolledWindow;
+typedef void GtkIconTheme;
+typedef void GtkWidget;
+typedef void GtkMisc;
+typedef void GtkContainer;
+typedef void GtkBin;
+typedef void GtkAdjustment;
+typedef void GtkRange;
+typedef void GtkProgressBar;
+typedef void GtkProgress;
+
+/* Some real structures */
+typedef struct
+{
+  guint32 pixel;
+  guint16 red;
+  guint16 green;
+  guint16 blue;
+} GdkColor;
+
+typedef struct
+{
+  gdouble red;
+  gdouble green;
+  gdouble blue;
+  gdouble alpha;
+} GdkRGBA;
+
+typedef struct {
+  gint      fd;
+  gushort   events;
+  gushort   revents;
+} GPollFD;
+
+typedef struct {
+  gint x;
+  gint y;
+  gint width;
+  gint height;
+} GdkRectangle;
+
+typedef struct {
+    int x, y;
+    int width, height;
+} GtkAllocation;
+
+typedef struct {
+  gint width;
+  gint height;
+} GtkRequisition;
+
+typedef struct {
+  GtkWidgetClass *g_class;
+} GTypeInstance;
+
+typedef struct {
+  gint16 left;
+  gint16 right;
+  gint16 top;
+  gint16 bottom;
+} GtkBorder;
+
+typedef struct
+{
+  GType         g_type;
+  union {
+    gint        v_int;
+    guint       v_uint;
+    glong       v_long;
+    gulong      v_ulong;
+    gint64      v_int64;
+    guint64     v_uint64;
+    gfloat      v_float;
+    gdouble     v_double;
+    gpointer    v_pointer;
+  } data[2];
+} GValue;
+
+typedef struct {
+  GTypeInstance  g_type_instance;
+  const gchar   *name;
+  GParamFlags    flags;
+  GType    value_type;
+  GType    owner_type;
+} GParamSpec;
+
+
+static gchar* (*fp_glib_check_version)(guint required_major,
+                           guint required_minor, guint required_micro);
+
+/**
+ * Returns :
+ * NULL if the GTK+ library is compatible with the given version, or a string
+ * describing the version mismatch.
+ */
+static gchar* (*fp_gtk_check_version)(guint required_major, guint
+                           required_minor, guint required_micro);
+
+static void (*fp_g_free)(gpointer mem);
+static void (*fp_g_object_unref)(gpointer object);
+static GdkWindow *(*fp_gdk_get_default_root_window) (void);
+
+static int (*fp_gdk_pixbuf_get_bits_per_sample)(const GdkPixbuf *pixbuf);
+static guchar *(*fp_gdk_pixbuf_get_pixels)(const GdkPixbuf *pixbuf);
+static gboolean (*fp_gdk_pixbuf_get_has_alpha)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_height)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_n_channels)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_rowstride)(const GdkPixbuf *pixbuf);
+static int (*fp_gdk_pixbuf_get_width)(const GdkPixbuf *pixbuf);
+static GdkPixbuf *(*fp_gdk_pixbuf_new_from_file)(const char *filename,
+                                                              GError **error);
+static GdkColorspace (*fp_gdk_pixbuf_get_colorspace)(const GdkPixbuf *pixbuf);
+
+static GdkPixbuf *(*fp_gdk_pixbuf_get_from_drawable)(GdkWindow *window,
+        int src_x, int src_y, int width, int height);
+static GdkPixbuf *(*fp_gdk_pixbuf_scale_simple)(GdkPixbuf *src,
+        int dest_width, int dest_heigh, GdkInterpType interp_type);
+
+
+static void (*fp_gtk_widget_destroy)(void *widget);
+static void (*fp_gtk_window_present)(GtkWindow *window);
+static void (*fp_gtk_window_move)(GtkWindow *window, gint x, gint y);
+static void (*fp_gtk_window_resize)(GtkWindow *window, gint width, gint height);
+
+/**
+ * Function Pointers for GtkFileChooser
+ */
+static gchar* (*fp_gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+static void (*fp_gtk_widget_hide)(void *widget);
+static void (*fp_gtk_main_quit)(void);
+static void* (*fp_gtk_file_chooser_dialog_new)(const gchar *title,
+    GtkWindow *parent, GtkFileChooserAction action,
+    const gchar *first_button_text, ...);
+static gboolean (*fp_gtk_file_chooser_set_current_folder)
+                              (GtkFileChooser *chooser, const gchar *filename);
+static gboolean (*fp_gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+    const char *filename);
+static void (*fp_gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+    const gchar *name);
+static void (*fp_gtk_file_filter_add_custom)(GtkFileFilter *filter,
+    GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
+    GDestroyNotify notify);
+static void (*fp_gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+    GtkFileFilter *filter);
+static GType (*fp_gtk_file_chooser_get_type)(void);
+static GtkFileFilter* (*fp_gtk_file_filter_new)(void);
+static void (*fp_gtk_file_chooser_set_do_overwrite_confirmation)(
+    GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
+static void (*fp_gtk_file_chooser_set_select_multiple)(
+    GtkFileChooser *chooser, gboolean select_multiple);
+static gchar* (*fp_gtk_file_chooser_get_current_folder)
+                                                      (GtkFileChooser *chooser);
+static GSList* (*fp_gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+static guint (*fp_gtk_g_slist_length)(GSList *list);
+static gulong (*fp_g_signal_connect_data)(gpointer instance,
+    const gchar *detailed_signal, GCallback c_handler, gpointer data,
+    GClosureNotify destroy_data, GConnectFlags connect_flags);
+static void (*fp_gtk_widget_show)(void *widget);
+static void (*fp_gtk_main)(void);
+static guint (*fp_gtk_main_level)(void);
+static gchar* (*fp_g_path_get_dirname) (const gchar *file_name);
+static XID (*fp_gdk_x11_drawable_get_xid) (GdkWindow *drawable);
+
+static GList* (*fp_g_list_append) (GList *list, gpointer data);
+static void (*fp_g_list_free) (GList *list);
+static void (*fp_g_list_free_full) (GList *list, GDestroyNotify free_func);
+
+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);
+
+// Implementation functions prototypes
+static void gtk3_init(GtkApi* gtk);
+static GValue*      (*fp_g_value_init)(GValue *value, GType g_type);
+static gboolean     (*fp_g_type_is_a)(GType type, GType is_a_type);
+static gboolean     (*fp_g_value_get_boolean)(const GValue *value);
+static gchar        (*fp_g_value_get_char)(const GValue *value);
+static guchar       (*fp_g_value_get_uchar)(const GValue *value);
+static gint         (*fp_g_value_get_int)(const GValue *value);
+static guint        (*fp_g_value_get_uint)(const GValue *value);
+static glong        (*fp_g_value_get_long)(const GValue *value);
+static gulong       (*fp_g_value_get_ulong)(const GValue *value);
+static gint64       (*fp_g_value_get_int64)(const GValue *value);
+static guint64      (*fp_g_value_get_uint64)(const GValue *value);
+static gfloat       (*fp_g_value_get_float)(const GValue *value);
+static gdouble      (*fp_g_value_get_double)(const GValue *value);
+static const gchar* (*fp_g_value_get_string)(const GValue *value);
+static gint         (*fp_g_value_get_enum)(const GValue *value);
+static guint        (*fp_g_value_get_flags)(const GValue *value);
+static GParamSpec*  (*fp_g_value_get_param)(const GValue *value);
+static gpointer*    (*fp_g_value_get_boxed)(const GValue *value);
+static gpointer*    (*fp_g_value_get_pointer)(const GValue *value);
+static void         (*fp_g_object_get)(gpointer object,
+                                       const gchar* fpn, ...);
+static void         (*fp_g_object_set)(gpointer object,
+                                       const gchar *first_property_name,
+                                       ...);
+
+static gboolean (*fp_g_main_context_iteration)(GMainContext *context);
+static gboolean (*fp_g_str_has_prefix)(const gchar *str, const gchar *prefix);
+static gchar** (*fp_g_strsplit)(const gchar *string, const gchar *delimiter,
+           gint max_tokens);
+static void (*fp_g_strfreev)(gchar **str_array);
+
+
+static cairo_surface_t* (*fp_cairo_image_surface_create)(cairo_format_t format,
+                               int width, int height);
+static void (*fp_cairo_surface_destroy)(cairo_surface_t *surface);
+static cairo_t* (*fp_cairo_create)(cairo_surface_t *target);
+static void (*fp_cairo_destroy)(cairo_t *cr);
+static void (*fp_cairo_fill)(cairo_t *cr);
+static void (*fp_cairo_surface_flush)(cairo_surface_t *surface);
+static void (*fp_cairo_rectangle)(cairo_t *cr, double x, double y, double width,
+                double height);
+static void (*fp_cairo_set_source_rgb)(cairo_t *cr, double red, double green,
+                double blue);
+static void (*fp_cairo_set_source_rgba)(cairo_t *cr, double red, double green,
+                double blue, double alpha);
+static void (*fp_cairo_paint)(cairo_t *cr);
+static void (*fp_cairo_clip)(cairo_t *cr);
+static unsigned char* (*fp_cairo_image_surface_get_data)(
+                                                 cairo_surface_t *surface);
+static int (*fp_cairo_image_surface_get_stride) (cairo_surface_t *surface);
+static GdkPixbuf* (*fp_gdk_pixbuf_get_from_surface)(cairo_surface_t *surface,
+                            gint src_x, gint src_y, gint width, gint height);
+static GtkStateType (*fp_gtk_widget_get_state)(GtkWidget *widget);
+static void (*fp_gtk_widget_set_state)(GtkWidget *widget, GtkStateType state);
+static gboolean (*fp_gtk_widget_is_focus)(GtkWidget *widget);
+static void (*fp_gtk_widget_set_allocation)(GtkWidget *widget,
+                                            const GtkAllocation *allocation);
+static GtkWidget* (*fp_gtk_widget_get_parent)(GtkWidget *widget);
+static GtkStyleContext* (*fp_gtk_widget_get_style_context)(GtkWidget *widget);
+static void (*fp_gtk_style_context_get_color)(GtkStyleContext *context,
+                                           GtkStateFlags state, GdkRGBA *color);
+static void (*fp_gtk_style_context_get_background_color)
+                (GtkStyleContext *context, GtkStateFlags state, GdkRGBA *color);
+static void (*fp_gtk_style_context_get)(GtkStyleContext *context,
+                                                      GtkStateFlags state, ...);
+static GtkStateFlags (*fp_gtk_widget_get_state_flags)(GtkWidget* widget);
+static void (*fp_gtk_style_context_set_state)(GtkStyleContext* style,
+                                              GtkStateFlags flags);
+static void (*fp_gtk_style_context_add_class)(GtkStyleContext *context,
+                                                 const gchar *class_name);
+static void (*fp_gtk_style_context_save)(GtkStyleContext *context);
+static void (*fp_gtk_style_context_restore)(GtkStyleContext *context);
+static void (*fp_gtk_render_check)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_option)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_extension)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height,
+                     GtkPositionType gap_side);
+static void (*fp_gtk_render_expander)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_frame_gap)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height,
+                     GtkPositionType gap_side, gdouble xy0_gap,
+                     gdouble xy1_gap);
+static void (*fp_gtk_render_line)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x0, gdouble y0, gdouble x1, gdouble y1);
+static GdkPixbuf* (*fp_gtk_widget_render_icon_pixbuf)(GtkWidget *widget,
+                     const gchar *stock_id, GtkIconSize size);
+static cairo_surface_t* (*fp_gdk_window_create_similar_image_surface)(
+                     GdkWindow *window, cairo_format_t format, int width,
+                     int height, int scale);
+static cairo_surface_t* (*fp_gdk_window_create_similar_surface)(
+                     GdkWindow *window, cairo_format_t format,
+                     int width, int height);
+static GdkWindow* (*fp_gtk_widget_get_window)(GtkWidget *widget);
+static GtkSettings *(*fp_gtk_settings_get_for_screen)(GdkScreen *screen);
+static GdkScreen *(*fp_gtk_widget_get_screen)(GtkWidget *widget);
+static GtkStyleProvider* (*fp_gtk_css_provider_get_named)(const gchar *name,
+                     const gchar *variant);
+static void (*fp_gtk_style_context_add_provider)(GtkStyleContext *context,
+                     GtkStyleProvider *provider, guint priority);
+static void (*fp_gtk_render_frame)(GtkStyleContext *context,cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_focus)(GtkStyleContext *context,cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_handle)(GtkStyleContext *context,cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_style_context_get_property)(GtkStyleContext *context,
+                     const gchar *property, GtkStateFlags state, GValue *value);
+static void (*fp_gtk_render_activity)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static void (*fp_gtk_render_background)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height);
+static gboolean (*fp_gtk_style_context_has_class)(GtkStyleContext *context,
+                     const gchar *class_name);
+static void transform_detail_string (const gchar *detail,
+                     GtkStyleContext *context);
+void (*fp_gtk_style_context_set_junction_sides)(GtkStyleContext  *context,
+                     GtkJunctionSides  sides);
+void (*fp_gtk_style_context_add_region)(GtkStyleContext *context,
+                     const gchar *region_name, GtkRegionFlags flags);
+void (*fp_gtk_render_arrow)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble angle, gdouble x, gdouble y, gdouble size);
+void (*fp_gtk_bin_set_child)(GtkBin *bin, GtkWidget *widget);
+void (*fp_gtk_scrolled_window_set_shadow_type)(
+                     GtkScrolledWindow *scrolled_window, GtkShadowType type);
+static void (*fp_gtk_render_slider)(GtkStyleContext *context, cairo_t *cr,
+                     gdouble x, gdouble y, gdouble width, gdouble height,
+                     GtkOrientation orientation);
+static void (*fp_gtk_style_context_get_padding)(GtkStyleContext *self,
+                     GtkStateFlags state, GtkBorder* padding);
+static void (*fp_gtk_range_set_inverted)(GtkRange *range, gboolean  setting);
+static PangoFontDescription* (*fp_gtk_style_context_get_font)(
+                     GtkStyleContext *context, GtkStateFlags state);
+static int (*fp_gtk_widget_get_allocated_width)(GtkWidget *widget);
+static int (*fp_gtk_widget_get_allocated_height)(GtkWidget *widget);
+static GtkIconTheme* (*fp_gtk_icon_theme_get_default)(void);
+static GdkPixbuf* (*fp_gtk_icon_theme_load_icon)(GtkIconTheme *icon_theme,
+                     const gchar *icon_name, gint size,
+                     GtkIconLookupFlags flags, GError **error);
+static void (*fp_gtk_adjustment_set_lower)(GtkAdjustment *adjustment,
+                     gdouble lower);
+static void (*fp_gtk_adjustment_set_page_increment)(GtkAdjustment *adjustment,
+                     gdouble page_increment);
+static void (*fp_gtk_adjustment_set_page_size)(GtkAdjustment *adjustment,
+                     gdouble page_size);
+static void (*fp_gtk_adjustment_set_step_increment)(GtkAdjustment *adjustment,
+                     gdouble step_increment);
+static void (*fp_gtk_adjustment_set_upper)(GtkAdjustment *adjustment,
+                     gdouble upper);
+static void (*fp_gtk_adjustment_set_value)(GtkAdjustment *adjustment,
+                     gdouble value);
+static GdkGC *(*fp_gdk_gc_new)(GdkDrawable*);
+static void (*fp_gdk_rgb_gc_set_foreground)(GdkGC*, guint32);
+static void (*fp_gdk_draw_rectangle)(GdkDrawable*, GdkGC*, gboolean,
+        gint, gint, gint, gint);
+static GdkPixbuf *(*fp_gdk_pixbuf_new)(GdkColorspace colorspace,
+        gboolean has_alpha, int bits_per_sample, int width, int height);
+static void (*fp_gdk_drawable_get_size)(GdkDrawable *drawable,
+        gint* width, gint* height);
+static gboolean (*fp_gtk_init_check)(int* argc, char** argv);
+
+/* Widget creation */
+static GtkWidget* (*fp_gtk_arrow_new)(GtkArrowType arrow_type,
+                                      GtkShadowType shadow_type);
+static GtkWidget* (*fp_gtk_button_new)();
+static GtkWidget* (*fp_gtk_check_button_new)();
+static GtkWidget* (*fp_gtk_check_menu_item_new)();
+static GtkWidget* (*fp_gtk_color_selection_dialog_new)(const gchar* title);
+static GtkWidget* (*fp_gtk_combo_box_new)();
+static GtkWidget* (*fp_gtk_combo_box_entry_new)();
+static GtkWidget* (*fp_gtk_entry_new)();
+static GtkWidget* (*fp_gtk_fixed_new)();
+static GtkWidget* (*fp_gtk_handle_box_new)();
+static GtkWidget* (*fp_gtk_hpaned_new)();
+static GtkWidget* (*fp_gtk_vpaned_new)();
+static GtkWidget* (*fp_gtk_scale_new)(GtkOrientation  orientation,
+                                       GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_hscrollbar_new)(GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_vscrollbar_new)(GtkAdjustment* adjustment);
+static GtkWidget* (*fp_gtk_hseparator_new)();
+static GtkWidget* (*fp_gtk_vseparator_new)();
+static GtkWidget* (*fp_gtk_image_new)();
+static GtkWidget* (*fp_gtk_label_new)(const gchar* str);
+static GtkWidget* (*fp_gtk_menu_new)();
+static GtkWidget* (*fp_gtk_menu_bar_new)();
+static GtkWidget* (*fp_gtk_menu_item_new)();
+static GtkWidget* (*fp_gtk_notebook_new)();
+static GtkWidget* (*fp_gtk_progress_bar_new)();
+static GtkWidget* (*fp_gtk_progress_bar_set_orientation)(
+        GtkProgressBar *pbar,
+        GtkProgressBarOrientation orientation);
+static GtkWidget* (*fp_gtk_radio_button_new)(GSList *group);
+static GtkWidget* (*fp_gtk_radio_menu_item_new)(GSList *group);
+static GtkWidget* (*fp_gtk_scrolled_window_new)(GtkAdjustment *hadjustment,
+        GtkAdjustment *vadjustment);
+static GtkWidget* (*fp_gtk_separator_menu_item_new)();
+static GtkWidget* (*fp_gtk_separator_tool_item_new)();
+static GtkWidget* (*fp_gtk_text_view_new)();
+static GtkWidget* (*fp_gtk_toggle_button_new)();
+static GtkWidget* (*fp_gtk_toolbar_new)();
+static GtkWidget* (*fp_gtk_tree_view_new)();
+static GtkWidget* (*fp_gtk_viewport_new)(GtkAdjustment *hadjustment,
+        GtkAdjustment *vadjustment);
+static GtkWidget* (*fp_gtk_window_new)(GtkWindowType type);
+static GtkWidget* (*fp_gtk_dialog_new)();
+static GtkWidget* (*fp_gtk_spin_button_new)(GtkAdjustment *adjustment,
+        gdouble climb_rate, guint digits);
+static GtkWidget* (*fp_gtk_frame_new)(const gchar *label);
+
+/* Other widget operations */
+static GtkAdjustment* (*fp_gtk_adjustment_new)(gdouble value,
+        gdouble lower, gdouble upper, gdouble step_increment,
+        gdouble page_increment, gdouble page_size);
+static void (*fp_gtk_container_add)(GtkContainer *window, GtkWidget *widget);
+static void (*fp_gtk_menu_shell_append)(GtkMenuShell *menu_shell,
+        GtkWidget *child);
+static void (*fp_gtk_menu_item_set_submenu)(GtkMenuItem *menu_item,
+        GtkWidget *submenu);
+static void (*fp_gtk_widget_realize)(GtkWidget *widget);
+static GdkPixbuf* (*fp_gtk_widget_render_icon)(GtkWidget *widget,
+        const gchar *stock_id, GtkIconSize size, const gchar *detail);
+static void (*fp_gtk_widget_set_name)(GtkWidget *widget, const gchar *name);
+static void (*fp_gtk_widget_set_parent)(GtkWidget *widget, GtkWidget *parent);
+static void (*fp_gtk_widget_set_direction)(GtkWidget *widget,
+        GtkTextDirection direction);
+static void (*fp_gtk_widget_style_get)(GtkWidget *widget,
+        const gchar *first_property_name, ...);
+static void (*fp_gtk_widget_class_install_style_property)(
+        GtkWidgetClass* class, GParamSpec *pspec);
+static GParamSpec* (*fp_gtk_widget_class_find_style_property)(
+        GtkWidgetClass* class, const gchar* property_name);
+static void (*fp_gtk_widget_style_get_property)(GtkWidget* widget,
+        const gchar* property_name, GValue* value);
+static char* (*fp_pango_font_description_to_string)(
+        const PangoFontDescription* fd);
+static GtkSettings* (*fp_gtk_settings_get_default)();
+static GtkSettings* (*fp_gtk_widget_get_settings)(GtkWidget *widget);
+static GType        (*fp_gtk_border_get_type)();
+static void (*fp_gtk_arrow_set)(GtkWidget* arrow,
+                                GtkArrowType arrow_type,
+                                GtkShadowType shadow_type);
+static void (*fp_gtk_widget_size_request)(GtkWidget *widget,
+                                          GtkRequisition *requisition);
+static GtkAdjustment* (*fp_gtk_range_get_adjustment)(GtkRange* range);
+
+#endif /* !_GTK3_INTERFACE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.c	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#include <dlfcn.h>
+#include <stdlib.h>
+#include "jvm_md.h"
+#include "gtk_interface.h"
+
+GtkApi* gtk2_load(JNIEnv *env, const char* lib_name);
+GtkApi* gtk3_load(JNIEnv *env, const char* lib_name);
+
+gboolean gtk2_check(const char* lib_name, int flags);
+gboolean gtk3_check(const char* lib_name, int flags);
+
+GtkApi *gtk;
+
+typedef struct {
+    GtkVersion version;
+    const char* name;
+    const char* vname;
+    GtkApi* (*load)(JNIEnv *env, const char* lib_name);
+    gboolean (*check)(const char* lib_name, int flags);
+} GtkLib;
+
+static GtkLib libs[] = {
+    {
+        GTK_2,
+        JNI_LIB_NAME("gtk-x11-2.0"),
+        VERSIONED_JNI_LIB_NAME("gtk-x11-2.0", "0"),
+        &gtk2_load,
+        &gtk2_check
+    },
+    {
+        GTK_3,
+        JNI_LIB_NAME("gtk-3"),
+        VERSIONED_JNI_LIB_NAME("gtk-3", "0"),
+        &gtk3_load,
+        &gtk3_check
+    },
+    {
+        0,
+        NULL,
+        NULL,
+        NULL,
+        NULL
+    }
+};
+
+static GtkLib* get_loaded() {
+    GtkLib* lib = libs;
+    while(!gtk && lib->version) {
+        if (lib->check(lib->vname, RTLD_NOLOAD)) {
+            return lib;
+        }
+        if (lib->check(lib->name, RTLD_NOLOAD)) {
+            return lib;
+        }
+        lib++;
+    }
+    return NULL;
+}
+
+gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose) {
+    if (gtk == NULL) {
+        GtkLib* lib = get_loaded();
+        if (lib) {
+            if (version != GTK_ANY && lib->version != version) {
+                if (verbose) {
+                    fprintf(stderr, "WARNING: Cannot load GTK%d library: \
+                         GTK%d has already been loaded\n", version, lib->version);
+                }
+                return FALSE;
+            }
+            if (verbose) {
+                fprintf(stderr, "Looking for GTK%d library...\n", version);
+            }
+            gtk = lib->load(env, lib->vname);
+            if (!gtk) {
+                gtk = lib->load(env, lib->name);
+            }
+        } else {
+            lib = libs;
+            while (!gtk && lib->version) {
+                if (version == GTK_ANY || lib->version == version) {
+                    if (verbose) {
+                        fprintf(stderr, "Looking for GTK%d library...\n",
+                                                                  lib->version);
+                    }
+                    gtk = lib->load(env, lib->vname);
+                    if (!gtk) {
+                        gtk = lib->load(env, lib->name);
+                    }
+                    if (verbose && !gtk) {
+                        fprintf(stderr, "Not found.\n");
+                    }
+                }
+                lib++;
+            }
+            lib--;
+        }
+        if (verbose) {
+            if (gtk) {
+                fprintf(stderr, "GTK%d library loaded.\n", lib->version);
+            } else {
+                fprintf(stderr, "Failed to load GTK library.\n");
+            }
+        }
+    }
+    return gtk != NULL;
+}
+
+static gboolean check_version(GtkVersion version, int flags) {
+    GtkLib* lib = libs;
+    while (lib->version) {
+        if (version == GTK_ANY || lib->version == version) {
+            if (lib->check(lib->vname, flags)) {
+                return TRUE;
+            }
+            if (lib->check(lib->name, flags)) {
+                return TRUE;
+            }
+        }
+        lib++;
+    }
+    return FALSE;
+}
+
+gboolean gtk_check_version(GtkVersion version) {
+    if (gtk) {
+        return TRUE;
+    }
+    if (check_version(version, RTLD_NOLOAD)) {
+        return TRUE;
+    }
+    return check_version(version, RTLD_LAZY | RTLD_LOCAL);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/gtk_interface.h	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+#ifndef _GTK_INTERFACE_H
+#define _GTK_INTERFACE_H
+
+#include <X11/X.h>
+#include <jni.h>
+
+#ifndef FALSE
+#define FALSE           (0)
+#define TRUE            (!FALSE)
+#endif
+
+#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))
+#define GTK_TYPE_FILE_CHOOSER             (fp_gtk_file_chooser_get_type ())
+#define GTK_FILE_CHOOSER(obj) \
+     (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_CHOOSER, GtkFileChooser))
+#define G_CALLBACK(f) ((GCallback) (f))
+#define G_TYPE_FUNDAMENTAL_SHIFT (2)
+#define G_TYPE_MAKE_FUNDAMENTAL(x) ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
+#define G_TYPE_OBJECT G_TYPE_MAKE_FUNDAMENTAL (20)
+#define GTK_STOCK_CANCEL           "gtk-cancel"
+#define GTK_STOCK_SAVE             "gtk-save"
+#define GTK_STOCK_OPEN             "gtk-open"
+#define GDK_CURRENT_TIME           0L
+
+#define G_TYPE_INVALID                  G_TYPE_MAKE_FUNDAMENTAL (0)
+#define G_TYPE_NONE                     G_TYPE_MAKE_FUNDAMENTAL (1)
+#define G_TYPE_INTERFACE                G_TYPE_MAKE_FUNDAMENTAL (2)
+#define G_TYPE_CHAR                     G_TYPE_MAKE_FUNDAMENTAL (3)
+#define G_TYPE_UCHAR                    G_TYPE_MAKE_FUNDAMENTAL (4)
+#define G_TYPE_BOOLEAN                  G_TYPE_MAKE_FUNDAMENTAL (5)
+#define G_TYPE_INT                      G_TYPE_MAKE_FUNDAMENTAL (6)
+#define G_TYPE_UINT                     G_TYPE_MAKE_FUNDAMENTAL (7)
+#define G_TYPE_LONG                     G_TYPE_MAKE_FUNDAMENTAL (8)
+#define G_TYPE_ULONG                    G_TYPE_MAKE_FUNDAMENTAL (9)
+#define G_TYPE_INT64                    G_TYPE_MAKE_FUNDAMENTAL (10)
+#define G_TYPE_UINT64                   G_TYPE_MAKE_FUNDAMENTAL (11)
+#define G_TYPE_ENUM                     G_TYPE_MAKE_FUNDAMENTAL (12)
+#define G_TYPE_FLAGS                    G_TYPE_MAKE_FUNDAMENTAL (13)
+#define G_TYPE_FLOAT                    G_TYPE_MAKE_FUNDAMENTAL (14)
+#define G_TYPE_DOUBLE                   G_TYPE_MAKE_FUNDAMENTAL (15)
+#define G_TYPE_STRING                   G_TYPE_MAKE_FUNDAMENTAL (16)
+#define G_TYPE_POINTER                  G_TYPE_MAKE_FUNDAMENTAL (17)
+#define G_TYPE_BOXED                    G_TYPE_MAKE_FUNDAMENTAL (18)
+#define G_TYPE_PARAM                    G_TYPE_MAKE_FUNDAMENTAL (19)
+#define G_TYPE_OBJECT                   G_TYPE_MAKE_FUNDAMENTAL (20)
+
+#define GTK_TYPE_BORDER                 ((*fp_gtk_border_get_type)())
+
+#define G_TYPE_FUNDAMENTAL_SHIFT        (2)
+#define G_TYPE_MAKE_FUNDAMENTAL(x)      ((GType) ((x) << G_TYPE_FUNDAMENTAL_SHIFT))
+
+#ifndef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#endif
+
+#define CONV_BUFFER_SIZE 128
+#define NO_SYMBOL_EXCEPTION 1
+
+/* basic types */
+typedef char    gchar;
+typedef short   gshort;
+typedef int     gint;
+typedef long    glong;
+typedef float   gfloat;
+typedef double  gdouble;
+typedef void*   gpointer;
+typedef gint    gboolean;
+typedef signed char  gint8;
+typedef signed short gint16;
+typedef signed int   gint32;
+typedef unsigned char  guchar;
+typedef unsigned char  guint8;
+typedef unsigned short gushort;
+typedef unsigned short guint16;
+typedef unsigned int   guint;
+typedef unsigned int   guint32;
+typedef unsigned int   gsize;
+typedef unsigned long  gulong;
+typedef signed long long   gint64;
+typedef unsigned long long guint64;
+typedef gulong GType;
+
+typedef struct _GList GList;
+struct _GList
+{
+  gpointer data;
+  GList *next;
+  GList *prev;
+};
+
+typedef struct _GSList GSList;
+struct _GSList {
+  gpointer data;
+  GSList *next;
+};
+
+typedef enum {
+    BUTTON,                     /* GtkButton */
+    CHECK_BOX,                  /* GtkCheckButton */
+    CHECK_BOX_MENU_ITEM,        /* GtkCheckMenuItem */
+    COLOR_CHOOSER,              /* GtkColorSelectionDialog */
+    COMBO_BOX,                  /* GtkComboBox */
+    COMBO_BOX_ARROW_BUTTON,     /* GtkComboBoxEntry */
+    COMBO_BOX_TEXT_FIELD,       /* GtkComboBoxEntry */
+    DESKTOP_ICON,               /* GtkLabel */
+    DESKTOP_PANE,               /* GtkContainer */
+    EDITOR_PANE,                /* GtkTextView */
+    FORMATTED_TEXT_FIELD,       /* GtkEntry */
+    HANDLE_BOX,                 /* GtkHandleBox */
+    HPROGRESS_BAR,              /* GtkProgressBar */
+    HSCROLL_BAR,                /* GtkHScrollbar */
+    HSCROLL_BAR_BUTTON_LEFT,    /* GtkHScrollbar */
+    HSCROLL_BAR_BUTTON_RIGHT,   /* GtkHScrollbar */
+    HSCROLL_BAR_TRACK,          /* GtkHScrollbar */
+    HSCROLL_BAR_THUMB,          /* GtkHScrollbar */
+    HSEPARATOR,                 /* GtkHSeparator */
+    HSLIDER,                    /* GtkHScale */
+    HSLIDER_TRACK,              /* GtkHScale */
+    HSLIDER_THUMB,              /* GtkHScale */
+    HSPLIT_PANE_DIVIDER,        /* GtkHPaned */
+    INTERNAL_FRAME,             /* GtkWindow */
+    INTERNAL_FRAME_TITLE_PANE,  /* GtkLabel */
+    IMAGE,                      /* GtkImage */
+    LABEL,                      /* GtkLabel */
+    LIST,                       /* GtkTreeView */
+    MENU,                       /* GtkMenu */
+    MENU_BAR,                   /* GtkMenuBar */
+    MENU_ITEM,                  /* GtkMenuItem */
+    MENU_ITEM_ACCELERATOR,      /* GtkLabel */
+    OPTION_PANE,                /* GtkMessageDialog */
+    PANEL,                      /* GtkContainer */
+    PASSWORD_FIELD,             /* GtkEntry */
+    POPUP_MENU,                 /* GtkMenu */
+    POPUP_MENU_SEPARATOR,       /* GtkSeparatorMenuItem */
+    RADIO_BUTTON,               /* GtkRadioButton */
+    RADIO_BUTTON_MENU_ITEM,     /* GtkRadioMenuItem */
+    ROOT_PANE,                  /* GtkContainer */
+    SCROLL_PANE,                /* GtkScrolledWindow */
+    SPINNER,                    /* GtkSpinButton */
+    SPINNER_ARROW_BUTTON,       /* GtkSpinButton */
+    SPINNER_TEXT_FIELD,         /* GtkSpinButton */
+    SPLIT_PANE,                 /* GtkPaned */
+    TABBED_PANE,                /* GtkNotebook */
+    TABBED_PANE_TAB_AREA,       /* GtkNotebook */
+    TABBED_PANE_CONTENT,        /* GtkNotebook */
+    TABBED_PANE_TAB,            /* GtkNotebook */
+    TABLE,                      /* GtkTreeView */
+    TABLE_HEADER,               /* GtkButton */
+    TEXT_AREA,                  /* GtkTextView */
+    TEXT_FIELD,                 /* GtkEntry */
+    TEXT_PANE,                  /* GtkTextView */
+    TITLED_BORDER,              /* GtkFrame */
+    TOGGLE_BUTTON,              /* GtkToggleButton */
+    TOOL_BAR,                   /* GtkToolbar */
+    TOOL_BAR_DRAG_WINDOW,       /* GtkToolbar */
+    TOOL_BAR_SEPARATOR,         /* GtkSeparatorToolItem */
+    TOOL_TIP,                   /* GtkWindow */
+    TREE,                       /* GtkTreeView */
+    TREE_CELL,                  /* GtkTreeView */
+    VIEWPORT,                   /* GtkViewport */
+    VPROGRESS_BAR,              /* GtkProgressBar */
+    VSCROLL_BAR,                /* GtkVScrollbar */
+    VSCROLL_BAR_BUTTON_UP,      /* GtkVScrollbar */
+    VSCROLL_BAR_BUTTON_DOWN,    /* GtkVScrollbar */
+    VSCROLL_BAR_TRACK,          /* GtkVScrollbar */
+    VSCROLL_BAR_THUMB,          /* GtkVScrollbar */
+    VSEPARATOR,                 /* GtkVSeparator */
+    VSLIDER,                    /* GtkVScale */
+    VSLIDER_TRACK,              /* GtkVScale */
+    VSLIDER_THUMB,              /* GtkVScale */
+    VSPLIT_PANE_DIVIDER,        /* GtkVPaned */
+    WIDGET_TYPE_SIZE
+} WidgetType;
+
+typedef enum
+{
+    _GTK_ARROW_TYPE,
+    _GTK_BUTTON_TYPE,
+    _GTK_CHECK_BUTTON_TYPE,
+    _GTK_CHECK_MENU_ITEM_TYPE,
+    _GTK_COLOR_SELECTION_DIALOG_TYPE,
+    _GTK_COMBO_BOX_TYPE,
+    _GTK_COMBO_BOX_ARROW_BUTTON_TYPE,
+    _GTK_COMBO_BOX_TEXT_FIELD_TYPE,
+    _GTK_CONTAINER_TYPE,
+    _GTK_ENTRY_TYPE,
+    _GTK_FRAME_TYPE,
+    _GTK_HANDLE_BOX_TYPE,
+    _GTK_HPANED_TYPE,
+    _GTK_HPROGRESS_BAR_TYPE,
+    _GTK_HSCALE_TYPE,
+    _GTK_HSCROLLBAR_TYPE,
+    _GTK_HSEPARATOR_TYPE,
+    _GTK_IMAGE_TYPE,
+    _GTK_MENU_TYPE,
+    _GTK_MENU_BAR_TYPE,
+    _GTK_MENU_ITEM_TYPE,
+    _GTK_NOTEBOOK_TYPE,
+    _GTK_LABEL_TYPE,
+    _GTK_RADIO_BUTTON_TYPE,
+    _GTK_RADIO_MENU_ITEM_TYPE,
+    _GTK_SCROLLED_WINDOW_TYPE,
+    _GTK_SEPARATOR_MENU_ITEM_TYPE,
+    _GTK_SEPARATOR_TOOL_ITEM_TYPE,
+    _GTK_SPIN_BUTTON_TYPE,
+    _GTK_TEXT_VIEW_TYPE,
+    _GTK_TOGGLE_BUTTON_TYPE,
+    _GTK_TOOLBAR_TYPE,
+    _GTK_TOOLTIP_TYPE,
+    _GTK_TREE_VIEW_TYPE,
+    _GTK_VIEWPORT_TYPE,
+    _GTK_VPANED_TYPE,
+    _GTK_VPROGRESS_BAR_TYPE,
+    _GTK_VSCALE_TYPE,
+    _GTK_VSCROLLBAR_TYPE,
+    _GTK_VSEPARATOR_TYPE,
+    _GTK_WINDOW_TYPE,
+    _GTK_DIALOG_TYPE,
+    _GTK_WIDGET_TYPE_SIZE
+} GtkWidgetType;
+
+typedef enum
+{
+  GTK_STATE_NORMAL,
+  GTK_STATE_ACTIVE,
+  GTK_STATE_PRELIGHT,
+  GTK_STATE_SELECTED,
+  GTK_STATE_INSENSITIVE,
+  GTK_STATE_INCONSISTENT,
+  GTK_STATE_FOCUSED
+} GtkStateType;
+
+typedef enum
+{
+  GTK_SHADOW_NONE,
+  GTK_SHADOW_IN,
+  GTK_SHADOW_OUT,
+  GTK_SHADOW_ETCHED_IN,
+  GTK_SHADOW_ETCHED_OUT
+} GtkShadowType;
+
+typedef enum
+{
+  GTK_EXPANDER_COLLAPSED,
+  GTK_EXPANDER_SEMI_COLLAPSED,
+  GTK_EXPANDER_SEMI_EXPANDED,
+  GTK_EXPANDER_EXPANDED
+} GtkExpanderStyle;
+
+typedef enum
+{
+  GTK_ICON_SIZE_INVALID,
+  GTK_ICON_SIZE_MENU,
+  GTK_ICON_SIZE_SMALL_TOOLBAR,
+  GTK_ICON_SIZE_LARGE_TOOLBAR,
+  GTK_ICON_SIZE_BUTTON,
+  GTK_ICON_SIZE_DND,
+  GTK_ICON_SIZE_DIALOG
+} GtkIconSize;
+
+typedef enum
+{
+  GTK_ORIENTATION_HORIZONTAL,
+  GTK_ORIENTATION_VERTICAL
+} GtkOrientation;
+
+typedef enum
+{
+    FOREGROUND,
+    BACKGROUND,
+    TEXT_FOREGROUND,
+    TEXT_BACKGROUND,
+    FOCUS,
+    LIGHT,
+    DARK,
+    MID,
+    BLACK,
+    WHITE
+} ColorType;
+
+typedef enum
+{
+    GTK_FONT_NAME,
+    GTK_ICON_SIZES,
+    GTK_CURSOR_BLINK,
+    GTK_CURSOR_BLINK_TIME
+} Setting;
+
+typedef enum
+{
+  GTK_ARROW_UP,
+  GTK_ARROW_DOWN,
+  GTK_ARROW_LEFT,
+  GTK_ARROW_RIGHT,
+  GTK_ARROW_NONE
+} GtkArrowType;
+
+typedef enum
+{
+  GTK_TEXT_DIR_NONE,
+  GTK_TEXT_DIR_LTR,
+  GTK_TEXT_DIR_RTL
+} GtkTextDirection;
+
+typedef enum
+{
+  GTK_POS_LEFT,
+  GTK_POS_RIGHT,
+  GTK_POS_TOP,
+  GTK_POS_BOTTOM
+} GtkPositionType;
+
+/* SynthConstants */
+static const gint ENABLED    = 1 << 0;
+static const gint MOUSE_OVER = 1 << 1;
+static const gint PRESSED    = 1 << 2;
+static const gint DISABLED   = 1 << 3;
+static const gint FOCUSED    = 1 << 8;
+static const gint SELECTED   = 1 << 9;
+static const gint DEFAULT    = 1 << 10;
+
+typedef enum
+{
+  GTK_ANY,
+  GTK_1,
+  GTK_2,
+  GTK_3
+} GtkVersion;
+
+//------------------------------
+
+
+
+typedef enum {
+  GTK_RESPONSE_NONE = -1,
+  GTK_RESPONSE_REJECT = -2,
+  GTK_RESPONSE_ACCEPT = -3,
+  GTK_RESPONSE_DELETE_EVENT = -4,
+  GTK_RESPONSE_OK = -5,
+  GTK_RESPONSE_CANCEL = -6,
+  GTK_RESPONSE_CLOSE = -7,
+  GTK_RESPONSE_YES = -8,
+  GTK_RESPONSE_NO = -9,
+  GTK_RESPONSE_APPLY = -10,
+  GTK_RESPONSE_HELP = -11
+} GtkResponseType;
+
+typedef enum {
+  GTK_FILE_CHOOSER_ACTION_OPEN,
+  GTK_FILE_CHOOSER_ACTION_SAVE,
+  GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+  GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
+} GtkFileChooserAction;
+
+typedef enum {
+  GTK_FILE_FILTER_FILENAME = 1 << 0,
+  GTK_FILE_FILTER_URI = 1 << 1,
+  GTK_FILE_FILTER_DISPLAY_NAME = 1 << 2,
+  GTK_FILE_FILTER_MIME_TYPE = 1 << 3
+} GtkFileFilterFlags;
+
+typedef enum {
+  GDK_COLORSPACE_RGB
+} GdkColorspace;
+
+typedef enum {
+    GDK_INTERP_NEAREST,
+    GDK_INTERP_TILES,
+    GDK_INTERP_BILINEAR,
+    GDK_INTERP_HYPER
+} GdkInterpType;
+
+typedef enum {
+  G_CONNECT_AFTER = 1 << 0, G_CONNECT_SWAPPED = 1 << 1
+} GConnectFlags;
+//------------------------------
+
+
+typedef void GError;
+typedef void GdkScreen;
+typedef void GtkWindow;
+typedef void GdkWindow;
+typedef void GClosure;
+typedef void GtkFileChooser;
+typedef void GtkFileFilter;
+typedef struct {
+    GtkFileFilterFlags contains;
+    const gchar *filename;
+    const gchar *uri;
+    const gchar *display_name;
+    const gchar *mime_type;
+} GtkFileFilterInfo;
+typedef gboolean (*GtkFileFilterFunc)(const GtkFileFilterInfo *filter_info,
+                                                                 gpointer data);
+typedef void (*GClosureNotify)(gpointer data, GClosure *closure);
+typedef void (*GDestroyNotify)(gpointer data);
+typedef void (*GCallback)(void);
+
+
+typedef struct GtkApi {
+    int version;
+    gboolean (*show_uri_load)(JNIEnv *env);
+    gboolean (*unload)();
+    void (*flush_event_loop)();
+    gchar* (*gtk_check_version)(guint required_major, guint required_minor,
+                                guint required_micro);
+    jobject (*get_setting)(JNIEnv *env, Setting property);
+
+    void (*paint_arrow)(WidgetType widget_type, GtkStateType state_type,
+        GtkShadowType shadow_type, const gchar *detail,
+        gint x, gint y, gint width, gint height,
+        GtkArrowType arrow_type, gboolean fill);
+    void (*paint_box)(WidgetType widget_type, GtkStateType state_type,
+                        GtkShadowType shadow_type, const gchar *detail,
+                        gint x, gint y, gint width, gint height,
+                        gint synth_state, GtkTextDirection dir);
+    void (*paint_box_gap)(WidgetType widget_type, GtkStateType state_type,
+            GtkShadowType shadow_type, const gchar *detail,
+            gint x, gint y, gint width, gint height,
+            GtkPositionType gap_side, gint gap_x, gint gap_width);
+    void (*paint_expander)(WidgetType widget_type, GtkStateType state_type,
+            const gchar *detail, gint x, gint y, gint width, gint height,
+            GtkExpanderStyle expander_style);
+    void (*paint_extension)(WidgetType widget_type, GtkStateType state_type,
+            GtkShadowType shadow_type, const gchar *detail,
+            gint x, gint y, gint width, gint height, GtkPositionType gap_side);
+    void (*paint_flat_box)(WidgetType widget_type, GtkStateType state_type,
+            GtkShadowType shadow_type, const gchar *detail,
+            gint x, gint y, gint width, gint height, gboolean has_focus);
+    void (*paint_focus)(WidgetType widget_type, GtkStateType state_type,
+            const char *detail, gint x, gint y, gint width, gint height);
+    void (*paint_handle)(WidgetType widget_type, GtkStateType state_type,
+           GtkShadowType shadow_type, const gchar *detail,
+           gint x, gint y, gint width, gint height, GtkOrientation orientation);
+    void (*paint_hline)(WidgetType widget_type, GtkStateType state_type,
+            const gchar *detail, gint x, gint y, gint width, gint height);
+    void (*paint_vline)(WidgetType widget_type, GtkStateType state_type,
+            const gchar *detail, gint x, gint y, gint width, gint height);
+    void (*paint_option)(WidgetType widget_type, gint synth_state,
+             const gchar *detail, gint x, gint y, gint width, gint height);
+    void (*paint_shadow)(WidgetType widget_type, GtkStateType state_type,
+                           GtkShadowType shadow_type, const gchar *detail,
+                           gint x, gint y, gint width, gint height,
+                           gint synth_state, GtkTextDirection dir);
+    void (*paint_slider)(WidgetType widget_type, GtkStateType state_type,
+            GtkShadowType shadow_type, const gchar *detail,
+            gint x, gint y, gint width, gint height, GtkOrientation orientation,
+            gboolean has_focus);
+    void (*paint_background)(WidgetType widget_type, GtkStateType state_type,
+            gint x, gint y, gint width, gint height);
+    void (*paint_check)(WidgetType widget_type, gint synth_state,
+        const gchar *detail, gint x, gint y, gint width, gint height);
+    void (*set_range_value)(WidgetType widget_type, jdouble value,
+                              jdouble min, jdouble max, jdouble visible);
+
+    void (*init_painting)(JNIEnv *env, gint w, gint h);
+    gint (*copy_image)(gint *dest, gint width, gint height);
+
+    gint (*get_xthickness)(JNIEnv *env, WidgetType widget_type);
+    gint (*get_ythickness)(JNIEnv *env, WidgetType widget_type);
+    gint (*get_color_for_state)(JNIEnv *env, WidgetType widget_type,
+                                  GtkStateType state_type, ColorType color_type);
+    jobject (*get_class_value)(JNIEnv *env, WidgetType widget_type,
+                               const char* key);
+
+    jstring (*get_pango_font_name)(JNIEnv *env, WidgetType widget_type);
+    jboolean (*get_icon_data)(JNIEnv *env, gint widget_type,
+                    const gchar *stock_id, GtkIconSize size,
+                    GtkTextDirection direction, const char *detail,
+                    jmethodID icon_upcall_method, jobject this);
+    jboolean (*get_file_icon_data)(JNIEnv *env, const char *filename,
+                    GError **error, jmethodID icon_upcall_method, jobject this);
+    void (*gdk_threads_enter)(void);
+    void (*gdk_threads_leave)(void);
+    gboolean (*gtk_show_uri)(GdkScreen *screen, const gchar *uri,
+                                             guint32 timestamp, GError **error);
+    gboolean (*get_drawable_data)(JNIEnv *env, jintArray pixelArray,
+                                       jint x, jint y, jint width, jint height,
+                                       jint jwidth, int dx, int dy, jint scale);
+    void (*g_free)(gpointer mem);
+
+
+    gchar* (*gtk_file_chooser_get_filename)(GtkFileChooser *chooser);
+    void (*gtk_widget_hide)(void* widget);
+    void (*gtk_main_quit)(void);
+    void* (*gtk_file_chooser_dialog_new)(const gchar *title,
+        GtkWindow *parent, GtkFileChooserAction action,
+        const gchar *first_button_text, ...);
+    gboolean (*gtk_file_chooser_set_current_folder)(GtkFileChooser *chooser,
+        const gchar *filename);
+    gboolean (*gtk_file_chooser_set_filename)(GtkFileChooser *chooser,
+        const char *filename);
+    void (*gtk_file_chooser_set_current_name)(GtkFileChooser *chooser,
+        const gchar *name);
+    void (*gtk_file_filter_add_custom)(GtkFileFilter *filter,
+        GtkFileFilterFlags needed, GtkFileFilterFunc func, gpointer data,
+        GDestroyNotify notify);
+    void (*gtk_file_chooser_set_filter)(GtkFileChooser *chooser,
+        GtkFileFilter *filter);
+    GType (*gtk_file_chooser_get_type)(void);
+    GtkFileFilter* (*gtk_file_filter_new)(void);
+    void (*gtk_file_chooser_set_do_overwrite_confirmation)(
+        GtkFileChooser *chooser, gboolean do_overwrite_confirmation);
+    void (*gtk_file_chooser_set_select_multiple)(
+        GtkFileChooser *chooser, gboolean select_multiple);
+    gchar* (*gtk_file_chooser_get_current_folder)(GtkFileChooser *chooser);
+    GSList* (*gtk_file_chooser_get_filenames)(GtkFileChooser *chooser);
+    guint (*gtk_g_slist_length)(GSList *list);
+    gulong (*g_signal_connect_data)(gpointer instance,
+        const gchar *detailed_signal, GCallback c_handler, gpointer data,
+        GClosureNotify destroy_data, GConnectFlags connect_flags);
+    void (*gtk_widget_show)(void *widget);
+    void (*gtk_main)(void);
+    guint (*gtk_main_level)(void);
+    gchar* (*g_path_get_dirname) (const gchar *file_name);
+    XID (*gdk_x11_drawable_get_xid) (void *drawable);
+    void (*gtk_widget_destroy)(void *widget);
+    void (*gtk_window_present)(void *window);
+    void (*gtk_window_move)(void *window, gint x, gint y);
+    void (*gtk_window_resize)(void *window, gint width, gint height);
+    GdkWindow *(*get_window)(void *widget);
+
+    void (*g_object_unref)(gpointer object);
+    GList* (*g_list_append) (GList *list, gpointer data);
+    void (*g_list_free) (GList *list);
+    void (*g_list_free_full) (GList *list, GDestroyNotify free_func);
+} GtkApi;
+
+gboolean gtk_load(JNIEnv *env, GtkVersion version, gboolean verbose);
+gboolean gtk_check_version(GtkVersion version);
+
+extern GtkApi* gtk;
+
+#endif /* !_GTK_INTERFACE_H */
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/sun_awt_X11_GtkFileDialogPeer.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,11 +28,12 @@
 #include <jni_util.h>
 #include <string.h>
 #include <X11/X.h>
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 #include "sun_awt_X11_GtkFileDialogPeer.h"
 #include "java_awt_FileDialog.h"
 #include "debug_assert.h"
 
+typedef void GtkWidget;
 static JavaVM *jvm;
 
 /* To cache some method IDs */
@@ -90,20 +91,20 @@
     {
         // Callbacks from GTK signals are made within the GTK lock
         // So, within a signal handler there is no need to call
-        // gdk_threads_enter() / fp_gdk_threads_leave()
+        // gdk_threads_enter() / gtk->gdk_threads_leave()
         if (!isSignalHandler) {
-            fp_gdk_threads_enter();
+            gtk->gdk_threads_enter();
         }
 
-        fp_gtk_widget_hide (dialog);
-        fp_gtk_widget_destroy (dialog);
+        gtk->gtk_widget_hide (dialog);
+        gtk->gtk_widget_destroy (dialog);
 
-        fp_gtk_main_quit ();
+        gtk->gtk_main_quit ();
 
         (*env)->SetLongField(env, jpeer, widgetFieldID, 0);
 
         if (!isSignalHandler) {
-            fp_gdk_threads_leave();
+            gtk->gdk_threads_leave();
         }
     }
 
@@ -133,16 +134,16 @@
 {
     GtkWidget * dialog;
 
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
 
     dialog = (GtkWidget*)jlong_to_ptr(
             (*env)->GetLongField(env, jpeer, widgetFieldID));
 
     if (dialog != NULL) {
-        fp_gtk_window_present((GtkWindow*)dialog);
+        gtk->gtk_window_present((GtkWindow*)dialog);
     }
 
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -155,21 +156,21 @@
 {
     GtkWindow* dialog;
 
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
 
     dialog = (GtkWindow*)jlong_to_ptr(
         (*env)->GetLongField(env, jpeer, widgetFieldID));
 
     if (dialog != NULL) {
         if (x >= 0 && y >= 0) {
-            fp_gtk_window_move(dialog, (gint)x, (gint)y);
+            gtk->gtk_window_move(dialog, (gint)x, (gint)y);
         }
         if (width > 0 && height > 0) {
-            fp_gtk_window_resize(dialog, (gint)width, (gint)height);
+            gtk->gtk_window_resize(dialog, (gint)width, (gint)height);
         }
     }
 
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -182,18 +183,18 @@
     gboolean isAllDirsSame = TRUE;
 
     while (it) {
-        gchar* dir = fp_g_path_get_dirname((gchar*) it->data);
+        gchar* dir = gtk->g_path_get_dirname((gchar*) it->data);
 
         if (prevDir && strcmp(prevDir, dir) != 0) {
             isAllDirsSame = FALSE;
-            fp_g_free(dir);
+            gtk->g_free(dir);
             break;
         }
 
         if (!prevDir) {
             prevDir = strdup(dir);
         }
-        fp_g_free(dir);
+        gtk->g_free(dir);
 
         it = it->next;
     }
@@ -233,7 +234,7 @@
         return NULL;
     }
 
-    array = (*env)->NewObjectArray(env, fp_gtk_g_slist_length(list), stringCls, NULL);
+    array = (*env)->NewObjectArray(env, gtk->gtk_g_slist_length(list), stringCls, NULL);
     if (array == NULL) {
         (*env)->ExceptionClear(env);
         JNU_ThrowInternalError(env, "Could not instantiate array files array");
@@ -287,7 +288,7 @@
     filenames = NULL;
 
     if (responseId == GTK_RESPONSE_ACCEPT) {
-        filenames = fp_gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog));
+        filenames = gtk->gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(aDialog));
     }
 
     jfilenames = toFilenamesArray(env, filenames, &jcurrent_folder);
@@ -318,7 +319,7 @@
         JNU_CHECK_EXCEPTION(env);
     }
 
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
 
     const char *title = jtitle == NULL? "": (*env)->GetStringUTFChars(env, jtitle, 0);
     if (title == NULL) {
@@ -329,19 +330,19 @@
 
     if (mode == java_awt_FileDialog_SAVE) {
         /* Save action */
-        dialog = fp_gtk_file_chooser_dialog_new(title, NULL,
+        dialog = gtk->gtk_file_chooser_dialog_new(title, NULL,
                 GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL,
                 GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, NULL);
     }
     else {
         /* Default action OPEN */
-        dialog = fp_gtk_file_chooser_dialog_new(title, NULL,
+        dialog = gtk->gtk_file_chooser_dialog_new(title, NULL,
                 GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,
                 GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
 
         /* Set multiple selection mode, that is allowed only in OPEN action */
         if (multiple) {
-            fp_gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog),
+            gtk->gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog),
                     multiple);
         }
     }
@@ -358,7 +359,7 @@
             JNU_ThrowOutOfMemoryError(env, "Could not get dir");
             return;
         }
-        fp_gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
+        gtk->gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dir);
         (*env)->ReleaseStringUTFChars(env, jdir, dir);
     }
 
@@ -371,47 +372,48 @@
             return;
         }
         if (mode == java_awt_FileDialog_SAVE) {
-            fp_gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename);
+            gtk->gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), filename);
         } else {
-            fp_gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
+            gtk->gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), filename);
         }
         (*env)->ReleaseStringUTFChars(env, jfile, filename);
     }
 
     /* Set the file filter */
     if (jfilter != NULL) {
-        filter = fp_gtk_file_filter_new();
-        fp_gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
+        filter = gtk->gtk_file_filter_new();
+        gtk->gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
                 filenameFilterCallback, jpeer, NULL);
-        fp_gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
+        gtk->gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), filter);
     }
 
     /* Other Properties */
-    if (fp_gtk_check_version(2, 8, 0) == NULL) {
-        fp_gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(
+    if (gtk->gtk_check_version(2, 8, 0) == NULL ||
+                                     gtk->gtk_check_version(3, 0, 0) == NULL) {
+        gtk->gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(
                 dialog), TRUE);
     }
 
     /* Set the initial location */
     if (x >= 0 && y >= 0) {
-        fp_gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y);
+        gtk->gtk_window_move((GtkWindow*)dialog, (gint)x, (gint)y);
 
         // NOTE: it doesn't set the initial size for the file chooser
         // as it seems like the file chooser overrides the size internally
     }
 
-    fp_g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(
-            handle_response), jpeer);
+    gtk->g_signal_connect_data(dialog, "response", G_CALLBACK(
+            handle_response), jpeer, 0, 0);
 
     (*env)->SetLongField(env, jpeer, widgetFieldID, ptr_to_jlong(dialog));
 
-    fp_gtk_widget_show(dialog);
+    gtk->gtk_widget_show(dialog);
 
-    XID xid = fp_gdk_x11_drawable_get_xid(dialog->window);
+    XID xid = gtk->gdk_x11_drawable_get_xid(gtk->get_window(dialog));
     if( (*env)->CallBooleanMethod(env, jpeer, setWindowMethodID, xid) ) {
-        fp_gtk_main();
+        gtk->gtk_main();
     }
 
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKEngine.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, 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
@@ -24,9 +24,24 @@
  */
 
 #include <stdlib.h>
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 #include "com_sun_java_swing_plaf_gtk_GTKEngine.h"
 
+/* Static buffer for conversion from java.lang.String to UTF-8 */
+static char conversionBuffer[CONV_BUFFER_SIZE];
+
+const char *getStrFor(JNIEnv *env, jstring val)
+{
+    int length = (*env)->GetStringLength(env, val);
+    if (length > CONV_BUFFER_SIZE-1)
+    {
+        length = CONV_BUFFER_SIZE-1;
+    }
+
+    (*env)->GetStringUTFRegion(env, val, 0, length, conversionBuffer);
+    return conversionBuffer;
+}
+
 /*
  * Class:     com_sun_java_swing_plaf_gtk_GTKEngine
  * Method:    native_paint_arrow
@@ -38,10 +53,10 @@
         jint widget_type, jint state, jint shadow_type, jstring detail,
         jint x, jint y, jint w, jint h, jint arrow_type)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_arrow(widget_type, state, shadow_type, getStrFor(env, detail),
             x, y, w, h, arrow_type, TRUE);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -56,10 +71,10 @@
         jint x, jint y, jint w, jint h,
         jint synth_state, jint dir)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_box(widget_type, state, shadow_type, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_box(widget_type, state, shadow_type, getStrFor(env, detail),
                    x, y, w, h, synth_state, dir);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -74,10 +89,10 @@
         jint x, jint y, jint w, jint h,
         jint gap_side, jint gap_x, jint gap_w)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_box_gap(widget_type, state, shadow_type, getStrFor(env, detail),
             x, y, w, h, gap_side, gap_x, gap_w);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -91,10 +106,10 @@
         jint widget_type, jint synth_state, jstring detail,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_check(widget_type, synth_state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_check(widget_type, synth_state, getStrFor(env, detail),
                      x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -108,10 +123,10 @@
         jint widget_type, jint state, jstring detail,
         jint x, jint y, jint w, jint h, jint expander_style)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_expander(widget_type, state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_expander(widget_type, state, getStrFor(env, detail),
             x, y, w, h, expander_style);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -125,10 +140,10 @@
         jint widget_type, jint state, jint shadow_type, jstring detail,
         jint x, jint y, jint w, jint h, jint placement)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_extension(widget_type, state, shadow_type,
+    gtk->gdk_threads_enter();
+    gtk->paint_extension(widget_type, state, shadow_type,
             getStrFor(env, detail), x, y, w, h, placement);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -142,10 +157,10 @@
         jint widget_type, jint state, jint shadow_type, jstring detail,
         jint x, jint y, jint w, jint h, jboolean has_focus)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_flat_box(widget_type, state, shadow_type,
+    gtk->gdk_threads_enter();
+    gtk->paint_flat_box(widget_type, state, shadow_type,
             getStrFor(env, detail), x, y, w, h, has_focus);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -159,10 +174,10 @@
         jint widget_type, jint state, jstring detail,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_focus(widget_type, state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_focus(widget_type, state, getStrFor(env, detail),
             x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -176,10 +191,10 @@
         jint widget_type, jint state, jint shadow_type, jstring detail,
         jint x, jint y, jint w, jint h, jint orientation)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_handle(widget_type, state, shadow_type, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_handle(widget_type, state, shadow_type, getStrFor(env, detail),
             x, y, w, h, orientation);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -193,10 +208,10 @@
         jint widget_type, jint state, jstring detail,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_hline(widget_type, state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_hline(widget_type, state, getStrFor(env, detail),
             x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -210,10 +225,10 @@
         jint widget_type, jint synth_state, jstring detail,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_option(widget_type, synth_state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_option(widget_type, synth_state, getStrFor(env, detail),
                       x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -228,10 +243,10 @@
         jint x, jint y, jint w, jint h,
         jint synth_state, jint dir)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_shadow(widget_type, state, shadow_type, getStrFor(env, detail),
                       x, y, w, h, synth_state, dir);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -243,12 +258,12 @@
 Java_com_sun_java_swing_plaf_gtk_GTKEngine_native_1paint_1slider(
         JNIEnv *env, jobject this,
         jint widget_type, jint state, jint shadow_type, jstring detail,
-        jint x, jint y, jint w, jint h, jint orientation)
+        jint x, jint y, jint w, jint h, jint orientation, jboolean has_focus)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_slider(widget_type, state, shadow_type, getStrFor(env, detail),
-            x, y, w, h, orientation);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    gtk->paint_slider(widget_type, state, shadow_type, getStrFor(env, detail),
+            x, y, w, h, orientation, has_focus);
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -262,10 +277,10 @@
         jint widget_type, jint state, jstring detail,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_paint_vline(widget_type, state, getStrFor(env, detail),
+    gtk->gdk_threads_enter();
+    gtk->paint_vline(widget_type, state, getStrFor(env, detail),
             x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -278,9 +293,9 @@
         JNIEnv *env, jobject this, jint widget_type, jint state,
         jint x, jint y, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk_paint_background(widget_type, state, x, y, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    gtk->paint_background(widget_type, state, x, y, w, h);
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -292,9 +307,9 @@
 Java_com_sun_java_swing_plaf_gtk_GTKEngine_nativeStartPainting(
         JNIEnv *env, jobject this, jint w, jint h)
 {
-    fp_gdk_threads_enter();
-    gtk2_init_painting(env, w, h);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    gtk->init_painting(env, w, h);
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -308,9 +323,9 @@
 {
     jint transparency;
     gint *buffer = (gint*) (*env)->GetPrimitiveArrayCritical(env, dest, 0);
-    fp_gdk_threads_enter();
-    transparency = gtk2_copy_image(buffer, width, height);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    transparency = gtk->copy_image(buffer, width, height);
+    gtk->gdk_threads_leave();
     (*env)->ReleasePrimitiveArrayCritical(env, dest, buffer, 0);
     return transparency;
 }
@@ -324,7 +339,9 @@
         JNIEnv *env, jobject this)
 {
     // Note that flush_gtk_event_loop takes care of locks (7053002)
-    flush_gtk_event_loop();
+    gtk->gdk_threads_enter();
+    gtk->flush_event_loop();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -336,9 +353,9 @@
         JNIEnv *env, jobject this, jint property)
 {
     jobject obj;
-    fp_gdk_threads_enter();
-    obj = gtk2_get_setting(env, property);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    obj = gtk->get_setting(env, property);
+    gtk->gdk_threads_leave();
     return obj;
 }
 
@@ -352,7 +369,7 @@
         JNIEnv *env, jobject this, jint widget_type,
         jdouble value, jdouble min, jdouble max, jdouble visible)
 {
-    fp_gdk_threads_enter();
-    gtk2_set_range_value(widget_type, value, min, max, visible);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    gtk->set_range_value(widget_type, value, min, max, visible);
+    gtk->gdk_threads_leave();
 }
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/awt/swing_GTKStyle.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,9 +24,12 @@
  */
 
 #include <stdlib.h>
-#include "gtk2_interface.h"
+#include <stdio.h>
+#include "gtk_interface.h"
 #include "com_sun_java_swing_plaf_gtk_GTKStyle.h"
 
+const char *getStrFor(JNIEnv *env, jstring val);
+
 /*
  * Class:     com_sun_java_swing_plaf_gtk_GTKStyle
  * Method:    nativeGetXThickness
@@ -37,9 +40,9 @@
     JNIEnv *env, jclass klass, jint widget_type)
 {
     jint ret;
-    fp_gdk_threads_enter();
-    ret = gtk2_get_xthickness(env, widget_type);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    ret = gtk->get_xthickness(env, widget_type);
+    gtk->gdk_threads_leave();
     return ret;
 }
 
@@ -53,9 +56,9 @@
     JNIEnv *env, jclass klass, jint widget_type)
 {
     jint ret;
-    fp_gdk_threads_enter();
-    ret = gtk2_get_ythickness(env, widget_type);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    ret = gtk->get_ythickness(env, widget_type);
+    gtk->gdk_threads_leave();
     return ret;
 }
 
@@ -70,9 +73,9 @@
     jint state_type, jint type_id)
 {
     jint ret;
-    fp_gdk_threads_enter();
-    ret = gtk2_get_color_for_state(env, widget_type, state_type, type_id);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    ret = gtk->get_color_for_state(env, widget_type, state_type, type_id);
+    gtk->gdk_threads_leave();
     return ret;
 }
 
@@ -86,9 +89,9 @@
     JNIEnv *env, jclass klass, jint widget_type, jstring key)
 {
     jobject ret;
-    fp_gdk_threads_enter();
-    ret = gtk2_get_class_value(env, widget_type, key);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    ret = gtk->get_class_value(env, widget_type, getStrFor(env, key));
+    gtk->gdk_threads_leave();
     return ret;
 }
 
@@ -102,8 +105,8 @@
     JNIEnv *env, jclass klass, jint widget_type)
 {
     jstring ret;
-    fp_gdk_threads_enter();
-    ret = gtk2_get_pango_font_name(env, widget_type);
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    ret = gtk->get_pango_font_name(env, widget_type);
+    gtk->gdk_threads_leave();
     return ret;
 }
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/java2d/x11/XRBackendNative.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -72,8 +72,8 @@
 
 #include <dlfcn.h>
 
-#if defined(__solaris__) || defined(_AIX)
-/* Solaris 10 and AIX will not have these symbols at runtime */
+#if defined(__solaris__)
+/* Solaris 10 will not have these symbols at compile time */
 
 typedef Picture (*XRenderCreateLinearGradientFuncType)
                                      (Display *dpy,
@@ -147,7 +147,22 @@
         return JNI_FALSE;
     }
 
-#if defined(__solaris__) || defined(_AIX)
+#if defined(_AIX)
+    // On AIX we have to use a special syntax because the shared libraries are packed in
+    // multi-architecture archives. We first try to load the system default libXrender
+    // which is contained in the 'X11.base.lib' fileset starting with AIX 6.1
+    xrenderlib = dlopen("libXrender.a(shr_64.o)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER);
+    if (xrenderlib == NULL) {
+      // If the latter wasn't successful, we also try to load the version under /opt/freeware
+      // This may be downloaded from the "AIX Toolbox for Linux Applications" even for AIX 5.3
+      xrenderlib = dlopen("libXrender.a(libXrender.so.0)", RTLD_GLOBAL | RTLD_LAZY | RTLD_MEMBER);
+    }
+    if (xrenderlib != NULL) {
+      dlclose(xrenderlib);
+    } else {
+      available = JNI_FALSE;
+    }
+#elif defined(__solaris__)
     xrenderlib = dlopen("libXrender.so",RTLD_GLOBAL|RTLD_LAZY);
     if (xrenderlib != NULL) {
 
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XToolkit.c	Wed Jul 05 21:39:33 2017 +0200
@@ -354,7 +354,6 @@
 
 static void     waitForEvents(JNIEnv *, jlong);
 static void     awt_pipe_init();
-static void     processOneEvent(XtInputMask iMask);
 static Boolean  performPoll(JNIEnv *, jlong);
 static void     wakeUp();
 static void     update_poll_timeout(int timeout_control);
@@ -614,7 +613,7 @@
 } /* get_poll_timeout() */
 
 /*
- * Waits for X/Xt events to appear on the pipe. Returns only when
+ * Waits for X events to appear on the pipe. Returns only when
  * it is likely (but not definite) that there are events waiting to
  * be processed.
  *
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Desktop.c	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,7 @@
  */
 
 #include "jni_util.h"
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 #include "gnome_interface.h"
 
 static gboolean gtk_has_been_loaded = FALSE;
@@ -36,14 +36,14 @@
  * Signature: ()Z
  */
 JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XDesktopPeer_init
-  (JNIEnv *env, jclass cls)
+  (JNIEnv *env, jclass cls, jint version, jboolean verbose)
 {
 
     if (gtk_has_been_loaded || gnome_has_been_loaded) {
         return JNI_TRUE;
     }
 
-    if (gtk2_load(env) && gtk2_show_uri_load(env)) {
+    if (gtk_load(env, version, verbose) && gtk->show_uri_load(env)) {
         gtk_has_been_loaded = TRUE;
         return JNI_TRUE;
     } else if (gnome_load()) {
@@ -74,9 +74,9 @@
     }
 
     if (gtk_has_been_loaded) {
-        fp_gdk_threads_enter();
-        success = fp_gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL);
-        fp_gdk_threads_leave();
+        gtk->gdk_threads_enter();
+        success = gtk->gtk_show_uri(NULL, url_c, GDK_CURRENT_TIME, NULL);
+        gtk->gdk_threads_leave();
     } else if (gnome_has_been_loaded) {
         success = (*gnome_url_show)(url_c, NULL);
     }
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.c	Wed Jul 05 21:39:33 2017 +0200
@@ -109,7 +109,7 @@
  * Signature: (Ljava/lang/String;)Z
  */
 JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XTaskbarPeer_init
-(JNIEnv *env, jclass cls, jstring jname) {
+(JNIEnv *env, jclass cls, jstring jname, jint version, jboolean verbose) {
     jclass clazz;
 
     jTaskbarCls = (*env)->NewGlobalRef(env, cls);
@@ -121,7 +121,7 @@
     CHECK_NULL_RETURN(
             jMenuItemGetLabel = (*env)->GetMethodID(env, clazz, "getLabel", "()Ljava/lang/String;"), JNI_FALSE);
 
-    if (gtk2_load(env) && unity_load()) {
+    if (gtk_load(env, version, verbose) && unity_load()) {
         const gchar* name = (*env)->GetStringUTFChars(env, jname, NULL);
         if (name) {
             entry = fp_unity_launcher_entry_get_for_desktop_file(name);
@@ -139,9 +139,9 @@
  */
 JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_runloop
 (JNIEnv *env, jclass cls) {
-    fp_gdk_threads_enter();
-    fp_gtk_main();
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_enter();
+    gtk->gtk_main();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -151,14 +151,14 @@
  */
 JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setBadge
 (JNIEnv *env, jobject obj, jlong value, jboolean visible) {
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
     fp_unity_launcher_entry_set_count(entry, value);
     fp_unity_launcher_entry_set_count_visible(entry, visible);
     DbusmenuMenuitem* m;
     if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
         fp_unity_launcher_entry_set_quicklist(entry, m);
     }
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -168,13 +168,13 @@
  */
 JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setUrgent
 (JNIEnv *env, jobject obj, jboolean urgent) {
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
     fp_unity_launcher_entry_set_urgent(entry, urgent);
     DbusmenuMenuitem* m;
     if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
         fp_unity_launcher_entry_set_quicklist(entry, m);
     }
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 /*
@@ -184,14 +184,14 @@
  */
 JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_updateProgress
 (JNIEnv *env, jobject obj, jdouble value, jboolean visible) {
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
     fp_unity_launcher_entry_set_progress(entry, value);
     fp_unity_launcher_entry_set_progress_visible(entry, visible);
     DbusmenuMenuitem* m;
     if (m = fp_unity_launcher_entry_get_quicklist(entry)) {
         fp_unity_launcher_entry_set_quicklist(entry, m);
     }
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
 
 void deleteGlobalRef(gpointer data) {
@@ -209,7 +209,7 @@
         }
         elem = (*env)->NewGlobalRef(env, elem);
 
-        globalRefs = fp_g_list_append(globalRefs, elem);
+        globalRefs = gtk->g_list_append(globalRefs, elem);
 
         jstring jlabel = (jstring) (*env)->CallObjectMethod(env, elem, jMenuItemGetLabel);
         if (!(*env)->ExceptionCheck(env) && jlabel) {
@@ -224,7 +224,8 @@
 
                 (*env)->ReleaseStringUTFChars(env, jlabel, label);
                 fp_dbusmenu_menuitem_child_append(menu, mi);
-                fp_g_signal_connect(mi, "item_activated", G_CALLBACK(callback), elem);
+                gtk->g_signal_connect_data(mi, "item_activated",
+                                           G_CALLBACK(callback), elem, NULL, 0);
             }
         }
     }
@@ -238,7 +239,7 @@
 JNIEXPORT void JNICALL Java_sun_awt_X11_XTaskbarPeer_setNativeMenu
 (JNIEnv *env, jobject obj, jobjectArray items) {
 
-    fp_gdk_threads_enter();
+    gtk->gdk_threads_enter();
 
     if (!menu) {
         menu = fp_dbusmenu_menuitem_new();
@@ -247,14 +248,14 @@
     fp_unity_launcher_entry_set_quicklist(entry, menu);
 
     GList* list = fp_dbusmenu_menuitem_take_children(menu);
-    fp_g_list_free_full(list, fp_g_object_unref);
+    gtk->g_list_free_full(list, gtk->g_object_unref);
 
-    fp_g_list_free_full(globalRefs, deleteGlobalRef);
+    gtk->g_list_free_full(globalRefs, deleteGlobalRef);
     globalRefs = NULL;
 
     if (items) {
         fill_menu(env, items);
     }
 
-    fp_gdk_threads_leave();
+    gtk->gdk_threads_leave();
 }
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/awt_Taskbar.h	Wed Jul 05 21:39:33 2017 +0200
@@ -26,7 +26,7 @@
 #ifndef AWT_TASKBAR_H
 #define AWT_TASKBAR_H
 
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 
 typedef void UnityLauncherEntry;
 typedef void DbusmenuMenuitem;
--- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/gnome_interface.h	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
 
 #ifndef _GNOME_INTERFACE_H
 #define _GNOME_INTERFACE_H
-#include "gtk2_interface.h"
+#include "gtk_interface.h"
 #include <dlfcn.h>
 #include <jvm_md.h>
 #include <jni.h>
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WComponentPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -28,7 +28,6 @@
 import java.awt.peer.*;
 import java.awt.image.VolatileImage;
 import sun.awt.RepaintArea;
-import sun.awt.CausedFocusEvent;
 import sun.awt.image.SunVolatileImage;
 import sun.awt.image.ToolkitImage;
 import java.awt.image.BufferedImage;
@@ -321,7 +320,7 @@
                   WKeyboardFocusManagerPeer.shouldFocusOnClick((Component)target))
               {
                   WKeyboardFocusManagerPeer.requestFocusFor((Component)target,
-                                                            CausedFocusEvent.Cause.MOUSE_EVENT);
+                                                            FocusEvent.Cause.MOUSE_EVENT);
               }
               break;
         }
@@ -687,7 +686,7 @@
     @Override
     public boolean requestFocus(Component lightweightChild, boolean temporary,
                                 boolean focusedWindowChangeAllowed, long time,
-                                CausedFocusEvent.Cause cause)
+                                FocusEvent.Cause cause)
     {
         if (WKeyboardFocusManagerPeer.
             processSynchronousLightweightTransfer((Component)target, lightweightChild, temporary,
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WFileDialogPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -25,6 +25,7 @@
 package sun.awt.windows;
 
 import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.dnd.DropTarget;
 import java.awt.peer.*;
 import java.io.File;
@@ -34,7 +35,6 @@
 import java.util.ResourceBundle;
 import java.util.MissingResourceException;
 import java.util.Vector;
-import sun.awt.CausedFocusEvent;
 import sun.awt.AWTAccessor;
 
 final class WFileDialogPeer extends WWindowPeer implements FileDialogPeer {
@@ -282,7 +282,7 @@
     @Override
     public boolean requestFocus
          (Component lightweightChild, boolean temporary,
-          boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+          boolean focusedWindowChangeAllowed, long time, Cause cause)
     {
         return false;
     }
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WKeyboardFocusManagerPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 import sun.awt.AWTAccessor;
 import sun.awt.AWTAccessor.ComponentAccessor;
 import sun.awt.KeyboardFocusManagerPeerImpl;
-import sun.awt.CausedFocusEvent;
+import java.awt.event.FocusEvent.Cause;
 
 final class WKeyboardFocusManagerPeer extends KeyboardFocusManagerPeerImpl {
     static native void setNativeFocusOwner(ComponentPeer peer);
@@ -75,7 +75,7 @@
                                        boolean temporary,
                                        boolean focusedWindowChangeAllowed,
                                        long time,
-                                       CausedFocusEvent.Cause cause)
+                                       Cause cause)
     {
         // TODO: do something to eliminate this forwarding
         return KeyboardFocusManagerPeerImpl.deliverFocus(lightweightChild,
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WPrintDialogPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,11 +26,11 @@
 package sun.awt.windows;
 
 import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
 import java.awt.peer.DialogPeer;
 import java.awt.peer.ComponentPeer;
 import java.awt.dnd.DropTarget;
 import java.util.Vector;
-import sun.awt.CausedFocusEvent;
 import sun.awt.AWTAccessor;
 
 class WPrintDialogPeer extends WWindowPeer implements DialogPeer {
@@ -153,7 +153,7 @@
     @Override
     public boolean requestFocus
          (Component lightweightChild, boolean temporary,
-          boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
+          boolean focusedWindowChangeAllowed, long time, Cause cause)
     {
 
         return false;
--- a/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/classes/sun/awt/windows/WWindowPeer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -300,11 +300,11 @@
         return getNativeWindowSize();
     }
 
-    public boolean requestWindowFocus(CausedFocusEvent.Cause cause) {
+    public boolean requestWindowFocus(FocusEvent.Cause cause) {
         if (!focusAllowedFor()) {
             return false;
         }
-        return requestWindowFocus(cause == CausedFocusEvent.Cause.MOUSE_EVENT);
+        return requestWindowFocus(cause == FocusEvent.Cause.MOUSE_EVENT);
     }
     private native boolean requestWindowFocus(boolean isMouseEventCause);
 
--- a/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.desktop/windows/native/libfontmanager/lcdglyph.c	Wed Jul 05 21:39:33 2017 +0200
@@ -157,6 +157,9 @@
     if (hBitmap != 0) { \
         DeleteObject(hBitmap); \
     } \
+    if (tmpBitmap != 0) { \
+        DeleteObject(tmpBitmap); \
+    } \
     if (dibImage != NULL) { \
         free(dibImage); \
     } \
@@ -196,6 +199,7 @@
     int bmWidth, bmHeight;
     int x, y;
     HBITMAP hBitmap = NULL, hOrigBM;
+    HBITMAP tmpBitmap = NULL;
     int gamma, orient;
 
     HWND hWnd = NULL;
@@ -250,6 +254,12 @@
     }
     oldFont = SelectObject(hMemoryDC, hFont);
 
+    tmpBitmap = CreateCompatibleBitmap(hDesktopDC, 1, 1);
+    if (tmpBitmap == NULL) {
+        FREE_AND_RETURN;
+    }
+    hOrigBM = (HBITMAP)SelectObject(hMemoryDC, tmpBitmap);
+
     memset(&textMetric, 0, sizeof(TEXTMETRIC));
     err = GetTextMetrics(hMemoryDC, &textMetric);
     if (err == 0) {
@@ -334,7 +344,7 @@
     if (hBitmap == NULL) {
         FREE_AND_RETURN;
     }
-    hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap);
+    SelectObject(hMemoryDC, hBitmap);
 
     /* Fill in black */
     rect.left = 0;
@@ -478,6 +488,7 @@
     ReleaseDC(hWnd, hDesktopDC);
     DeleteObject(hMemoryDC);
     DeleteObject(hBitmap);
+    DeleteObject(tmpBitmap);
 
     return ptr_to_jlong(glyphInfo);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,68 @@
+/*
+ * 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
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.function.Consumer;
+
+/**
+ * Implemented by classes that offer an asynchronous interface.
+ *
+ * PlainHttpConnection, AsyncSSLConnection AsyncSSLDelegate.
+ *
+ * setAsyncCallbacks() is called to set the callback for reading
+ * and error notification. Reads all happen on the selector thread, which
+ * must not block.
+ *
+ * Writing uses the same write() methods as used in blocking mode.
+ * Queues are employed on the writing side to buffer data while it is waiting
+ * to be sent. This strategy relies on HTTP/2 protocol flow control to stop
+ * outgoing queue from continually growing. Writes can be initiated by the
+ * calling thread, but if socket becomes full then the queue is emptied by
+ * the selector thread
+ *
+ */
+interface AsyncConnection {
+
+    /**
+     * Enables asynchronous sending and receiving mode. The given async
+     * receiver will receive all incoming data. asyncInput() will be called
+     * to trigger reads. asyncOutput() will be called to drive writes.
+     *
+     * The errorReceiver callback must be called when any fatal exception
+     * occurs. Connection is assumed to be closed afterwards.
+     *
+     * @param asyncReceiver
+     * @param errorReceiver
+     */
+    void setAsyncCallbacks(
+            Consumer<ByteBuffer> asyncReceiver,
+            Consumer<Throwable> errorReceiver);
+
+    /**
+     * Does whatever is required to start reading. Usually registers
+     * an event with the selector thread.
+     */
+    void startReading();
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -25,24 +25,27 @@
 package java.net.http;
 
 import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
 
 /**
  * Event handling interface from HttpClientImpl's selector.
  *
- * <p> If blockingChannel is true, then the channel will be put in blocking
+ * If BLOCKING is set, then the channel will be put in blocking
  * mode prior to handle() being called. If false, then it remains non-blocking.
+ *
+ * If REPEATING is set then the event is not cancelled after being posted.
  */
 abstract class AsyncEvent {
 
-    /**
-     * Implement this if channel should be made blocking before calling handle()
-     */
-    public interface Blocking { }
+    public static final int BLOCKING = 0x1; // non blocking if not set
+    public static final int REPEATING = 0x2; // one off event if not set
 
-    /**
-     * Implement this if channel should remain non-blocking before calling handle()
-     */
-    public interface NonBlocking { }
+    protected final int flags;
+
+    AsyncEvent(int flags) {
+        this.flags = flags;
+    }
 
     /** Returns the channel */
     public abstract SelectableChannel channel();
@@ -55,4 +58,12 @@
 
     /** Called when selector is shutting down. Abort all exchanges. */
     public abstract void abort();
+
+    public boolean blocking() {
+        return (flags & BLOCKING) != 0;
+    }
+
+    public boolean repeating() {
+        return (flags & REPEATING) != 0;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+
+/**
+ * Asynchronous version of SSLConnection.
+ */
+class AsyncSSLConnection extends HttpConnection implements AsyncConnection {
+    final AsyncSSLDelegate sslDelegate;
+    final PlainHttpConnection delegate;
+
+    AsyncSSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) {
+        super(addr, client);
+        delegate = new PlainHttpConnection(addr, client);
+        sslDelegate = new AsyncSSLDelegate(delegate, client, ap);
+    }
+
+    @Override
+    public void connect() throws IOException, InterruptedException {
+        delegate.connect();
+    }
+
+    @Override
+    public CompletableFuture<Void> connectAsync() {
+        return delegate.connectAsync();
+    }
+
+    @Override
+    boolean connected() {
+        return delegate.connected();
+    }
+
+    @Override
+    boolean isSecure() {
+        return true;
+    }
+
+    @Override
+    boolean isProxied() {
+        return false;
+    }
+
+    @Override
+    SocketChannel channel() {
+        return delegate.channel();
+    }
+
+    @Override
+    ConnectionPool.CacheKey cacheKey() {
+        return ConnectionPool.cacheKey(address, null);
+    }
+
+    @Override
+    synchronized long write(ByteBuffer[] buffers, int start, int number) throws IOException {
+        ByteBuffer[] bufs = Utils.reduce(buffers, start, number);
+        long n = Utils.remaining(bufs);
+        sslDelegate.write(bufs);
+        return n;
+    }
+
+    @Override
+    long write(ByteBuffer buffer) throws IOException {
+        long n = buffer.remaining();
+        sslDelegate.write(buffer);
+        return n;
+    }
+
+    @Override
+    public void close() {
+        Utils.close(sslDelegate, delegate.channel());
+    }
+
+    @Override
+    public void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver, Consumer<Throwable> errorReceiver) {
+        sslDelegate.setAsyncCallbacks(asyncReceiver, errorReceiver);
+        delegate.setAsyncCallbacks(sslDelegate::lowerRead, errorReceiver);
+    }
+
+    // Blocking read functions not used here
+
+    @Override
+    protected ByteBuffer readImpl(int length) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    protected int readImpl(ByteBuffer buffer) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    CompletableFuture<Void> whenReceivingResponse() {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    public void startReading() {
+        delegate.startReading();
+        sslDelegate.startReading();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,598 @@
+/*
+ * 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
+ */
+package java.net.http;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import static javax.net.ssl.SSLEngineResult.Status.*;
+import javax.net.ssl.*;
+import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
+
+/**
+ * Asynchronous wrapper around SSLEngine. send and receive is fully non
+ * blocking. When handshaking is required, a thread is created to perform
+ * the handshake and application level sends do not take place during this time.
+ *
+ * Is implemented using queues and functions operating on the receiving end
+ * of each queue.
+ *
+ * Application writes to:
+ *        ||
+ *        \/
+ *     appOutputQ
+ *        ||
+ *        \/
+ * appOutputQ read by "upperWrite" method which does SSLEngine.wrap
+ * and writes to
+ *        ||
+ *        \/
+ *     channelOutputQ
+ *        ||
+ *        \/
+ * channelOutputQ is read by "lowerWrite" method which is invoked from
+ * OP_WRITE events on the socket (from selector thread)
+ *
+ * Reading side is as follows
+ * --------------------------
+ *
+ * "upperRead" method reads off channelInputQ and calls SSLEngine.unwrap and
+ * when decrypted data is returned, it is passed to the user's Consumer<ByteBuffer>
+ *        /\
+ *        ||
+ *     channelInputQ
+ *        /\
+ *        ||
+ * "lowerRead" method puts buffers into channelInputQ. It is invoked from
+ * OP_READ events from the selector.
+ *
+ * Whenever handshaking is required, the doHandshaking() method is called
+ * which creates a thread to complete the handshake. It takes over the
+ * channelInputQ from upperRead, and puts outgoing packets on channelOutputQ.
+ * Selector events are delivered to lowerRead and lowerWrite as normal.
+ *
+ * Errors
+ *
+ * Any exception thrown by the engine or channel, causes all Queues to be closed
+ * the channel to be closed, and the error is reported to the user's
+ * Consumer<Throwable>
+ */
+public class AsyncSSLDelegate implements Closeable, AsyncConnection {
+
+    // outgoing buffers put in this queue first and may remain here
+    // while SSL handshaking happening.
+    final Queue<ByteBuffer> appOutputQ;
+
+    // queue of wrapped ByteBuffers waiting to be sent on socket channel
+    //final Queue<ByteBuffer> channelOutputQ;
+
+    // Bytes read into this queue before being unwrapped. Backup on this
+    // Q should only happen when the engine is stalled due to delegated tasks
+    final Queue<ByteBuffer> channelInputQ;
+
+    // input occurs through the read() method which is expected to be called
+    // when the selector signals some data is waiting to be read. All incoming
+    // handshake data is handled in this method, which means some calls to
+    // read() may return zero bytes of user data. This is not a sign of spinning,
+    // just that the handshake mechanics are being executed.
+
+    final SSLEngine engine;
+    final SSLParameters sslParameters;
+    //final SocketChannel chan;
+    final HttpConnection lowerOutput;
+    final HttpClientImpl client;
+    final ExecutorService executor;
+    final BufferHandler bufPool;
+    Consumer<ByteBuffer> receiver;
+    Consumer<Throwable> errorHandler;
+    // Locks.
+    final Object reader = new Object();
+    final Object writer = new Object();
+    // synchronizing handshake state
+    final Object handshaker = new Object();
+    // flag set when reader or writer is blocked waiting for handshake to finish
+    boolean writerBlocked;
+    boolean readerBlocked;
+
+    // some thread is currently doing the handshake
+    boolean handshaking;
+
+    // alpn[] may be null. upcall is callback which receives incoming decoded bytes off socket
+
+    AsyncSSLDelegate(HttpConnection lowerOutput, HttpClientImpl client, String[] alpn)
+    {
+        SSLContext context = client.sslContext();
+        executor = client.executorService();
+        bufPool = client;
+        appOutputQ = new Queue<>();
+        appOutputQ.registerPutCallback(this::upperWrite);
+        //channelOutputQ = new Queue<>();
+        //channelOutputQ.registerPutCallback(this::lowerWrite);
+        engine = context.createSSLEngine();
+        engine.setUseClientMode(true);
+        SSLParameters sslp = client.sslParameters().orElse(null);
+        if (sslp == null) {
+            sslp = context.getSupportedSSLParameters();
+            //sslp = context.getDefaultSSLParameters();
+            //printParams(sslp);
+        }
+        sslParameters = Utils.copySSLParameters(sslp);
+        if (alpn != null) {
+            sslParameters.setApplicationProtocols(alpn);
+            Log.logSSL("Setting application protocols: " + Arrays.toString(alpn));
+        } else {
+            Log.logSSL("No application protocols proposed");
+        }
+        engine.setSSLParameters(sslParameters);
+        engine.setEnabledCipherSuites(sslp.getCipherSuites());
+        engine.setEnabledProtocols(sslp.getProtocols());
+        this.lowerOutput = lowerOutput;
+        this.client = client;
+        this.channelInputQ = new Queue<>();
+        this.channelInputQ.registerPutCallback(this::upperRead);
+    }
+
+    /**
+     * Put buffers to appOutputQ, and call upperWrite() if q was empty.
+     *
+     * @param src
+     */
+    public void write(ByteBuffer[] src) throws IOException {
+        appOutputQ.putAll(src);
+    }
+
+    public void write(ByteBuffer buf) throws IOException {
+        ByteBuffer[] a = new ByteBuffer[1];
+        a[0] = buf;
+        write(a);
+    }
+
+    @Override
+    public void close() {
+        Utils.close(appOutputQ, channelInputQ, lowerOutput);
+    }
+
+    /**
+     * Attempts to wrap buffers from appOutputQ and place them on the
+     * channelOutputQ for writing. If handshaking is happening, then the
+     * process stalls and last buffers taken off the appOutputQ are put back
+     * into it until handshaking completes.
+     *
+     * This same method is called to try and resume output after a blocking
+     * handshaking operation has completed.
+     */
+    private void upperWrite() {
+        try {
+            EngineResult r = null;
+            ByteBuffer[] buffers = appOutputQ.pollAll(Utils.EMPTY_BB_ARRAY);
+            int bytes = Utils.remaining(buffers);
+            while (bytes > 0) {
+                synchronized (writer) {
+                    r = wrapBuffers(buffers);
+                    int bytesProduced = r.bytesProduced();
+                    int bytesConsumed = r.bytesConsumed();
+                    bytes -= bytesConsumed;
+                    if (bytesProduced > 0) {
+                        // pass destination buffer to channelOutputQ.
+                        lowerOutput.write(r.destBuffer);
+                    }
+                    synchronized (handshaker) {
+                        if (r.handshaking()) {
+                            // handshaking is happening or is needed
+                            // so we put the buffers back on Q to process again
+                            // later. It's possible that some may have already
+                            // been processed, which is ok.
+                            appOutputQ.pushbackAll(buffers);
+                            writerBlocked = true;
+                            if (!handshaking()) {
+                                // execute the handshake in another thread.
+                                // This method will be called again to resume sending
+                                // later
+                                doHandshake(r);
+                            }
+                            return;
+                        }
+                    }
+                }
+            }
+            returnBuffers(buffers);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            close();
+        }
+    }
+
+    private void doHandshake(EngineResult r) {
+        handshaking = true;
+        channelInputQ.registerPutCallback(null);
+        executor.execute(() -> {
+            try {
+                doHandshakeImpl(r);
+                channelInputQ.registerPutCallback(this::upperRead);
+            } catch (Throwable t) {
+                t.printStackTrace();
+                close();
+            }
+        });
+    }
+
+    private void returnBuffers(ByteBuffer[] bufs) {
+        for (ByteBuffer buf : bufs)
+            client.returnBuffer(buf);
+    }
+
+    /**
+     * Return true if some thread is currently doing the handshake
+     *
+     * @return
+     */
+    boolean handshaking() {
+        synchronized(handshaker) {
+            return handshaking;
+        }
+    }
+
+    /**
+     * Executes entire handshake in calling thread.
+     * Returns after handshake is completed or error occurs
+     * @param r
+     * @throws IOException
+     */
+    private void doHandshakeImpl(EngineResult r) throws IOException {
+        while (true) {
+            SSLEngineResult.HandshakeStatus status = r.handshakeStatus();
+            if (status == NEED_TASK) {
+                LinkedList<Runnable> tasks = obtainTasks();
+                for (Runnable task : tasks)
+                    task.run();
+                r = handshakeWrapAndSend();
+            } else if (status == NEED_WRAP) {
+                r = handshakeWrapAndSend();
+            } else if (status == NEED_UNWRAP) {
+                r = handshakeReceiveAndUnWrap();
+            }
+            if (!r.handshaking())
+                break;
+        }
+        boolean dowrite = false;
+        boolean doread = false;
+        // Handshake is finished. Now resume reading and/or writing
+        synchronized(handshaker) {
+            handshaking = false;
+            if (writerBlocked) {
+                writerBlocked = false;
+                dowrite = true;
+            }
+            if (readerBlocked) {
+                readerBlocked = false;
+                doread = true;
+            }
+        }
+        if (dowrite)
+            upperWrite();
+        if (doread)
+            upperRead();
+    }
+
+    // acknowledge a received CLOSE request from peer
+    void doClosure() throws IOException {
+        //while (!wrapAndSend(emptyArray))
+            //;
+    }
+
+    LinkedList<Runnable> obtainTasks() {
+        LinkedList<Runnable> l = new LinkedList<>();
+        Runnable r;
+        while ((r = engine.getDelegatedTask()) != null)
+            l.add(r);
+        return l;
+    }
+
+    @Override
+    public synchronized void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver, Consumer<Throwable> errorReceiver) {
+        this.receiver = asyncReceiver;
+        this.errorHandler = errorReceiver;
+    }
+
+    @Override
+    public void startReading() {
+        // maybe this class does not need to implement AsyncConnection
+    }
+
+    static class EngineResult {
+        ByteBuffer destBuffer;
+        ByteBuffer srcBuffer;
+        SSLEngineResult result;
+        Throwable t;
+
+        boolean handshaking() {
+            SSLEngineResult.HandshakeStatus s = result.getHandshakeStatus();
+            return s != FINISHED && s != NOT_HANDSHAKING;
+        }
+
+        int bytesConsumed() {
+            return result.bytesConsumed();
+        }
+
+        int bytesProduced() {
+            return result.bytesProduced();
+        }
+
+        Throwable exception() {
+            return t;
+        }
+
+        SSLEngineResult.HandshakeStatus handshakeStatus() {
+            return result.getHandshakeStatus();
+        }
+
+        SSLEngineResult.Status status() {
+            return result.getStatus();
+        }
+    }
+
+    EngineResult handshakeWrapAndSend() throws IOException {
+        EngineResult r = wrapBuffer(Utils.EMPTY_BYTEBUFFER);
+        if (r.bytesProduced() > 0) {
+            lowerOutput.write(r.destBuffer);
+        }
+        return r;
+    }
+
+    // called during handshaking. It blocks until a complete packet
+    // is available, unwraps it and returns.
+    EngineResult handshakeReceiveAndUnWrap() throws IOException {
+        ByteBuffer buf = channelInputQ.take();
+        while (true) {
+            // block waiting for input
+            EngineResult r = unwrapBuffer(buf);
+            SSLEngineResult.Status status = r.status();
+            if (status == BUFFER_UNDERFLOW) {
+                // wait for another buffer to arrive
+                ByteBuffer buf1 = channelInputQ.take();
+                buf = combine (buf, buf1);
+                continue;
+            }
+            // OK
+            // theoretically possible we could receive some user data
+            if (r.bytesProduced() > 0) {
+                receiver.accept(r.destBuffer);
+            }
+            if (!buf.hasRemaining())
+                return r;
+        }
+    }
+
+    EngineResult wrapBuffer(ByteBuffer src) throws SSLException {
+        ByteBuffer[] bufs = new ByteBuffer[1];
+        bufs[0] = src;
+        return wrapBuffers(bufs);
+    }
+
+    EngineResult wrapBuffers(ByteBuffer[] src) throws SSLException {
+        EngineResult r = new EngineResult();
+        ByteBuffer dst = bufPool.getBuffer();
+        while (true) {
+            r.result = engine.wrap(src, dst);
+            switch (r.result.getStatus()) {
+                case BUFFER_OVERFLOW:
+                    dst = getPacketBuffer();
+                    break;
+                case CLOSED:
+                case OK:
+                    dst.flip();
+                    r.destBuffer = dst;
+                    return r;
+                case BUFFER_UNDERFLOW:
+                    // underflow handled externally
+                    bufPool.returnBuffer(dst);
+                    return r;
+                default:
+                    assert false;
+            }
+        }
+    }
+
+    EngineResult unwrapBuffer(ByteBuffer srcbuf) throws IOException {
+        EngineResult r = new EngineResult();
+        r.srcBuffer = srcbuf;
+
+        ByteBuffer dst = bufPool.getBuffer();
+        while (true) {
+            r.result = engine.unwrap(srcbuf, dst);
+            switch (r.result.getStatus()) {
+                case BUFFER_OVERFLOW:
+                    // dest buffer not big enough. Reallocate
+                    int oldcap = dst.capacity();
+                    dst = getApplicationBuffer();
+                    assert dst.capacity() > oldcap;
+                    break;
+                case CLOSED:
+                    doClosure();
+                    throw new IOException("Engine closed");
+                case BUFFER_UNDERFLOW:
+                    bufPool.returnBuffer(dst);
+                    return r;
+                case OK:
+                    dst.flip();
+                    r.destBuffer = dst;
+                    return r;
+            }
+        }
+    }
+
+    /**
+     * Asynchronous read input. Call this when selector fires.
+     * Unwrap done in upperRead because it also happens in
+     * doHandshake() when handshake taking place
+     */
+    public void lowerRead(ByteBuffer buffer) {
+        try {
+            channelInputQ.put(buffer);
+        } catch (Throwable t) {
+            close();
+            errorHandler.accept(t);
+        }
+    }
+
+    public void upperRead() {
+        EngineResult r;
+        ByteBuffer srcbuf;
+        synchronized (reader) {
+            try {
+                srcbuf = channelInputQ.poll();
+                if (srcbuf == null) {
+                    return;
+                }
+                while (true) {
+                    r = unwrapBuffer(srcbuf);
+                    switch (r.result.getStatus()) {
+                        case BUFFER_UNDERFLOW:
+                            // Buffer too small. Need to combine with next buf
+                            ByteBuffer nextBuf = channelInputQ.poll();
+                            if (nextBuf == null) {
+                                // no data available. push buffer back until more data available
+                                channelInputQ.pushback(srcbuf);
+                                return;
+                            } else {
+                                srcbuf = combine(srcbuf, nextBuf);
+                            }
+                            break;
+                        case OK:
+                            // check for any handshaking work
+                            synchronized (handshaker) {
+                                if (r.handshaking()) {
+                                    // handshaking is happening or is needed
+                                    // so we put the buffer back on Q to process again
+                                    // later.
+                                    channelInputQ.pushback(srcbuf);
+                                    readerBlocked = true;
+                                    if (!handshaking()) {
+                                        // execute the handshake in another thread.
+                                        // This method will be called again to resume sending
+                                        // later
+                                        doHandshake(r);
+                                    }
+                                    return;
+                                }
+                            }
+                            ByteBuffer dst = r.destBuffer;
+                            if (dst.hasRemaining()) {
+                                receiver.accept(dst);
+                            }
+                    }
+                    if (srcbuf.hasRemaining()) {
+                        continue;
+                    }
+                    srcbuf = channelInputQ.poll();
+                    if (srcbuf == null) {
+                        return;
+                    }
+                }
+            } catch (Throwable t) {
+                Utils.close(lowerOutput);
+                errorHandler.accept(t);
+            }
+        }
+    }
+
+    /**
+     * Get a new buffer that is the right size for application buffers.
+     *
+     * @return
+     */
+    ByteBuffer getApplicationBuffer() {
+        SSLSession session = engine.getSession();
+        int appBufsize = session.getApplicationBufferSize();
+        bufPool.setMinBufferSize(appBufsize);
+        return bufPool.getBuffer(appBufsize);
+    }
+
+    ByteBuffer getPacketBuffer() {
+        SSLSession session = engine.getSession();
+        int packetBufSize = session.getPacketBufferSize();
+        bufPool.setMinBufferSize(packetBufSize);
+        return bufPool.getBuffer(packetBufSize);
+    }
+
+    ByteBuffer combine(ByteBuffer buf1, ByteBuffer buf2) {
+        int avail1 = buf1.capacity() - buf1.remaining();
+        if (buf2.remaining() < avail1) {
+            buf1.compact();
+            buf1.put(buf2);
+            buf1.flip();
+            return buf1;
+        }
+        int newsize = buf1.remaining() + buf2.remaining();
+        ByteBuffer newbuf = bufPool.getBuffer(newsize);
+        newbuf.put(buf1);
+        newbuf.put(buf2);
+        newbuf.flip();
+        return newbuf;
+    }
+
+    SSLParameters getSSLParameters() {
+        return sslParameters;
+    }
+
+    static void printParams(SSLParameters p) {
+        System.out.println("SSLParameters:");
+        if (p == null) {
+            System.out.println("Null params");
+            return;
+        }
+        for (String cipher : p.getCipherSuites()) {
+                System.out.printf("cipher: %s\n", cipher);
+        }
+        for (String approto : p.getApplicationProtocols()) {
+                System.out.printf("application protocol: %s\n", approto);
+        }
+        for (String protocol : p.getProtocols()) {
+                System.out.printf("protocol: %s\n", protocol);
+        }
+        if (p.getServerNames() != null)
+        for (SNIServerName sname : p.getServerNames()) {
+                System.out.printf("server name: %s\n", sname.toString());
+        }
+    }
+
+    String getSessionInfo() {
+        StringBuilder sb = new StringBuilder();
+        String application = engine.getApplicationProtocol();
+        SSLSession sess = engine.getSession();
+        String cipher = sess.getCipherSuite();
+        String protocol = sess.getProtocol();
+        sb.append("Handshake complete alpn: ")
+                .append(application)
+                .append(", Cipher: ")
+                .append(cipher)
+                .append(", Protocol: ")
+                .append(protocol);
+        return sb.toString();
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -45,7 +45,7 @@
     static final int DEFAULT_RETRY_LIMIT = 3;
 
     static final int retry_limit = Utils.getIntegerNetProperty(
-            "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT);
+            "java.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT);
 
     static final int UNAUTHORIZED = 401;
     static final int PROXY_UNAUTHORIZED = 407;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -27,11 +27,23 @@
 import java.nio.ByteBuffer;
 
 /**
- * Implemented by buffer pools.
+ * Implemented by buffer pools. A buffer pool has a current buffer size
+ * (number of bytes in each buffer) which may increase over time.
  */
 interface BufferHandler {
 
-    ByteBuffer getBuffer();
+    default ByteBuffer getBuffer() {
+        return getBuffer(-1);
+    }
+
+    void setMinBufferSize(int size);
+
+    /**
+     * size == -1 means return any sized buffer. Any other value means
+     * @param size
+     * @return
+     */
+    ByteBuffer getBuffer(int size);
 
     void returnBuffer(ByteBuffer buffer);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.function.Supplier;
+
+/**
+ * Takes a List<ByteBuffer> which is assumed to contain at least one HTTP/2
+ * frame and allows it to be processed supplying bytes, ints, shorts, byte[] etc.
+ * from the list. As each ByteBuffer is consumed it is removed from the List<>.
+ *
+ * NOTE. shorts and bytes returned are UNSIGNED ints
+ *
+ * When finished processing the frame, the List may be empty or may contain
+ * partially read or unread ByteBuffers. A new ByteBufferConsumer can be
+ * created with the List<>
+ */
+class ByteBufferConsumer {
+
+    ByteBuffer currentBuffer;
+
+    final List<ByteBuffer> buffers;
+    final ListIterator<ByteBuffer> iterator;
+    final Supplier<ByteBuffer> newBufferSupplier;
+
+    ByteBufferConsumer(List<ByteBuffer> buffers,
+                       Supplier<ByteBuffer> newBufferSupplier) {
+        this.buffers = buffers;
+        this.newBufferSupplier = newBufferSupplier;
+        this.iterator = buffers.listIterator();
+        if (!iterator.hasNext()) {
+            throw new IllegalArgumentException("Empty buffer list");
+        }
+        currentBuffer = iterator.next();
+    }
+
+    private void dump() {
+        int l = 0;
+        System.err.printf("ByteBufferConsumer:\n");
+        for (ByteBuffer buf : buffers) {
+            System.err.printf("\t%s\n", buf.toString());
+            l+= buf.remaining();
+        }
+        System.err.printf("BBC contains %d bytes\n", l);
+    }
+
+    private synchronized ByteBuffer getBuffer(boolean exception) throws IOException {
+        while (currentBuffer == null || !currentBuffer.hasRemaining()) {
+            if (currentBuffer != null) {
+                iterator.remove();
+            }
+            if (!iterator.hasNext()) {
+                currentBuffer = null;
+                if (exception) {
+                    throw new IOException ("Connection closed unexpectedly");
+                }
+                return null;
+            }
+            currentBuffer = iterator.next();
+        }
+        return currentBuffer;
+    }
+
+    // call this to check if the data has all been consumed
+
+    public boolean consumed() {
+        try {
+            return getBuffer(false) == null;
+        } catch (IOException e) {
+            /* CAN'T HAPPEN */
+            throw new InternalError();
+        }
+    }
+
+    public int getByte() throws IOException {
+        // TODO: what to do if connection is closed. Throw NPE?
+        ByteBuffer buf = getBuffer(true);
+        return buf.get() & 0xff;
+    }
+
+    public byte[] getBytes(int n) throws IOException {
+        return getBytes(n, null);
+    }
+
+    public byte[] getBytes(int n, byte[] buf) throws IOException {
+        if (buf == null) {
+            buf = new byte[n];
+        } else if (buf.length < n) {
+            throw new IllegalArgumentException("getBytes: buffer too small");
+        }
+        int offset = 0;
+        while (n > 0) {
+            ByteBuffer b = getBuffer(true);
+            int length = Math.min(n, b.remaining());
+            b.get(buf, offset, length);
+            offset += length;
+            n -= length;
+        }
+        return buf;
+    }
+
+    public int getShort() throws IOException {
+        ByteBuffer buf = getBuffer(true);
+        int rem = buf.remaining();
+        if (rem >= 2) {
+            return buf.getShort() & 0xffff;
+        }
+        // Slow path. Not common
+        int val = 0;
+        val = (val << 8) + getByte();
+        val = (val << 8) + getByte();
+        return val;
+    }
+
+    public int getInt() throws IOException {
+        ByteBuffer buf = getBuffer(true);
+        int rem = buf.remaining();
+        if (rem >= 4) {
+            return buf.getInt();
+        }
+        // Slow path. Not common
+        int val = 0;
+        for (int nbytes = 0; nbytes < 4; nbytes++) {
+            val = (val << 8) + getByte();
+        }
+        return val;
+    }
+
+    private static final ByteBuffer[] EMPTY = new ByteBuffer[0];
+
+    /**
+     * Extracts whatever number of ByteBuffers from list to get required number
+     * of bytes. Any remaining buffers are 'tidied up' so reading can continue.
+     */
+    public ByteBuffer[] getBuffers(int bytecount) throws IOException {
+        LinkedList<ByteBuffer> l = new LinkedList<>();
+        while (bytecount > 0) {
+            ByteBuffer buffer = getBuffer(true);
+            int remaining = buffer.remaining();
+            if (remaining > bytecount) {
+                int difference = remaining - bytecount;
+                // split
+                ByteBuffer newb = newBufferSupplier.get();
+                newb.clear();
+                int limit = buffer.limit();
+                buffer.limit(limit - difference);
+                newb.put(buffer);
+                newb.flip();
+                buffer.limit(limit);
+                l.add(newb);
+                bytecount = 0;
+            } else {
+                l.add(buffer);
+                currentBuffer = null;
+                iterator.remove();
+                bytecount -= remaining;
+            }
+        }
+        return l.toArray(EMPTY);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,136 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+/**
+ * Manages a ByteBuffer[] for writing frames into for output. The last
+ * ByteBuffer in the list is always unflipped (able to receive more bytes for
+ * sending) until getBufferArray() is called, which calls finish().
+ *
+ * This allows multiple frames to be written to the same BBG.
+ *
+ * Buffers added with addByteBuffer() must be already flipped.
+ */
+class ByteBufferGenerator {
+
+    ByteBuffer currentBuffer;
+    // source is assumed to always return the same sized buffer
+    final BufferHandler pool;
+    final ArrayList<ByteBuffer> buflist;
+    final int bufsize;
+    boolean finished;
+
+    ByteBufferGenerator(BufferHandler pool) {
+        this.buflist = new ArrayList<>();
+        this.pool = pool;
+        this.currentBuffer = pool.getBuffer();
+        this.bufsize = currentBuffer.capacity();
+    }
+
+    private static final ByteBuffer[] EMPTY = new ByteBuffer[0];
+
+    public ByteBuffer[] getBufferArray() {
+        finish();
+        return buflist.toArray(EMPTY);
+    }
+
+    public ArrayList<ByteBuffer> getBufferList() {
+        finish();
+        return buflist;
+    }
+
+    private synchronized void finish() {
+        if (finished) {
+            return;
+        }
+        finished = true;
+        currentBuffer.flip();
+        if (currentBuffer.hasRemaining()) {
+            buflist.add(currentBuffer);
+        } else {
+            pool.returnBuffer(currentBuffer);
+        }
+    }
+
+    // only used for SettingsFrame: offset is number of bytes to
+    // ignore at start (we only want the payload of the settings frame)
+    public byte[] asByteArray(int offset) {
+        ByteBuffer[] bufs = getBufferArray();
+        int size = 0;
+        for (ByteBuffer buf : bufs) {
+            size += buf.remaining();
+        }
+        byte[] bytes = new byte[size-offset];
+        int pos = 0;
+        for (ByteBuffer buf : bufs) {
+            int rem = buf.remaining();
+            int ignore = Math.min(rem, offset);
+            buf.position(buf.position()+ignore);
+            rem -= ignore;
+            offset -= ignore;
+            buf.get(bytes, pos, rem);
+            pos += rem;
+        }
+        return bytes;
+    }
+
+    ByteBuffer getBuffer(long n) {
+        if (currentBuffer.remaining() < n) {
+            getNewBuffer();
+            if (n > currentBuffer.capacity()) {
+                throw new IllegalArgumentException("requested buffer too large");
+            }
+        }
+        return currentBuffer;
+    }
+
+    void getNewBuffer() {
+        currentBuffer.flip();
+        if (currentBuffer.hasRemaining()) {
+            buflist.add(currentBuffer);
+        } else {
+            pool.returnBuffer(currentBuffer);
+        }
+        currentBuffer = pool.getBuffer();
+    }
+
+    void addByteBuffer(ByteBuffer buf) {
+        getNewBuffer();
+        buflist.add(buf);
+    }
+
+    void addPadding(int length) {
+        while (length > 0) {
+            int n = Math.min(length, bufsize);
+            ByteBuffer b = getBuffer(n);
+            // TODO: currently zeroed?
+            b.position(b.position() + n);
+            length -= n;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+// The purpose of this class is to separate charset-related tasks from the main
+// WebSocket logic, simplifying where possible.
+//
+//     * Coders hide the differences between coding and flushing stages on the
+//       API level
+//     * Verifier abstracts the way the verification is performed
+//       (spoiler: it's a decoding into a throw-away buffer)
+//
+// Coding methods throw exceptions instead of returning coding result denoting
+// errors, since any kind of handling and recovery is not expected.
+final class CharsetToolkit {
+
+    private CharsetToolkit() { }
+
+    static final class Verifier {
+
+        private final CharsetDecoder decoder = UTF_8.newDecoder();
+        // A buffer used to check validity of UTF-8 byte stream by decoding it.
+        // The contents of this buffer are never used.
+        // The size is arbitrary, though it should probably be chosen from the
+        // performance perspective since it affects the total number of calls to
+        // decoder.decode() and amount of work in each of these calls
+        private final CharBuffer blackHole = CharBuffer.allocate(1024);
+
+        void verify(ByteBuffer in, boolean endOfInput)
+                throws CharacterCodingException {
+            while (true) {
+                // Since decoder.flush() cannot produce an error, it's not
+                // helpful for verification. Therefore this step is skipped.
+                CoderResult r = decoder.decode(in, blackHole, endOfInput);
+                if (r.isOverflow()) {
+                    blackHole.clear();
+                } else if (r.isUnderflow()) {
+                    break;
+                } else if (r.isError()) {
+                    r.throwException();
+                } else {
+                    // Should not happen
+                    throw new InternalError();
+                }
+            }
+        }
+
+        Verifier reset() {
+            decoder.reset();
+            return this;
+        }
+    }
+
+    static final class Encoder {
+
+        private final CharsetEncoder encoder = UTF_8.newEncoder();
+        private boolean coding = true;
+
+        CoderResult encode(CharBuffer in, ByteBuffer out, boolean endOfInput)
+                throws CharacterCodingException {
+
+            if (coding) {
+                CoderResult r = encoder.encode(in, out, endOfInput);
+                if (r.isOverflow()) {
+                    return r;
+                } else if (r.isUnderflow()) {
+                    if (endOfInput) {
+                        coding = false;
+                    } else {
+                        return r;
+                    }
+                } else if (r.isError()) {
+                    r.throwException();
+                } else {
+                    // Should not happen
+                    throw new InternalError();
+                }
+            }
+            assert !coding;
+            return encoder.flush(out);
+        }
+
+        Encoder reset() {
+            coding = true;
+            encoder.reset();
+            return this;
+        }
+    }
+
+    static CharBuffer decode(ByteBuffer in) throws CharacterCodingException {
+        return UTF_8.newDecoder().decode(in);
+    }
+
+    static final class Decoder {
+
+        private final CharsetDecoder decoder = UTF_8.newDecoder();
+        private boolean coding = true; // Either coding or flushing
+
+        CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
+                throws CharacterCodingException {
+
+            if (coding) {
+                CoderResult r = decoder.decode(in, out, endOfInput);
+                if (r.isOverflow()) {
+                    return r;
+                } else if (r.isUnderflow()) {
+                    if (endOfInput) {
+                        coding = false;
+                    } else {
+                        return r;
+                    }
+                } else if (r.isError()) {
+                    r.throwException();
+                } else {
+                    // Should not happen
+                    throw new InternalError();
+                }
+            }
+            assert !coding;
+            return decoder.flush(out);
+        }
+
+        Decoder reset() {
+            coding = true;
+            decoder.reset();
+            return this;
+        }
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java	Wed Jul 05 21:39:33 2017 +0200
@@ -35,7 +35,7 @@
 class ConnectionPool {
 
     static final long KEEP_ALIVE = Utils.getIntegerNetProperty(
-            "sun.net.httpclient.keepalive.timeout", 1200); // seconds
+            "java.net.httpclient.keepalive.timeout", 1200); // seconds
 
     // Pools of idle connections
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+
+class ContinuationFrame extends HeaderFrame {
+
+    public static final int TYPE = 0x9;
+
+    ContinuationFrame() {
+        type = TYPE;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        headerBlocks = bc.getBuffers(length);
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        for (int i=0; i<headerBlocks.length; i++) {
+            bg.addByteBuffer(headerBlocks[i]);
+        }
+    }
+
+    @Override
+    public boolean endHeaders() {
+        return getFlag(END_HEADERS);
+    }
+
+    @Override
+    void computeLength() {
+        length = headerLength;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -44,7 +44,7 @@
     @Override
     public void request(HttpRequestImpl r) throws IOException {
         Map<String,List<String>> userheaders, cookies;
-        userheaders = r.getUserHeaders().directMap();
+        userheaders = r.getUserHeaders().map();
         cookies = cookieMan.get(r.uri(), userheaders);
         // add the returned cookies
         HttpHeadersImpl systemHeaders = r.getSystemHeaders();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,126 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class DataFrame extends Http2Frame {
+
+    public final static int TYPE = 0x0;
+
+    DataFrame() {
+        type = TYPE;
+    }
+
+    // Flags
+    public static final int END_STREAM = 0x1;
+    public static final int PADDED = 0x8;
+
+    int padLength;
+    int dataLength;
+    ByteBuffer[] data;
+
+    public void setData(ByteBuffer[] data) {
+        this.data = data;
+        setDataLength();
+    }
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case END_STREAM:
+            return "END_STREAM";
+        case PADDED:
+            return "PADDED";
+        }
+        return super.flagAsString(flag);
+    }
+
+    public synchronized void setData(ByteBuffer data) {
+        ByteBuffer[] bb;
+        if (data == null) {
+            bb = new ByteBuffer[0];
+        } else {
+            bb = new ByteBuffer[1];
+            bb[0] = data;
+        }
+        setData(bb);
+    }
+
+    public synchronized ByteBuffer[] getData() {
+        return data;
+    }
+
+    private void setDataLength() {
+        int len = 0;
+        for (ByteBuffer buf : data) {
+            len += buf.remaining();
+        }
+        dataLength = len;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if ((flags & PADDED) != 0) {
+            padLength = bc.getByte();
+            dataLength = length - (padLength + 1);
+        } else {
+            dataLength = length;
+        }
+        data = bc.getBuffers(dataLength);
+    }
+
+    int getPadLength() {
+        return padLength;
+    }
+
+    int getDataLength() {
+        return dataLength;
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        if ((flags & PADDED) != 0) {
+            ByteBuffer buf = bg.getBuffer(1);
+            buf.put((byte)getPadLength());
+        }
+        for (int i=0; i<data.length; i++) {
+            bg.addByteBuffer(data[i]);
+        }
+        if ((flags & PADDED) != 0) {
+            bg.addPadding(padLength);
+        }
+    }
+
+    @Override
+    void computeLength() {
+        length = dataLength;
+        if ((flags & PADDED) != 0) {
+            length += (1 + padLength);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ErrorFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,88 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+abstract class ErrorFrame extends Http2Frame {
+
+    // error codes
+    public static final int NO_ERROR = 0x0;
+    public static final int PROTOCOL_ERROR = 0x1;
+    public static final int INTERNAL_ERROR = 0x2;
+    public static final int FLOW_CONTROL_ERROR = 0x3;
+    public static final int SETTINGS_TIMEOUT = 0x4;
+    public static final int STREAM_CLOSED = 0x5;
+    public static final int FRAME_SIZE_ERROR = 0x6;
+    public static final int REFUSED_STREAM = 0x7;
+    public static final int CANCEL = 0x8;
+    public static final int COMPRESSION_ERROR = 0x9;
+    public static final int CONNECT_ERROR = 0xa;
+    public static final int ENHANCE_YOUR_CALM = 0xb;
+    public static final int INADEQUATE_SECURITY = 0xc;
+    public static final int HTTP_1_1_REQUIRED = 0xd;
+    static final int LAST_ERROR = 0xd;
+
+    static final String[] errorStrings = {
+        "Not an error",
+        "Protocol error",
+        "Internal error",
+        "Flow control error",
+        "Settings timeout",
+        "Stream is closed",
+        "Frame size error",
+        "Stream not processed",
+        "Stream cancelled",
+        "Compression state not updated",
+        "TCP Connection error on CONNECT",
+        "Processing capacity exceeded",
+        "Negotiated TLS parameters not acceptable",
+        "Use HTTP/1.1 for request"
+    };
+
+    public static String stringForCode(int code) {
+        if (code < 0)
+            throw new IllegalArgumentException();
+
+        if (code > LAST_ERROR) {
+            return "Error: " + Integer.toString(code);
+        } else {
+            return errorStrings[code];
+        }
+    }
+
+    int errorCode;
+
+    @Override
+    public String toString() {
+        return super.toString() + " Error: " + stringForCode(errorCode);
+    }
+
+    public int getErrorCode() {
+        return this.errorCode;
+    }
+
+    public void setErrorCode(int errorCode) {
+        this.errorCode = errorCode;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java	Wed Jul 05 21:39:33 2017 +0200
@@ -128,7 +128,7 @@
         }
     }
 
-    HttpResponseImpl responseImpl0(HttpConnection connection)
+    private HttpResponseImpl responseImpl0(HttpConnection connection)
         throws IOException, InterruptedException
     {
         exchImpl = ExchangeImpl.get(this, connection);
@@ -136,7 +136,7 @@
             request.addSystemHeader("Expect", "100-Continue");
             exchImpl.sendHeadersOnly();
             HttpResponseImpl resp = exchImpl.getResponse();
-            logResponse(resp);
+            Utils.logResponse(resp);
             if (resp.statusCode() != 100) {
                 return resp;
             }
@@ -145,7 +145,7 @@
         } else {
             exchImpl.sendRequest();
             HttpResponseImpl resp = exchImpl.getResponse();
-            logResponse(resp);
+            Utils.logResponse(resp);
             return checkForUpgrade(resp, exchImpl);
         }
     }
@@ -163,9 +163,7 @@
         }
         SecurityException e = securityCheck(acc);
         if (e != null) {
-            CompletableFuture<HttpResponseImpl> cf = new CompletableFuture<>();
-            cf.completeExceptionally(e);
-            return cf;
+            return CompletableFuture.failedFuture(e);
         }
         if (permissions.size() > 0) {
             return AccessController.doPrivileged(
@@ -182,9 +180,7 @@
         try {
             exchImpl = ExchangeImpl.get(this, connection);
         } catch (IOException | InterruptedException e) {
-            CompletableFuture<HttpResponseImpl> cf = new CompletableFuture<>();
-            cf.completeExceptionally(e);
-            return cf;
+            return CompletableFuture.failedFuture(e);
         }
         if (request.expectContinue()) {
             request.addSystemHeader("Expect", "100-Continue");
@@ -200,23 +196,19 @@
                             return exchImpl.sendBodyAsync()
                                 .thenCompose(exchImpl::getResponseAsync)
                                 .thenApply((r) -> {
-                                    logResponse(r);
+                                    Utils.logResponse(r);
                                     return r;
                                 });
                         } else {
                             Exchange.this.response = r1;
-                            logResponse(r1);
+                            Utils.logResponse(r1);
                             return CompletableFuture.completedFuture(r1);
                         }
                     });
         } else {
             return exchImpl
-                .sendHeadersAsync()
-                .thenCompose((Void v) -> {
-                    // send body and get response at same time
-                    return exchImpl.sendBodyAsync()
-                                   .thenCompose(exchImpl::getResponseAsync);
-                })
+                .sendRequestAsync()
+                .thenCompose(exchImpl::getResponseAsync)
                 .thenCompose((HttpResponseImpl r1) -> {
                     int rcode = r1.statusCode();
                     CompletableFuture<HttpResponseImpl> cf =
@@ -225,13 +217,13 @@
                         return cf;
                     } else {
                         Exchange.this.response = r1;
-                        logResponse(r1);
+                        Utils.logResponse(r1);
                         return CompletableFuture.completedFuture(r1);
                     }
                 })
                 .thenApply((HttpResponseImpl response) -> {
                     this.response = response;
-                    logResponse(response);
+                    Utils.logResponse(response);
                     return response;
                 });
         }
@@ -254,9 +246,9 @@
                                                  client.client2(),
                                                  this)
                         .thenCompose((Http2Connection c) -> {
+                            c.putConnection();
                             Stream s = c.getStream(1);
                             exchImpl = s;
-                            c.putConnection();
                             return s.getResponseAsync(null);
                         })
                 );
@@ -294,21 +286,6 @@
     }
 
 
-    private void logResponse(HttpResponseImpl r) {
-        if (!Log.requests())
-            return;
-        StringBuilder sb = new StringBuilder();
-        String method = r.request().method();
-        URI uri = r.uri();
-        String uristring = uri == null ? "" : uri.toString();
-        sb.append('(')
-          .append(method)
-          .append(" ")
-          .append(uristring)
-          .append(") ")
-          .append(Integer.toString(r.statusCode()));
-        Log.logResponse(sb.toString());
-    }
 
     <T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
         return exchImpl.responseBodyAsync(processor);
@@ -352,9 +329,9 @@
         }
 
         String method = request.method();
-        HttpHeadersImpl userHeaders = request.getUserHeaders();
+        HttpHeaders userHeaders = request.getUserHeaders();
         URI u = getURIForSecurityCheck();
-        URLPermission p = Utils.getPermission(u, method, userHeaders.directMap());
+        URLPermission p = Utils.getPermission(u, method, userHeaders.map());
 
         try {
             assert acc != null;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,70 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package java.net.http;
+
+import java.nio.ByteBuffer;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Represents one frame. May be initialized with a leftover buffer from previous
+ * frame. Call {@code haveFrame()} to determine if buffers contains at least one
+ * frame. If false, the obtain another buffer and call {@code}input(ByteBuffer)}.
+ * There may be additional bytes at end of the frame list.
+ */
+class FrameReader {
+
+    final List<ByteBuffer> buffers;
+
+    FrameReader() {
+        buffers = new LinkedList<>();
+    }
+
+    FrameReader(FrameReader that) {
+        this.buffers = that.buffers;
+    }
+
+    FrameReader(ByteBuffer remainder) {
+        buffers = new LinkedList<>();
+        if (remainder != null) {
+            buffers.add(remainder);
+        }
+    }
+
+    public synchronized void input(ByteBuffer buffer) {
+        buffers.add(buffer);
+    }
+
+    public synchronized boolean haveFrame() {
+        //buffers = Utils.superCompact(buffers, () -> ByteBuffer.allocate(Utils.BUFSIZE));
+        int size = 0;
+        for (ByteBuffer buffer : buffers) {
+            size += buffer.remaining();
+        }
+        if (size < 3) {
+            return false; // don't have length yet
+        }
+        // we at least have length field
+        int length = 0;
+        int j = 0;
+        ByteBuffer b = buffers.get(j);
+        b.mark();
+        for (int i=0; i<3; i++) {
+            while (!b.hasRemaining()) {
+                b.reset();
+                b = buffers.get(++j);
+                b.mark();
+            }
+            length = (length << 8) + (b.get() & 0xff);
+        }
+        b.reset();
+        return (size >= length + 9); // frame length
+    }
+
+    synchronized List<ByteBuffer> frame() {
+        return buffers;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,104 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class GoAwayFrame extends ErrorFrame {
+
+    GoAwayFrame() {
+        type = TYPE;
+    }
+
+    int lastStream;
+    byte[] debugData = new byte[0];
+
+    public static final int TYPE = 0x7;
+
+    // Flags
+    public static final int ACK = 0x1;
+
+    public void setDebugData(byte[] debugData) {
+        this.debugData = debugData;
+    }
+
+    @Override
+    public String toString() {
+        return super.toString() + " Debugdata: " + new String(debugData);
+    }
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case ACK:
+            return "ACK";
+        }
+        return super.flagAsString(flag);
+    }
+
+    public void setLastStream(int lastStream) {
+        this.lastStream = lastStream;
+    }
+
+    public int getLastStream() {
+        return this.lastStream;
+    }
+
+    public byte[] getDebugData() {
+        return debugData;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if (length < 8) {
+            throw new IOException("Invalid GoAway frame");
+        }
+        lastStream = bc.getInt() & 0x7fffffff;
+        errorCode = bc.getInt();
+        //debugData = bc.getBytes(8);
+        int datalen = length - 8;
+        if (datalen > 0) {
+            debugData = bc.getBytes(datalen);
+            Log.logError("GoAway debugData " + new String(debugData));
+        }
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(length);
+        buf.putInt(lastStream);
+        buf.putInt(errorCode);
+        if (length > 8) {
+            buf.put(debugData);
+        }
+    }
+
+    @Override
+    void computeLength() {
+        length = 8 + debugData.length;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,77 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Either a HeadersFrame or a ContinuationFrame
+ */
+abstract class HeaderFrame extends Http2Frame {
+
+    int offset;
+    int number;
+    int headerLength;
+    ByteBuffer[] headerBlocks;
+
+    public static final int END_HEADERS = 0x4;
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case END_HEADERS:
+            return "END_HEADERS";
+        }
+        return super.flagAsString(flag);
+    }
+
+    /**
+     * Sets the array of hpack encoded ByteBuffers
+     */
+    public void setHeaderBlock(ByteBuffer bufs[], int offset, int number) {
+        this.headerBlocks = bufs;
+        this.offset = offset;
+        this.number = number;
+        int length = 0;
+        for (int i=offset; i<offset+number; i++) {
+            length += headerBlocks[i].remaining();
+        }
+        this.headerLength = length;
+    }
+
+    public void setHeaderBlock(ByteBuffer bufs[]) {
+        setHeaderBlock(bufs, 0, bufs.length);
+    }
+
+    public ByteBuffer[] getHeaderBlock() {
+        return headerBlocks;
+    }
+
+    /**
+     * Returns true if this block is the final block of headers
+     */
+    public abstract boolean endHeaders();
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeadersFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class HeadersFrame extends HeaderFrame {
+
+    public final static int TYPE = 0x1;
+
+    // Flags
+    public static final int END_STREAM = 0x1;
+    public static final int PADDED = 0x8;
+    public static final int PRIORITY = 0x20;
+
+
+    int padLength;
+    int streamDependency;
+    int weight;
+    boolean exclusive;
+
+    HeadersFrame() {
+        type = TYPE;
+    }
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+            case END_STREAM:
+                return "END_STREAM";
+            case PADDED:
+                return "PADDED";
+            case PRIORITY:
+                return "PRIORITY";
+        }
+        return super.flagAsString(flag);
+    }
+
+    public void setPadLength(int padLength) {
+        this.padLength = padLength;
+        flags |= PADDED;
+    }
+
+    public void setPriority(int streamDependency, boolean exclusive, int weight) {
+        this.streamDependency = streamDependency;
+        this.exclusive = exclusive;
+        this.weight = weight;
+        this.flags |= PRIORITY;
+    }
+
+    public int getStreamDependency() {
+        return streamDependency;
+    }
+
+    public int getWeight() {
+        return weight;
+    }
+
+    @Override
+    public boolean endHeaders() {
+        return getFlag(END_HEADERS);
+    }
+
+    public boolean getExclusive() {
+        return exclusive;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if ((flags & PADDED) != 0) {
+            padLength = bc.getByte();
+        }
+        if ((flags & PRIORITY) != 0) {
+            int x = bc.getInt();
+            exclusive = (x & 0x80000000) != 0;
+            streamDependency = x & 0x7fffffff;
+            weight = bc.getByte();
+        }
+        headerLength = length - padLength;
+        headerBlocks = bc.getBuffers(headerLength);
+    }
+
+    @Override
+    void computeLength() {
+        int len = 0;
+        if ((flags & PADDED) != 0) {
+            len += (1 + padLength);
+        }
+        if ((flags & PRIORITY) != 0) {
+            len += 5;
+        }
+        len += headerLength;
+        this.length = len;
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(6);
+        if ((flags & PADDED) != 0) {
+            buf.put((byte)padLength);
+        }
+        if ((flags & PRIORITY) != 0) {
+            int x = exclusive ? 1 << 31 + streamDependency : streamDependency;
+            buf.putInt(x);
+            buf.put((byte)weight);
+        }
+        for (int i=0; i<headerBlocks.length; i++) {
+            bg.addByteBuffer(headerBlocks[i]);
+        }
+        if ((flags & PADDED) != 0) {
+            bg.addPadding(padLength);
+        }
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java	Wed Jul 05 21:39:33 2017 +0200
@@ -64,32 +64,12 @@
         if (connection != null) {
             this.connection = connection;
         } else {
-            InetSocketAddress addr = getAddress(request);
+            InetSocketAddress addr = Utils.getAddress(request);
             this.connection = HttpConnection.getConnection(addr, request);
         }
         this.requestAction = new Http1Request(request, this.connection);
     }
 
-    private static InetSocketAddress getAddress(HttpRequestImpl req) {
-        URI uri = req.uri();
-        if (uri == null) {
-            return req.authority();
-        }
-        int port = uri.getPort();
-        if (port == -1) {
-            if (uri.getScheme().equalsIgnoreCase("https")) {
-                port = 443;
-            } else {
-                port = 80;
-            }
-        }
-        String host = uri.getHost();
-        if (req.proxy() == null) {
-            return new InetSocketAddress(host, port);
-        } else {
-            return InetSocketAddress.createUnresolved(host, port);
-        }
-    }
 
     HttpConnection connection() {
         return connection;
@@ -211,7 +191,7 @@
                                 connection.close();
                             }
                          },
-                         () -> request.getAccessControlContext());
+                request::getAccessControlContext);
         operations.add(cf);
         return cf;
     }
@@ -269,7 +249,7 @@
                 cf.completeExceptionally(e);
                 connection.close();
             }
-        }, () -> request.getAccessControlContext());
+        }, request::getAccessControlContext);
         operations.add(cf);
         return cf;
     }
@@ -302,7 +282,7 @@
                 cf.completeExceptionally(e);
                 connection.close();
             }
-        }, () -> request.getAccessControlContext());
+        }, request::getAccessControlContext);
         operations.add(cf);
         return cf;
     }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,6 +30,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.net.InetSocketAddress;
+import java.net.http.HttpConnection.Mode;
 import java.nio.charset.StandardCharsets;
 import java.util.function.LongConsumer;
 import static java.nio.charset.StandardCharsets.US_ASCII;
@@ -48,7 +49,8 @@
     // See line 206 and below for description
     final ByteBuffer[] buffers;
     final HttpRequest.BodyProcessor requestProc;
-    final HttpHeadersImpl userHeaders, systemHeaders;
+    final HttpHeaders userHeaders;
+    final HttpHeadersImpl systemHeaders;
     final LongConsumer flowController;
     boolean streaming;
     long contentLength;
@@ -91,10 +93,10 @@
 
     private void collectHeaders1(StringBuilder sb,
                                  HttpRequestImpl request,
-                                 HttpHeadersImpl headers)
+                                 HttpHeaders headers)
         throws IOException
     {
-        Map<String,List<String>> h = headers.directMap();
+        Map<String,List<String>> h = headers.map();
         Set<Map.Entry<String,List<String>>> entries = h.entrySet();
 
         for (Map.Entry<String,List<String>> entry : entries) {
@@ -112,8 +114,6 @@
         }
     }
 
-    private static final int BUFSIZE = 64 * 1024; // TODO: configurable?
-
     private String getPathAndQuery(URI uri) {
         String path = uri.getPath();
         String query = uri.getQuery();
@@ -134,6 +134,25 @@
         return addr.getHostString() + ":" + addr.getPort();
     }
 
+    private String hostString() {
+        URI uri = request.uri();
+        int port = uri.getPort();
+        String host = uri.getHost();
+
+        boolean defaultPort;
+        if (port == -1)
+            defaultPort = true;
+        else if (request.secure())
+            defaultPort = port == 443;
+        else
+            defaultPort = port == 80;
+
+        if (defaultPort)
+            return host;
+        else
+            return host + ":" + Integer.toString(port);
+    }
+
     private String requestURI() {
         URI uri = request.uri();
         String method = request.method();
@@ -161,6 +180,7 @@
 
     void sendRequest() throws IOException {
         collectHeaders();
+        chan.configureMode(Mode.BLOCKING);
         if (contentLength == 0) {
             chan.write(buffers, 0, 2);
         } else if (contentLength > 0) {
@@ -196,7 +216,7 @@
         buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII));
         URI uri = request.uri();
         if (uri != null) {
-            systemHeaders.setHeader("Host", uri.getHost());
+            systemHeaders.setHeader("Host", hostString());
         }
         if (request == null) {
             // this is not a user request. No content
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,7 +24,6 @@
 package java.net.http;
 
 import java.io.IOException;
-import java.net.URI;
 import java.nio.ByteBuffer;
 import java.util.List;
 import java.util.Map;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,11 +23,133 @@
  */
 package java.net.http;
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import static java.net.http.SettingsFrame.INITIAL_WINDOW_SIZE;
+import static java.net.http.SettingsFrame.ENABLE_PUSH;
+import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE;
+import static java.net.http.SettingsFrame.MAX_CONCURRENT_STREAMS;
+import static java.net.http.SettingsFrame.MAX_FRAME_SIZE;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ *  Http2 specific aspects of HttpClientImpl
+ */
 class Http2ClientImpl {
-    Http2ClientImpl(HttpClientImpl t) {}
-    String getSettingsString() {return "";}
-    void debugPrint() {}
-    Http2Connection getConnectionFor(HttpRequestImpl r) {
-        return null;
+
+    final private HttpClientImpl client;
+
+    Http2ClientImpl(HttpClientImpl client) {
+        this.client = client;
+    }
+
+    /* Map key is "scheme:host:port" */
+    final private Map<String,Http2Connection> connections =
+            Collections.synchronizedMap(new HashMap<>());
+
+    final private Set<String> opening = Collections.synchronizedSet(new HashSet<>());
+
+    synchronized boolean haveConnectionFor(URI uri, InetSocketAddress proxy) {
+        return connections.containsKey(Http2Connection.keyFor(uri,proxy));
+    }
+
+    /**
+     * If a https request then blocks and waits until a connection is opened.
+     * Returns null if the request is 'http' as a different (upgrade)
+     * mechanism is used.
+     *
+     * Only one connection per destination is created. Blocks when opening
+     * connection, or when waiting for connection to be opened.
+     * First thread opens the connection and notifies the others when done.
+     *
+     * If the request is secure (https) then we open the connection here.
+     * If not, then the more complicated upgrade from 1.1 to 2 happens (not here)
+     * In latter case, when the Http2Connection is connected, putConnection() must
+     * be called to store it.
+     */
+    Http2Connection getConnectionFor(HttpRequestImpl req)
+            throws IOException, InterruptedException {
+        URI uri = req.uri();
+        InetSocketAddress proxy = req.proxy();
+        String key = Http2Connection.keyFor(uri, proxy);
+        Http2Connection connection;
+        synchronized (opening) {
+            while ((connection = connections.get(key)) == null) {
+                if (!req.secure()) {
+                    return null;
+                }
+                if (!opening.contains(key)) {
+                    opening.add(key);
+                    break;
+                } else {
+                    opening.wait();
+                }
+            }
+        }
+        if (connection != null) {
+            return connection;
+        }
+        // we are opening the connection here blocking until it is done.
+        connection = new Http2Connection(req);
+        synchronized (opening) {
+            connections.put(key, connection);
+            opening.remove(key);
+            opening.notifyAll();
+        }
+        return connection;
+    }
+
+
+    /*
+     * TODO: If there isn't a connection to the same destination, then
+     * store it. If there is already a connection, then close it
+     */
+    synchronized void putConnection(Http2Connection c) {
+        String key = c.key();
+        connections.put(key, c);
+    }
+
+    synchronized void deleteConnection(Http2Connection c) {
+        String key = c.key();
+        connections.remove(key);
+    }
+
+    HttpClientImpl client() {
+        return client;
+    }
+
+    /** Returns the client settings as a base64 (url) encoded string */
+    String getSettingsString() {
+        SettingsFrame sf = getClientSettings();
+        ByteBufferGenerator bg = new ByteBufferGenerator(client);
+        sf.writeOutgoing(bg);
+        byte[] settings = bg.asByteArray(9); // without the header
+        Base64.Encoder encoder = Base64.getUrlEncoder()
+                                       .withoutPadding();
+        return encoder.encodeToString(settings);
+    }
+
+    private static final int K = 1024;
+
+    SettingsFrame getClientSettings() {
+        SettingsFrame frame = new SettingsFrame();
+        frame.setParameter(HEADER_TABLE_SIZE, Utils.getIntegerNetProperty(
+            "java.net.httpclient.hpack.maxheadertablesize", 16 * K));
+        frame.setParameter(ENABLE_PUSH, Utils.getIntegerNetProperty(
+            "java.net.httpclient.enablepush", 1));
+        frame.setParameter(MAX_CONCURRENT_STREAMS, Utils.getIntegerNetProperty(
+            "java.net.httpclient.maxstreams", 16));
+        frame.setParameter(INITIAL_WINDOW_SIZE, Utils.getIntegerNetProperty(
+            "java.net.httpclient.windowsize", 32 * K));
+        frame.setParameter(MAX_FRAME_SIZE, Utils.getIntegerNetProperty(
+            "java.net.httpclient.maxframesize", 16 * K));
+        frame.computeLength();
+        return frame;
     }
 }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,42 +24,767 @@
 package java.net.http;
 
 import java.io.IOException;
-import java.net.Authenticator;
-import java.net.CookieManager;
-import java.net.ProxySelector;
+import java.net.InetSocketAddress;
 import java.net.URI;
-import static java.net.http.Utils.BUFSIZE;
+import java.net.http.HttpConnection.Mode;
 import java.nio.ByteBuffer;
-import java.nio.channels.SelectableChannel;
-import java.nio.channels.SelectionKey;
-import static java.nio.channels.SelectionKey.OP_CONNECT;
-import static java.nio.channels.SelectionKey.OP_READ;
-import static java.nio.channels.SelectionKey.OP_WRITE;
-import java.nio.channels.Selector;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Set;
-import java.util.concurrent.*;
-import java.security.NoSuchAlgorithmException;
-import java.util.ListIterator;
-import java.util.Optional;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import sun.net.httpclient.hpack.Encoder;
+import sun.net.httpclient.hpack.Decoder;
+import static java.net.http.SettingsFrame.*;
+import static java.net.http.Utils.BUFSIZE;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Formatter;
+import java.util.stream.Collectors;
+import sun.net.httpclient.hpack.DecodingCallback;
+
+/**
+ * An Http2Connection. Encapsulates the socket(channel) and any SSLEngine used
+ * over it. Contains an HttpConnection which hides the SocketChannel SSL stuff.
+ *
+ * Http2Connections belong to a Http2ClientImpl, (one of) which belongs
+ * to a HttpClientImpl.
+ *
+ * Creation cases:
+ * 1) upgraded HTTP/1.1 plain tcp connection
+ * 2) prior knowledge directly created plain tcp connection
+ * 3) directly created HTTP/2 SSL connection which uses ALPN.
+ *
+ * Sending is done by writing directly to underlying HttpConnection object which
+ * is operating in async mode. No flow control applies on output at this level
+ * and all writes are just executed as puts to an output Q belonging to HttpConnection
+ * Flow control is implemented by HTTP/2 protocol itself.
+ *
+ * Hpack header compression
+ * and outgoing stream creation is also done here, because these operations
+ * must be synchronized at the socket level. Stream objects send frames simply
+ * by placing them on the connection's output Queue. sendFrame() is called
+ * from a higher level (Stream) thread.
+ *
+ * asyncReceive(ByteBuffer) is always called from the selector thread. It assembles
+ * incoming Http2Frames, and directs them to the appropriate Stream.incoming()
+ * or handles them directly itself. This thread performs hpack decompression
+ * and incoming stream creation (Server push). Incoming frames destined for a
+ * stream are provided by calling Stream.incoming().
+ */
+class Http2Connection implements BufferHandler {
+
+    final Queue<Http2Frame> outputQ;
+    volatile boolean closed;
+
+    //-------------------------------------
+    final HttpConnection connection;
+    HttpClientImpl client;
+    final Http2ClientImpl client2;
+    Map<Integer,Stream> streams;
+    int nextstreamid = 3; // stream 1 is registered separately
+    int nextPushStream = 2;
+    Encoder hpackOut;
+    Decoder hpackIn;
+    SettingsFrame clientSettings, serverSettings;
+    ByteBufferConsumer bbc;
+    final LinkedList<ByteBuffer> freeList;
+    final String key; // for HttpClientImpl.connections map
+    FrameReader reader;
+
+    // Connection level flow control windows
+    int sendWindow = INITIAL_WINDOW_SIZE;
+
+    final static int DEFAULT_FRAME_SIZE = 16 * 1024;
+    private static ByteBuffer[] empty = Utils.EMPTY_BB_ARRAY;
+
+    final ExecutorWrapper executor;
+
+    /**
+     * This is established by the protocol spec and the peer will update it with
+     * WINDOW_UPDATEs, which affects the sendWindow.
+     */
+    final static int INITIAL_WINDOW_SIZE = 64 * 1024 - 1;
+
+    // TODO: need list of control frames from other threads
+    // that need to be sent
+
+    /**
+     * Case 1) Create from upgraded HTTP/1.1 connection.
+     * Is ready to use. Will not be SSL. exchange is the Exchange
+     * that initiated the connection, whose response will be delivered
+     * on a Stream.
+     */
+    Http2Connection(HttpConnection connection, Http2ClientImpl client2,
+            Exchange exchange) throws IOException, InterruptedException {
+        this.outputQ = new Queue<>();
+        String msg = "Connection send window size " + Integer.toString(sendWindow);
+        Log.logTrace(msg);
+
+        //this.initialExchange = exchange;
+        assert !(connection instanceof SSLConnection);
+        this.connection = connection;
+        this.client = client2.client();
+        this.client2 = client2;
+        this.executor = client.executorWrapper();
+        this.freeList = new LinkedList<>();
+        this.key = keyFor(connection);
+        streams = Collections.synchronizedMap(new HashMap<>());
+        initCommon();
+        //sendConnectionPreface();
+        Stream initialStream = createStream(exchange);
+        initialStream.registerStream(1);
+        initialStream.requestSent();
+        sendConnectionPreface();
+        connection.configureMode(Mode.ASYNC);
+        // start reading and writing
+        // start reading
+        AsyncConnection asyncConn = (AsyncConnection)connection;
+        asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown);
+        asyncReceive(connection.getRemaining());
+        asyncConn.startReading();
+    }
+
+    // async style but completes immediately
+    static CompletableFuture<Http2Connection> createAsync(HttpConnection connection,
+            Http2ClientImpl client2, Exchange exchange) {
+        CompletableFuture<Http2Connection> cf = new CompletableFuture<>();
+        try {
+            Http2Connection c = new Http2Connection(connection, client2, exchange);
+            cf.complete(c);
+        } catch (IOException | InterruptedException e) {
+            cf.completeExceptionally(e);
+        }
+        return cf;
+    }
+
+    /**
+     * Cases 2) 3)
+     *
+     * request is request to be sent.
+     */
+    Http2Connection(HttpRequestImpl request) throws IOException, InterruptedException {
+        InetSocketAddress proxy = request.proxy();
+        URI uri = request.uri();
+        InetSocketAddress addr = Utils.getAddress(request);
+        String msg = "Connection send window size " + Integer.toString(sendWindow);
+        Log.logTrace(msg);
+        this.key = keyFor(uri, proxy);
+        this.connection = HttpConnection.getConnection(addr, request, this);
+        streams = Collections.synchronizedMap(new HashMap<>());
+        this.client = request.client();
+        this.client2 = client.client2();
+        this.executor = client.executorWrapper();
+        this.freeList = new LinkedList<>();
+        this.outputQ = new Queue<>();
+        nextstreamid = 1;
+        initCommon();
+        connection.connect();
+        connection.configureMode(Mode.ASYNC);
+        // start reading
+        AsyncConnection asyncConn = (AsyncConnection)connection;
+        asyncConn.setAsyncCallbacks(this::asyncReceive, this::shutdown);
+        sendConnectionPreface();
+        asyncConn.startReading();
+    }
+
+    // NEW
+    synchronized void obtainSendWindow(int amount) throws InterruptedException {
+        while (amount > 0) {
+            int n = Math.min(amount, sendWindow);
+            sendWindow -= n;
+            amount -= n;
+            if (amount > 0)
+                wait();
+        }
+    }
+
+    synchronized void updateSendWindow(int amount) {
+        if (sendWindow == 0) {
+            sendWindow += amount;
+            notifyAll();
+        } else
+            sendWindow += amount;
+    }
+
+    synchronized int sendWindow() {
+        return sendWindow;
+    }
+
+    static String keyFor(HttpConnection connection) {
+        boolean isProxy = connection.isProxied();
+        boolean isSecure = connection.isSecure();
+        InetSocketAddress addr = connection.address();
+
+        return keyString(isSecure, isProxy, addr.getHostString(), addr.getPort());
+    }
+
+    static String keyFor(URI uri, InetSocketAddress proxy) {
+        boolean isSecure = uri.getScheme().equalsIgnoreCase("https");
+        boolean isProxy = proxy != null;
+
+        String host;
+        int port;
+
+        if (isProxy) {
+            host = proxy.getHostString();
+            port = proxy.getPort();
+        } else {
+            host = uri.getHost();
+            port = uri.getPort();
+        }
+        return keyString(isSecure, isProxy, host, port);
+    }
+
+    // {C,S}:{H:P}:host:port
+    // C indicates clear text connection "http"
+    // S indicates secure "https"
+    // H indicates host (direct) connection
+    // P indicates proxy
+    // Eg: "S:H:foo.com:80"
+    static String keyString(boolean secure, boolean proxy, String host, int port) {
+        char c1 = secure ? 'S' : 'C';
+        char c2 = proxy ? 'P' : 'H';
+
+        StringBuilder sb = new StringBuilder(128);
+        sb.append(c1).append(':').append(c2).append(':')
+                .append(host).append(':').append(port);
+        return sb.toString();
+    }
+
+    String key() {
+        return this.key;
+    }
+
+    void putConnection() {
+        client2.putConnection(this);
+    }
+
+    private static String toHexdump1(ByteBuffer bb) {
+        bb.mark();
+        StringBuilder sb = new StringBuilder(512);
+        Formatter f = new Formatter(sb);
+
+        while (bb.hasRemaining()) {
+            int i =  Byte.toUnsignedInt(bb.get());
+            f.format("%02x:", i);
+        }
+        sb.deleteCharAt(sb.length()-1);
+        bb.reset();
+        return sb.toString();
+    }
+
+    private static String toHexdump(ByteBuffer bb) {
+        List<String> words = new ArrayList<>();
+        int i = 0;
+        bb.mark();
+        while (bb.hasRemaining()) {
+            if (i % 2 == 0) {
+                words.add("");
+            }
+            byte b = bb.get();
+            String hex = Integer.toHexString(256 + Byte.toUnsignedInt(b)).substring(1);
+            words.set(i / 2, words.get(i / 2) + hex);
+            i++;
+        }
+        bb.reset();
+        return words.stream().collect(Collectors.joining(" "));
+    }
+
+    private void decodeHeaders(HeaderFrame frame, DecodingCallback decoder) {
+        boolean endOfHeaders = frame.getFlag(HeaderFrame.END_HEADERS);
+
+        ByteBuffer[] buffers = frame.getHeaderBlock();
+        for (int i = 0; i < buffers.length; i++) {
+            hpackIn.decode(buffers[i], endOfHeaders, decoder);
+        }
+    }
+
+    int getInitialSendWindowSize() {
+        return serverSettings.getParameter(SettingsFrame.INITIAL_WINDOW_SIZE);
+    }
+
+    void close() {
+        GoAwayFrame f = new GoAwayFrame();
+        f.setDebugData("Requested by user".getBytes());
+        // TODO: set last stream. For now zero ok.
+        sendFrame(f);
+    }
+
+    // BufferHandler methods
+
+    @Override
+    public ByteBuffer getBuffer(int n) {
+        return client.getBuffer(n);
+    }
+
+    @Override
+    public void returnBuffer(ByteBuffer buf) {
+        client.returnBuffer(buf);
+    }
 
-class Http2Connection {
-    static CompletableFuture<Http2Connection> createAsync(
-        HttpConnection connection, Http2ClientImpl client2, Exchange exchange) {
-            return null;
+    @Override
+    public void setMinBufferSize(int n) {
+        client.setMinBufferSize(n);
+    }
+
+    private final Object readlock = new Object();
+
+    void asyncReceive(ByteBuffer buffer) {
+        synchronized (readlock) {
+            try {
+                if (reader == null) {
+                    reader = new FrameReader(buffer);
+                } else {
+                    reader.input(buffer);
+                }
+                while (true) {
+                    if (reader.haveFrame()) {
+                        List<ByteBuffer> buffers = reader.frame();
+
+                        ByteBufferConsumer bbc = new ByteBufferConsumer(buffers, this::getBuffer);
+                        processFrame(bbc);
+                        if (bbc.consumed()) {
+                            reader = new FrameReader();
+                            return;
+                        } else {
+                            reader = new FrameReader(reader);
+                        }
+                    } else
+                        return;
+                }
+            } catch (Throwable e) {
+                String msg = Utils.stackTrace(e);
+                Log.logTrace(msg);
+                shutdown(e);
+            }
+        }
+    }
+
+    void shutdown(Throwable t) {
+        System.err.println("Shutdown: " + t);
+        t.printStackTrace();
+        closed = true;
+        client2.deleteConnection(this);
+        Collection<Stream> c = streams.values();
+        for (Stream s : c) {
+            s.cancelImpl(t);
+        }
+        connection.close();
+    }
+
+    /**
+     * Handles stream 0 (common) frames that apply to whole connection and passes
+     * other stream specific frames to that Stream object.
+     *
+     * Invokes Stream.incoming() which is expected to process frame without
+     * blocking.
+     */
+    void processFrame(ByteBufferConsumer bbc) throws IOException, InterruptedException {
+        Http2Frame frame = Http2Frame.readIncoming(bbc);
+        Log.logFrames(frame, "IN");
+        int streamid = frame.streamid();
+        if (streamid == 0) {
+            handleCommonFrame(frame);
+        } else {
+            Stream stream = getStream(streamid);
+            if (stream == null) {
+                // should never receive a frame with unknown stream id
+                resetStream(streamid, ResetFrame.PROTOCOL_ERROR);
+            }
+            if (frame instanceof PushPromiseFrame) {
+                PushPromiseFrame pp = (PushPromiseFrame)frame;
+                handlePushPromise(stream, pp);
+            } else if (frame instanceof HeaderFrame) {
+                // decode headers (or continuation)
+                decodeHeaders((HeaderFrame) frame, stream.rspHeadersConsumer());
+                stream.incoming(frame);
+            } else
+                stream.incoming(frame);
+        }
+    }
+
+    private void handlePushPromise(Stream parent, PushPromiseFrame pp)
+            throws IOException, InterruptedException {
+
+        HttpRequestImpl parentReq = parent.request;
+        int promisedStreamid = pp.getPromisedStream();
+        if (promisedStreamid != nextPushStream) {
+            resetStream(promisedStreamid, ResetFrame.PROTOCOL_ERROR);
+            return;
+        } else {
+            nextPushStream += 2;
+        }
+        HeaderDecoder decoder = new HeaderDecoder();
+        decodeHeaders(pp, decoder);
+        HttpHeadersImpl headers = decoder.headers();
+        HttpRequestImpl pushReq = HttpRequestImpl.createPushRequest(parentReq, headers);
+
+        Stream.PushedStream pushStream = createPushStream(parent, pushReq);
+        pushStream.registerStream(promisedStreamid);
+        parent.incoming_pushPromise(pushReq, pushStream);
+    }
+
+    private void handleCommonFrame(Http2Frame frame)
+            throws IOException, InterruptedException {
+
+        switch (frame.type()) {
+          case SettingsFrame.TYPE:
+          { SettingsFrame f = (SettingsFrame)frame;
+            handleSettings(f);}
+            break;
+          case PingFrame.TYPE:
+          { PingFrame f = (PingFrame)frame;
+            handlePing(f);}
+            break;
+          case GoAwayFrame.TYPE:
+          { GoAwayFrame f = (GoAwayFrame)frame;
+            handleGoAway(f);}
+            break;
+          case WindowUpdateFrame.TYPE:
+          { WindowUpdateFrame f = (WindowUpdateFrame)frame;
+            handleWindowUpdate(f);}
+            break;
+          default:
+            protocolError(ErrorFrame.PROTOCOL_ERROR);
+        }
+    }
+
+    void resetStream(int streamid, int code) throws IOException, InterruptedException {
+        Log.logError(
+            "Resetting stream {0,number,integer} with error code {1,number,integer}",
+            streamid, code);
+        ResetFrame frame = new ResetFrame();
+        frame.streamid(streamid);
+        frame.setErrorCode(code);
+        sendFrame(frame);
+        streams.remove(streamid);
+    }
+
+    private void handleWindowUpdate(WindowUpdateFrame f)
+            throws IOException, InterruptedException {
+        updateSendWindow(f.getUpdate());
+    }
+
+    private void protocolError(int errorCode)
+            throws IOException, InterruptedException {
+        GoAwayFrame frame = new GoAwayFrame();
+        frame.setErrorCode(errorCode);
+        sendFrame(frame);
+        String msg = "Error code: " + errorCode;
+        shutdown(new IOException("protocol error"));
+    }
+
+    private void handleSettings(SettingsFrame frame)
+            throws IOException, InterruptedException {
+        if (frame.getFlag(SettingsFrame.ACK)) {
+            // ignore ack frames for now.
+            return;
+        }
+        serverSettings = frame;
+        SettingsFrame ack = getAckFrame(frame.streamid());
+        sendFrame(ack);
+    }
+
+    private void handlePing(PingFrame frame)
+            throws IOException, InterruptedException {
+        frame.setFlag(PingFrame.ACK);
+        sendFrame(frame);
+    }
+
+    private void handleGoAway(GoAwayFrame frame)
+            throws IOException, InterruptedException {
+        //System.err.printf("GoAWAY: %s\n", ErrorFrame.stringForCode(frame.getErrorCode()));
+        shutdown(new IOException("GOAWAY received"));
+    }
+
+    private void initCommon() {
+        clientSettings = client2.getClientSettings();
+
+        // serverSettings will be updated by server
+        serverSettings = SettingsFrame.getDefaultSettings();
+        hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE));
+        hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
+    }
+
+    /**
+     * Max frame size we are allowed to send
+     */
+    public int getMaxSendFrameSize() {
+        int param = serverSettings.getParameter(MAX_FRAME_SIZE);
+        if (param == -1) {
+            param = DEFAULT_FRAME_SIZE;
+        }
+        return param;
+    }
+
+    /**
+     * Max frame size we will receive
+     */
+    public int getMaxReceiveFrameSize() {
+        return clientSettings.getParameter(MAX_FRAME_SIZE);
+    }
+
+    // Not sure how useful this is.
+    public int getMaxHeadersSize() {
+        return serverSettings.getParameter(MAX_HEADER_LIST_SIZE);
+    }
+
+    private static final String CLIENT_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
+
+    private static final byte[] PREFACE_BYTES =
+        CLIENT_PREFACE.getBytes(StandardCharsets.ISO_8859_1);
+
+    /**
+     * Sends Connection preface and Settings frame with current preferred
+     * values
+     */
+    private void sendConnectionPreface() throws IOException {
+        ByteBufferGenerator bg = new ByteBufferGenerator(this);
+        bg.getBuffer(PREFACE_BYTES.length).put(PREFACE_BYTES);
+        ByteBuffer[] ba = bg.getBufferArray();
+        connection.write(ba, 0, ba.length);
+
+        bg = new ByteBufferGenerator(this);
+        SettingsFrame sf = client2.getClientSettings();
+        Log.logFrames(sf, "OUT");
+        sf.writeOutgoing(bg);
+        WindowUpdateFrame wup = new WindowUpdateFrame();
+        wup.streamid(0);
+        // send a Window update for the receive buffer we are using
+        // minus the initial 64 K specified in protocol
+        wup.setUpdate(client2.client().getReceiveBufferSize() - (64 * 1024 - 1));
+        wup.computeLength();
+        wup.writeOutgoing(bg);
+        Log.logFrames(wup, "OUT");
+        ba = bg.getBufferArray();
+        connection.write(ba, 0, ba.length);
+    }
+
+    /**
+     * Returns an existing Stream with given id, or null if doesn't exist
+     */
+    Stream getStream(int streamid) {
+        return streams.get(streamid);
+    }
+
+    /**
+     * Creates Stream with given id.
+     */
+    Stream createStream(Exchange exchange) {
+        Stream stream = new Stream(client, this, exchange);
+        return stream;
+    }
+
+    Stream.PushedStream createPushStream(Stream parent, HttpRequestImpl pushReq) {
+        Stream.PushGroup<?> pg = parent.request.pushGroup();
+        return new Stream.PushedStream(pg, client, this, parent, pushReq);
+    }
+
+    void putStream(Stream stream, int streamid) {
+        streams.put(streamid, stream);
+    }
+
+    void deleteStream(Stream stream) {
+        streams.remove(stream.streamid);
+    }
+
+    static final int MAX_STREAM = Integer.MAX_VALUE - 2;
+
+    // Number of header bytes in a Headers Frame
+    final static int HEADERS_HEADER_SIZE = 15;
+
+    // Number of header bytes in a Continuation frame
+    final static int CONTIN_HEADER_SIZE = 9;
+
+    /**
+     * Encode the headers into a List<ByteBuffer> and then create HEADERS
+     * and CONTINUATION frames from the list and return the List<Http2Frame>.
+     *
+     * @param frame
+     * @return
+     */
+    private LinkedList<Http2Frame> encodeHeaders(OutgoingHeaders frame) {
+        LinkedList<ByteBuffer> buffers = new LinkedList<>();
+        ByteBuffer buf = getBuffer();
+        buffers.add(buf);
+        encodeHeadersImpl(frame.stream.getRequestPseudoHeaders(), buffers);
+        encodeHeadersImpl(frame.getUserHeaders(), buffers);
+        encodeHeadersImpl(frame.getSystemHeaders(), buffers);
+
+        for (ByteBuffer b : buffers) {
+            b.flip();
         }
 
-    Http2Connection(HttpConnection connection, Http2ClientImpl client2,
-            Exchange exchange) throws IOException, InterruptedException {
+        LinkedList<Http2Frame> frames = new LinkedList<>();
+        int maxframesize = getMaxSendFrameSize();
+
+        HeadersFrame oframe = new HeadersFrame();
+        oframe.setFlags(frame.getFlags());
+        oframe.streamid(frame.streamid());
+
+        oframe.setHeaderBlock(getBufferArray(buffers, maxframesize));
+        frames.add(oframe);
+        // Any buffers left?
+        boolean done = buffers.isEmpty();
+        if (done) {
+            oframe.setFlag(HeaderFrame.END_HEADERS);
+        } else {
+            ContinuationFrame cf = null;
+            while (!done) {
+                cf = new ContinuationFrame();
+                cf.streamid(frame.streamid());
+                cf.setHeaderBlock(getBufferArray(buffers, maxframesize));
+                frames.add(cf);
+                done = buffers.isEmpty();
+            }
+            cf.setFlag(HeaderFrame.END_HEADERS);
+        }
+        return frames;
+    }
+
+    // should always return at least one buffer
+    private static ByteBuffer[] getBufferArray(LinkedList<ByteBuffer> list, int maxsize) {
+        assert maxsize >= BUFSIZE;
+        LinkedList<ByteBuffer> newlist = new LinkedList<>();
+        int size = list.size();
+        int nbytes = 0;
+        for (int i=0; i<size; i++) {
+            ByteBuffer buf = list.getFirst();
+            if (nbytes + buf.remaining() <= maxsize) {
+                nbytes += buf.remaining();
+                newlist.add(buf);
+                list.remove();
+            } else {
+                break;
+            }
+        }
+        return newlist.toArray(empty);
+    }
+
+    /**
+     * Encode all the headers from the given HttpHeadersImpl into the given List.
+     */
+    private void encodeHeadersImpl(HttpHeaders hdrs, LinkedList<ByteBuffer> buffers) {
+        ByteBuffer buffer;
+        if (!(buffer = buffers.getLast()).hasRemaining()) {
+            buffer = getBuffer();
+            buffers.add(buffer);
+        }
+        for (Map.Entry<String, List<String>> e : hdrs.map().entrySet()) {
+            String key = e.getKey();
+            String lkey = key.toLowerCase();
+            List<String> values = e.getValue();
+            for (String value : values) {
+                hpackOut.header(lkey, value);
+                boolean encoded = false;
+                do {
+                    encoded = hpackOut.encode(buffer);
+                    if (!encoded) {
+                        buffer = getBuffer();
+                        buffers.add(buffer);
+                    }
+                } while (!encoded);
+            }
+        }
+    }
+
+    public void sendFrames(List<Http2Frame> frames) throws IOException, InterruptedException {
+        for (Http2Frame frame : frames) {
+            sendFrame(frame);
+        }
     }
 
-    Stream getStream(int i) {return null;}
-    Stream createStream(Exchange ex) {return null;}
-    void putConnection() {}
+    static Throwable getExceptionFrom(CompletableFuture<?> cf) {
+        try {
+            cf.get();
+            return null;
+        } catch (Throwable e) {
+            if (e.getCause() != null)
+                return e.getCause();
+            else
+                return e;
+        }
+    }
+
+
+    void execute(Runnable r) {
+        executor.execute(r, null);
+    }
+
+    private final Object sendlock = new Object();
+
+    /**
+     *
+     */
+    void sendFrame(Http2Frame frame) {
+        synchronized (sendlock) {
+            try {
+                if (frame instanceof OutgoingHeaders) {
+                    OutgoingHeaders oh = (OutgoingHeaders) frame;
+                    Stream stream = oh.getStream();
+                    stream.registerStream(nextstreamid);
+                    oh.streamid(nextstreamid);
+                    nextstreamid += 2;
+                    // set outgoing window here. This allows thread sending
+                    // body to proceed.
+                    stream.updateOutgoingWindow(getInitialSendWindowSize());
+                    LinkedList<Http2Frame> frames = encodeHeaders(oh);
+                    for (Http2Frame f : frames) {
+                        sendOneFrame(f);
+                    }
+                } else {
+                    sendOneFrame(frame);
+                }
+
+            } catch (IOException e) {
+                if (!closed) {
+                    Log.logError(e);
+                    shutdown(e);
+                }
+            }
+        }
+    }
+
+    /**
+     * Send a frame.
+     *
+     * @param frame
+     * @throws IOException
+     */
+    private void sendOneFrame(Http2Frame frame) throws IOException {
+        ByteBufferGenerator bbg = new ByteBufferGenerator(this);
+        frame.computeLength();
+        Log.logFrames(frame, "OUT");
+        frame.writeOutgoing(bbg);
+        ByteBuffer[] currentBufs = bbg.getBufferArray();
+        connection.write(currentBufs, 0, currentBufs.length);
+    }
+
+
+    private SettingsFrame getAckFrame(int streamid) {
+        SettingsFrame frame = new SettingsFrame();
+        frame.setFlag(SettingsFrame.ACK);
+        frame.streamid(streamid);
+        return frame;
+    }
+
+    static class HeaderDecoder implements DecodingCallback {
+        HttpHeadersImpl headers;
+
+        HeaderDecoder() {
+            this.headers = new HttpHeadersImpl();
+        }
+
+        @Override
+        public void onDecoded(CharSequence name, CharSequence value) {
+            headers.addHeader(name.toString(), value.toString());
+        }
+
+        HttpHeadersImpl headers() {
+            return headers;
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,211 @@
+/*
+ * 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
+ */
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * When sending a frame, the length field must be set in sub-class
+ * by calling computeLength()
+ */
+abstract class Http2Frame {
+
+    int length = -1;
+    int type;
+    int streamid;
+    int flags;
+
+    // called when reading in only
+    void initCommon(int length, int type, int streamid, int flags) {
+        this.length = length;
+        this.type = type;
+        this.streamid = streamid;
+        this.flags = flags;
+    }
+
+    public int length() {
+        return length;
+    }
+
+    public int type() {
+        return type;
+    }
+
+    public int streamid() {
+        return streamid;
+    }
+
+    public void setFlag(int flag) {
+        flags |= flag;
+    }
+
+    public void setFlags(int flags) {
+        this.flags = flags;
+    }
+
+    public int getFlags() {
+        return flags;
+    }
+
+    public boolean getFlag(int flag) {
+        return (flags & flag) != 0;
+    }
+
+    public void clearFlag(int flag) {
+        flags &= 0xffffffff ^ flag;
+    }
+
+    public void streamid(int streamid) {
+        this.streamid = streamid;
+    }
+
+    abstract void readIncomingImpl(ByteBufferConsumer bc) throws IOException;
+
+    /**
+     * assume given array contains at least one complete frame.
+     */
+    static Http2Frame readIncoming(ByteBufferConsumer bc) throws IOException {
+        int x = bc.getInt();
+        int length = x >> 8;
+        int type = x & 0xff;
+        int flags = bc.getByte();
+        int streamid = bc.getInt();
+        Http2Frame f = null;
+        switch (type) {
+          case DataFrame.TYPE:
+            f = new DataFrame();
+            break;
+          case HeadersFrame.TYPE:
+            f = new HeadersFrame();
+            break;
+          case ContinuationFrame.TYPE:
+            f = new ContinuationFrame();
+            break;
+          case ResetFrame.TYPE:
+            f = new ResetFrame();
+            break;
+          case PriorityFrame.TYPE:
+            f = new PriorityFrame();
+            break;
+          case SettingsFrame.TYPE:
+            f = new SettingsFrame();
+            break;
+          case GoAwayFrame.TYPE:
+            f = new GoAwayFrame();
+            break;
+          case PingFrame.TYPE:
+            f = new PingFrame();
+            break;
+          case PushPromiseFrame.TYPE:
+            f = new PushPromiseFrame();
+            break;
+          case WindowUpdateFrame.TYPE:
+            f = new WindowUpdateFrame();
+            break;
+          default:
+            String msg = Integer.toString(type);
+            throw new IOException("unknown frame type " + msg);
+        }
+        f.initCommon(length, type, streamid, flags);
+        f.readIncomingImpl(bc);
+        return f;
+    }
+
+    public String typeAsString() {
+        return asString(this.type);
+    }
+
+    public static String asString(int type) {
+        switch (type) {
+          case DataFrame.TYPE:
+            return "DATA";
+          case HeadersFrame.TYPE:
+            return "HEADERS";
+          case ContinuationFrame.TYPE:
+            return "CONTINUATION";
+          case ResetFrame.TYPE:
+            return "RESET";
+          case PriorityFrame.TYPE:
+            return "PRIORITY";
+          case SettingsFrame.TYPE:
+            return "SETTINGS";
+          case GoAwayFrame.TYPE:
+            return "GOAWAY";
+          case PingFrame.TYPE:
+            return "PING";
+          case PushPromiseFrame.TYPE:
+            return "PUSH_PROMISE";
+          case WindowUpdateFrame.TYPE:
+            return "WINDOW_UPDATE";
+          default:
+            return "UNKNOWN";
+        }
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(typeAsString())
+                .append(": length=")
+                .append(Integer.toString(length))
+                .append(", streamid=")
+                .append(streamid)
+                .append(", flags=");
+
+        int f = flags;
+        int i = 0;
+        if (f == 0) {
+            sb.append("0 ");
+        } else {
+            while (f != 0) {
+                if ((f & 1) == 1) {
+                    sb.append(flagAsString(1 << i))
+                      .append(' ');
+                }
+                f = f >> 1;
+                i++;
+            }
+        }
+        return sb.toString();
+    }
+
+    // Override
+    String flagAsString(int f) {
+        return "unknown";
+    }
+
+    abstract void computeLength();
+
+    void writeOutgoing(ByteBufferGenerator bg) {
+        if (length == -1) {
+            throw new InternalError("Length not set on outgoing frame");
+        }
+        ByteBuffer buf = bg.getBuffer(9);
+        int x = (length << 8) + type;
+        buf.putInt(x);
+        buf.put((byte)flags);
+        buf.putInt(streamid);
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,28 +23,32 @@
  */
 package java.net.http;
 
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
 import java.io.IOException;
 import java.net.Authenticator;
 import java.net.CookieManager;
 import java.net.ProxySelector;
 import java.net.URI;
-import static java.net.http.Utils.BUFSIZE;
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.SelectableChannel;
 import java.nio.channels.SelectionKey;
-import static java.nio.channels.SelectionKey.OP_CONNECT;
-import static java.nio.channels.SelectionKey.OP_READ;
-import static java.nio.channels.SelectionKey.OP_WRITE;
 import java.nio.channels.Selector;
-import java.util.*;
-import java.util.stream.Stream;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
-import java.security.NoSuchAlgorithmException;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLParameters;
+import java.util.stream.Stream;
+
+import static java.net.http.Utils.BUFSIZE;
 
 /**
  * Client implementation. Contains all configuration information and also
@@ -53,6 +57,9 @@
  */
 class HttpClientImpl extends HttpClient implements BufferHandler {
 
+    private static final ThreadFactory defaultFactory =
+            (r -> new Thread(null, r, "HttpClient_worker", 0, true));
+
     private final CookieManager cookieManager;
     private final Redirect followRedirects;
     private final ProxySelector proxySelector;
@@ -67,7 +74,6 @@
     private final SelectorManager selmgr;
     private final FilterFactory filters;
     private final Http2ClientImpl client2;
-    private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory();
     private final LinkedList<TimeoutEvent> timeouts;
 
     public static HttpClientImpl create(HttpClientBuilderImpl builder) {
@@ -115,7 +121,6 @@
             throw new InternalError(e);
         }
         selmgr.setDaemon(true);
-        selmgr.setName("HttpSelector");
         filters = new FilterFactory();
         initFilters();
     }
@@ -135,7 +140,7 @@
      *  4)   - mark connection as blocking
      *  5)   - call AsyncEvent.handle()
      *
-     *  If exchange needs to block again, then call registerEvent() again
+     * If exchange needs to block again, then call registerEvent() again
      */
     void registerEvent(AsyncEvent exchange) throws IOException {
         selmgr.register(exchange);
@@ -145,35 +150,56 @@
         return client2;
     }
 
-    LinkedList<ByteBuffer> freelist = new LinkedList<>();
+    /**
+     * We keep one size of buffer on free list. That size may increase
+     * depending on demand. If that happens we dispose of free buffers
+     * that are smaller than new size.
+     */
+    private final LinkedList<ByteBuffer> freelist = new LinkedList<>();
+    int currentSize = BUFSIZE;
 
     @Override
-    public synchronized ByteBuffer getBuffer() {
-        if (freelist.isEmpty()) {
-            return ByteBuffer.allocate(BUFSIZE);
+    public synchronized ByteBuffer getBuffer(int size) {
+
+        ByteBuffer buf;
+        if (size == -1)
+            size = currentSize;
+
+        if (size > currentSize)
+            currentSize = size;
+
+        while (!freelist.isEmpty()) {
+            buf = freelist.removeFirst();
+            if (buf.capacity() < currentSize)
+                continue;
+            buf.clear();
+            return buf;
         }
-        return freelist.removeFirst();
+        return ByteBuffer.allocate(size);
     }
 
     @Override
     public synchronized void returnBuffer(ByteBuffer buffer) {
-        buffer.clear();
         freelist.add(buffer);
     }
 
+    @Override
+    public synchronized void setMinBufferSize(int n) {
+        currentSize = Math.max(n, currentSize);
+    }
 
     // Main loop for this client's selector
+    private final class SelectorManager extends Thread {
 
-    class SelectorManager extends Thread {
-        final Selector selector;
-        boolean closed;
-
-        final List<AsyncEvent> readyList;
-        final List<AsyncEvent> registrations;
+        private final Selector selector;
+        private volatile boolean closed;
+        private final List<AsyncEvent> readyList;
+        private final List<AsyncEvent> registrations;
 
         SelectorManager() throws IOException {
-            readyList = new LinkedList<>();
-            registrations = new LinkedList<>();
+            super(null, null, "SelectorManager", 0, false);
+            readyList = new ArrayList<>();
+            registrations = new ArrayList<>();
             selector = Selector.open();
         }
 
@@ -193,32 +219,13 @@
             closed = true;
             try {
                 selector.close();
-            } catch (IOException e) {}
-        }
-
-        private List<AsyncEvent> copy(List<AsyncEvent> list) {
-            LinkedList<AsyncEvent> c = new LinkedList<>();
-            for (AsyncEvent e : list) {
-                c.add(e);
-            }
-            return c;
-        }
-
-        String opvals(int i) {
-            StringBuilder sb = new StringBuilder();
-            if ((i & OP_READ) != 0)
-                sb.append("OP_READ ");
-            if ((i & OP_CONNECT) != 0)
-                sb.append("OP_CONNECT ");
-            if ((i & OP_WRITE) != 0)
-                sb.append("OP_WRITE ");
-            return sb.toString();
+            } catch (IOException ignored) { }
         }
 
         @Override
         public void run() {
             try {
-                while (true) {
+                while (!Thread.currentThread().isInterrupted()) {
                     synchronized (this) {
                         for (AsyncEvent exchange : registrations) {
                             SelectableChannel c = exchange.channel();
@@ -229,7 +236,7 @@
                                 if (key == null) {
                                     sa = new SelectorAttachment(c, selector);
                                 } else {
-                                    sa = (SelectorAttachment)key.attachment();
+                                    sa = (SelectorAttachment) key.attachment();
                                 }
                                 sa.register(exchange);
                             } catch (IOException e) {
@@ -243,6 +250,7 @@
                     }
                     long timeval = getTimeoutValue();
                     long now = System.currentTimeMillis();
+                    //debugPrint(selector);
                     int n = selector.select(timeval);
                     if (n == 0) {
                         signalTimeouts(now);
@@ -251,7 +259,7 @@
                     Set<SelectionKey> keys = selector.selectedKeys();
 
                     for (SelectionKey key : keys) {
-                        SelectorAttachment sa = (SelectorAttachment)key.attachment();
+                        SelectorAttachment sa = (SelectorAttachment) key.attachment();
                         int eventsOccurred = key.readyOps();
                         sa.events(eventsOccurred).forEach(readyList::add);
                         sa.resetInterestOps(eventsOccurred);
@@ -260,10 +268,8 @@
                     selector.selectedKeys().clear();
 
                     for (AsyncEvent exchange : readyList) {
-                        if (exchange instanceof AsyncEvent.Blocking) {
+                        if (exchange.blocking()) {
                             exchange.channel().configureBlocking(true);
-                        } else {
-                            assert exchange instanceof AsyncEvent.NonBlocking;
                         }
                         executor.synchronize();
                         handleEvent(exchange); // will be delegated to executor
@@ -272,14 +278,26 @@
                 }
             } catch (Throwable e) {
                 if (!closed) {
-                    System.err.println("HttpClientImpl terminating on error");
                     // This terminates thread. So, better just print stack trace
                     String err = Utils.stackTrace(e);
                     Log.logError("HttpClientImpl: fatal error: " + err);
                 }
+            } finally {
+                shutdown();
             }
         }
 
+        void debugPrint(Selector selector) {
+            System.err.println("Selector: debugprint start");
+            Set<SelectionKey> keys = selector.keys();
+            for (SelectionKey key : keys) {
+                SelectableChannel c = key.channel();
+                int ops = key.interestOps();
+                System.err.printf("selector chan:%s ops:%d\n", c, ops);
+            }
+            System.err.println("Selector: debugprint end");
+        }
+
         void handleEvent(AsyncEvent e) {
             if (closed) {
                 e.abort();
@@ -303,7 +321,7 @@
         private final SelectableChannel chan;
         private final Selector selector;
         private final ArrayList<AsyncEvent> pending;
-        private int interestops;
+        private int interestOps;
 
         SelectorAttachment(SelectableChannel chan, Selector selector) {
             this.pending = new ArrayList<>();
@@ -312,53 +330,53 @@
         }
 
         void register(AsyncEvent e) throws ClosedChannelException {
-            int newops = e.interestOps();
-            boolean reRegister = (interestops & newops) != newops;
-            interestops |= newops;
+            int newOps = e.interestOps();
+            boolean reRegister = (interestOps & newOps) != newOps;
+            interestOps |= newOps;
             pending.add(e);
             if (reRegister) {
                 // first time registration happens here also
-                chan.register(selector, interestops, this);
+                chan.register(selector, interestOps, this);
             }
         }
 
-        int interestOps() {
-            return interestops;
-        }
-
         /**
          * Returns a Stream<AsyncEvents> containing only events that are
-         * registered with the given {@code interestop}.
+         * registered with the given {@code interestOps}.
          */
-        Stream<AsyncEvent> events(int interestop) {
+        Stream<AsyncEvent> events(int interestOps) {
             return pending.stream()
-                          .filter(ev -> (ev.interestOps() & interestop) != 0);
+                    .filter(ev -> (ev.interestOps() & interestOps) != 0);
         }
 
         /**
-         * Removes any events with the given {@code interestop}, and if no
+         * Removes any events with the given {@code interestOps}, and if no
          * events remaining, cancels the associated SelectionKey.
          */
-        void resetInterestOps(int interestop) {
-            int newops = 0;
+        void resetInterestOps(int interestOps) {
+            int newOps = 0;
 
             Iterator<AsyncEvent> itr = pending.iterator();
             while (itr.hasNext()) {
                 AsyncEvent event = itr.next();
                 int evops = event.interestOps();
-                if ((evops & interestop) != 0) {
+                if (event.repeating()) {
+                    newOps |= evops;
+                    continue;
+                }
+                if ((evops & interestOps) != 0) {
                     itr.remove();
                 } else {
-                    newops |= evops;
+                    newOps |= evops;
                 }
             }
 
-            interestops = newops;
+            this.interestOps = newOps;
             SelectionKey key = chan.keyFor(selector);
-            if (newops == 0) {
+            if (newOps == 0) {
                 key.cancel();
             } else {
-                key.interestOps(newops);
+                key.interestOps(newOps);
             }
         }
     }
@@ -366,7 +384,8 @@
     /**
      * Creates a HttpRequest associated with this group.
      *
-     * @throws IllegalStateException if the group has been stopped
+     * @throws IllegalStateException
+     *         if the group has been stopped
      */
     @Override
     public HttpRequestBuilderImpl request() {
@@ -376,7 +395,8 @@
     /**
      * Creates a HttpRequest associated with this group.
      *
-     * @throws IllegalStateException if the group has been stopped
+     * @throws IllegalStateException
+     *         if the group has been stopped
      */
     @Override
     public HttpRequestBuilderImpl request(URI uri) {
@@ -444,16 +464,12 @@
         return version.equals(Version.HTTP_2);
     }
 
-    //void setHttp2NotSupported(String host) {
-        //http2NotSupported.put(host, false);
-    //}
-
-    final void initFilters() {
+    private void initFilters() {
         addFilter(AuthenticationFilter.class);
         addFilter(RedirectFilter.class);
     }
 
-    final void addFilter(Class<? extends HeaderFilter> f) {
+    private void addFilter(Class<? extends HeaderFilter> f) {
         filters.addFilter(f);
     }
 
@@ -479,14 +495,14 @@
                 iter.previous();
                 break;
             } else if (!iter.hasNext()) {
-                event.delta = event.timeval - listval ;
+                event.delta = event.timeval - listval;
             }
         }
         iter.add(event);
         selmgr.wakeupSelector();
     }
 
-    synchronized void signalTimeouts(long then) {
+    private synchronized void signalTimeouts(long then) {
         if (timeouts.isEmpty()) {
             return;
         }
@@ -532,12 +548,12 @@
     // used for the connection window
     int getReceiveBufferSize() {
         return Utils.getIntegerNetProperty(
-                "sun.net.httpclient.connectionWindowSize", 256 * 1024
+                "java.net.httpclient.connectionWindowSize", 256 * 1024
         );
     }
 
     // returns 0 meaning block forever, or a number of millis to block for
-    synchronized long getTimeoutValue() {
+    private synchronized long getTimeoutValue() {
         if (timeouts.isEmpty()) {
             return 0;
         } else {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,9 +23,8 @@
  */
 package java.net.http;
 
-import java.io.FileOutputStream;
+import java.io.Closeable;
 import java.io.IOException;
-import java.io.PrintStream;
 import java.net.InetSocketAddress;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
@@ -42,7 +41,17 @@
  *      SSLConnection: TLS channel direct to server
  *      SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel
  */
-abstract class HttpConnection implements BufferHandler {
+abstract class HttpConnection implements BufferHandler, Closeable {
+
+    protected final static ByteBuffer emptyBuf = Utils.EMPTY_BYTEBUFFER;
+
+    enum Mode {
+        BLOCKING,
+        NON_BLOCKING,
+        ASYNC
+    }
+
+    protected Mode mode;
 
     // address we are connected to. Could be a server or a proxy
     final InetSocketAddress address;
@@ -52,6 +61,7 @@
     HttpConnection(InetSocketAddress address, HttpClientImpl client) {
         this.address = address;
         this.client = client;
+        this.buffer = emptyBuf;
     }
 
     /**
@@ -68,7 +78,21 @@
      */
     public static HttpConnection getConnection(InetSocketAddress addr,
                                                HttpRequestImpl request) {
-        return getConnectionImpl(addr, request);
+        return getConnectionImpl(addr, request, null);
+    }
+
+    /**
+     * Called specifically to get an async connection for HTTP/2 over SSL.
+     *
+     * @param addr
+     * @param request
+     * @param http2
+     * @return
+     */
+    public static HttpConnection getConnection(InetSocketAddress addr,
+        HttpRequestImpl request, Http2Connection http2) {
+
+        return getConnectionImpl(addr, request, http2);
     }
 
     public abstract void connect() throws IOException, InterruptedException;
@@ -93,7 +117,7 @@
     // at beginning of response.
     ByteBuffer getRemaining() {
         ByteBuffer b = buffer;
-        buffer = null;
+        buffer = emptyBuf;
         return b;
     }
 
@@ -123,17 +147,18 @@
     }
 
     private static HttpConnection getSSLConnection(InetSocketAddress addr,
-                                                   InetSocketAddress proxy,
-                                                   HttpRequestImpl request,
-                                                   String[] alpn) {
+            InetSocketAddress proxy, HttpRequestImpl request,
+            String[] alpn, Http2Connection http2) {
         HttpClientImpl client = request.client();
         if (proxy != null) {
             return new SSLTunnelConnection(addr,
                                            client,
                                            proxy,
                                            request.getAccessControlContext());
+        } else if (http2 == null) {
+            return new SSLConnection(addr, client, alpn);
         } else {
-            return new SSLConnection(addr, client, alpn);
+            return new AsyncSSLConnection(addr, client, alpn);
         }
     }
 
@@ -142,7 +167,8 @@
      * none available.
      */
     private static HttpConnection getConnectionImpl(InetSocketAddress addr,
-                                                    HttpRequestImpl request) {
+            HttpRequestImpl request, Http2Connection http2) {
+
         HttpConnection c;
         HttpClientImpl client = request.client();
         InetSocketAddress proxy = request.proxy();
@@ -167,7 +193,7 @@
             if (c != null) {
                 return c;
             } else {
-                return getSSLConnection(addr, proxy, request, alpn);
+                return getSSLConnection(addr, proxy, request, alpn, http2);
             }
         }
     }
@@ -223,64 +249,16 @@
         return address;
     }
 
-    void configureBlocking(boolean mode) throws IOException {
-        channel().configureBlocking(mode);
+    synchronized void configureMode(Mode mode) throws IOException {
+        this.mode = mode;
+        if (mode == Mode.BLOCKING)
+            channel().configureBlocking(true);
+        else
+            channel().configureBlocking(false);
     }
 
     abstract ConnectionPool.CacheKey cacheKey();
 
-    /*
-    static PrintStream ps;
-
-    static {
-        try {
-            String propval = Utils.getNetProperty("java.net.httpclient.showData");
-            if (propval != null && propval.equalsIgnoreCase("true")) {
-                ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false);
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-    synchronized final void debugPrint(String s, ByteBuffer b) {
-        ByteBuffer[] bufs = new ByteBuffer[1];
-        bufs[0] = b;
-        debugPrint(s, bufs, 0, 1);
-    }
-
-    synchronized final void debugPrint(String s,
-                                       ByteBuffer[] bufs,
-                                       int start,
-                                       int number) {
-        if (ps == null) {
-            return;
-        }
-
-        ps.printf("\n%s:\n", s);
-
-        for (int i=start; i<start+number; i++) {
-            ByteBuffer b = bufs[i].duplicate();
-            while (b.hasRemaining()) {
-                int c = b.get();
-                if (c == 10) {
-                    ps.printf("LF \n");
-                } else if (c == 13) {
-                    ps.printf(" CR ");
-                } else if (c == 0x20) {
-                    ps.printf("_");
-                } else if (c > 0x20 && c <= 0x7F) {
-                    ps.printf("%c", (char)c);
-                } else {
-                    ps.printf("0x%02x ", c);
-                }
-            }
-        }
-        ps.printf("\n---------------------\n");
-    }
-
-    */
-
     // overridden in SSL only
     SSLParameters sslParameters() {
         return null;
@@ -296,7 +274,8 @@
     /**
      * Closes this connection, by returning the socket to its connection pool.
      */
-    abstract void close();
+    @Override
+    public abstract void close();
 
     /**
      * Returns a ByteBuffer with data, or null if EOF.
@@ -356,12 +335,17 @@
     }
 
     @Override
-    public final ByteBuffer getBuffer() {
-        return client.getBuffer();
+    public final ByteBuffer getBuffer(int n) {
+        return client.getBuffer(n);
     }
 
     @Override
     public final void returnBuffer(ByteBuffer buffer) {
         client.returnBuffer(buffer);
     }
+
+    @Override
+    public final void setMinBufferSize(int n) {
+        client.setMinBufferSize(n);
+    }
 }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,44 +24,22 @@
 package java.net.http;
 
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.TreeMap;
 
 /**
  * Implementation of HttpHeaders.
  */
-class HttpHeadersImpl implements HttpHeaders1 {
+class HttpHeadersImpl implements HttpHeaders {
 
-    private final HashMap<String,List<String>> headers;
-    private boolean isUnmodifiable = false;
+    private final TreeMap<String,List<String>> headers;
 
     public HttpHeadersImpl() {
-        headers = new HashMap<>();
-    }
-
-    /**
-     * Replace all List<String> in headers with unmodifiable Lists. Call
-     * this only after all headers are added. The headers HashMap
-     * is wrapped with an unmodifiable HashMap in map()
-     */
-    @Override
-    public void makeUnmodifiable() {
-        if (isUnmodifiable)
-            return;
-
-        Set<String> keys = new HashSet<>(headers.keySet());
-        for (String key : keys) {
-            List<String> values = headers.remove(key);
-            if (values != null) {
-                headers.put(key, Collections.unmodifiableList(values));
-            }
-        }
-        isUnmodifiable = true;
+        headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
     }
 
     @Override
@@ -88,7 +66,7 @@
 
     public HttpHeadersImpl deepCopy() {
         HttpHeadersImpl h1 = new HttpHeadersImpl();
-        HashMap<String,List<String>> headers1 = h1.headers;
+        TreeMap<String,List<String>> headers1 = h1.headers;
         Set<String> keys = headers.keySet();
         for (String key : keys) {
             List<String> vals = headers.get(key);
@@ -98,22 +76,13 @@
         return h1;
     }
 
-    private List<String> getOrCreate(String name) {
-        List<String> l = headers.get(name);
-        if (l == null) {
-            l = new LinkedList<>();
-            headers.put(name, l);
-        }
-        return l;
-    }
-
     void addHeader(String name, String value) {
-        List<String> l = getOrCreate(name);
-        l.add(value);
+        headers.computeIfAbsent(name, k -> new LinkedList<>())
+               .add(value);
     }
 
     void setHeader(String name, String value) {
-        List<String> l = getOrCreate(name);
+        List<String> l = headers.computeIfAbsent(name, k -> new LinkedList<>());
         l.clear();
         l.add(value);
     }
@@ -122,7 +91,7 @@
     public Optional<Long> firstValueAsLong(String name) {
         List<String> l = headers.get(name);
         if (l == null) {
-            return Optional.ofNullable(null);
+            return Optional.empty();
         } else {
             String v = l.get(0);
             Long lv = Long.parseLong(v);
@@ -133,4 +102,4 @@
     void clear() {
         headers.clear();
     }
-}
+}
\ No newline at end of file
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -39,10 +39,11 @@
     private HttpClient.Version version;
     private final HttpClientImpl client;
     private ProxySelector proxy;
-    private long timeval = 0;
+    private long timeval;
 
     public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) {
         this.client = client;
+        checkURI(uri);
         this.uri = uri;
         this.version = client.version();
         this.userHeaders = new HttpHeadersImpl();
@@ -58,10 +59,17 @@
     @Override
     public HttpRequestBuilderImpl uri(URI uri) {
         Objects.requireNonNull(uri);
+        checkURI(uri);
         this.uri = uri;
         return this;
     }
 
+    private static void checkURI(URI uri) {
+        String scheme = uri.getScheme().toLowerCase();
+        if (!scheme.equals("https") && !scheme.equals("http"))
+            throw new IllegalArgumentException("invalid URI scheme");
+    }
+
     @Override
     public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) {
         Objects.requireNonNull(follow);
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,16 +30,14 @@
 import java.net.http.HttpClient.Version;
 import java.net.http.HttpResponse.MultiProcessor;
 import java.util.concurrent.CompletableFuture;
-import java.net.SocketPermission;
 import java.security.AccessControlContext;
 import java.security.AccessController;
-import java.util.Set;
 import static java.net.http.HttpRedirectImpl.getRedirects;
 import java.util.Locale;
 
 class HttpRequestImpl extends HttpRequest {
 
-    private final HttpHeadersImpl userHeaders;
+    private final ImmutableHeaders userHeaders;
     private final HttpHeadersImpl systemHeaders;
     private final URI uri;
     private InetSocketAddress authority; // only used when URI not specified
@@ -56,6 +54,7 @@
     private boolean receiving;
     private AccessControlContext acc;
     private final long timeval;
+    private Stream.PushGroup<?> pushGroup;
 
     public HttpRequestImpl(HttpClientImpl client,
                            String method,
@@ -63,8 +62,8 @@
         this.client = client;
         this.method = method == null? "GET" : method;
         this.userHeaders = builder.headers() == null ?
-                new HttpHeadersImpl() : builder.headers();
-        dropDisallowedHeaders();
+                new ImmutableHeaders() :
+                new ImmutableHeaders(builder.headers(), Utils.ALLOWED_HEADERS);
         this.followRedirects = getRedirects(builder.followRedirects() == null ?
                 client.followRedirects() : builder.followRedirects());
         this.systemHeaders = new HttpHeadersImpl();
@@ -90,15 +89,13 @@
                            HttpRequestImpl other) {
         this.client = client;
         this.method = method == null? "GET" : method;
-        this.userHeaders = other.userHeaders == null ?
-                new HttpHeadersImpl() : other.userHeaders;
-        dropDisallowedHeaders();
+        this.userHeaders = other.userHeaders;
         this.followRedirects = getRedirects(other.followRedirects() == null ?
                 client.followRedirects() : other.followRedirects());
         this.systemHeaders = other.systemHeaders;
         this.uri = uri;
         this.expectContinue = other.expectContinue;
-        this.secure = other.secure;
+        this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
         this.requestProcessor = other.requestProcessor;
         this.proxy = other.proxy;
         this.version = other.version;
@@ -115,7 +112,7 @@
         this.method = method;
         this.followRedirects = getRedirects(client.followRedirects());
         this.systemHeaders = new HttpHeadersImpl();
-        this.userHeaders = new HttpHeadersImpl();
+        this.userHeaders = new ImmutableHeaders();
         this.uri = null;
         this.proxy = null;
         this.requestProcessor = HttpRequest.noBody();
@@ -132,16 +129,52 @@
         return client;
     }
 
+    /**
+     * Creates a HttpRequestImpl from the given set of Headers and the associated
+     * "parent" request. Fields not taken from the headers are taken from the
+     * parent.
+     */
+    static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
+            HttpHeadersImpl headers) throws IOException {
+
+        return new HttpRequestImpl(parent, headers);
+    }
+
+    // only used for push requests
+    private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers) throws IOException {
+        this.method = headers.firstValue(":method")
+                .orElseThrow(() -> new IOException("No method in Push Promise"));
+        String path = headers.firstValue(":path")
+                .orElseThrow(() -> new IOException("No path in Push Promise"));
+        String scheme = headers.firstValue(":scheme")
+                .orElseThrow(() -> new IOException("No scheme in Push Promise"));
+        String authority = headers.firstValue(":authority")
+                .orElseThrow(() -> new IOException("No authority in Push Promise"));
+        StringBuilder sb = new StringBuilder();
+        sb.append(scheme).append("://").append(authority).append(path);
+        this.uri = URI.create(sb.toString());
+
+        this.client = parent.client;
+        this.userHeaders = new ImmutableHeaders(headers, Utils.ALLOWED_HEADERS);
+        this.followRedirects = parent.followRedirects;
+        this.systemHeaders = parent.systemHeaders;
+        this.expectContinue = parent.expectContinue;
+        this.secure = parent.secure;
+        this.requestProcessor = parent.requestProcessor;
+        this.proxy = parent.proxy;
+        this.version = parent.version;
+        this.acc = parent.acc;
+        this.exchange = parent.exchange;
+        this.timeval = parent.timeval;
+    }
 
     @Override
     public String toString() {
-        return (uri == null ? "" : uri.toString()) + "/" + method + "("
-                + hashCode() + ")";
+        return (uri == null ? "" : uri.toString()) + " " + method;
     }
 
     @Override
     public HttpHeaders headers() {
-        userHeaders.makeUnmodifiable();
         return userHeaders;
     }
 
@@ -154,21 +187,6 @@
         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
     }
 
-    private static final Set<String>  DISALLOWED_HEADERS_SET = Set.of(
-        "authorization", "connection", "cookie", "content-length",
-        "date", "expect", "from", "host", "origin", "proxy-authorization",
-        "referer", "user-agent", "upgrade", "via", "warning");
-
-
-    // we silently drop headers that are disallowed
-    private void dropDisallowedHeaders() {
-        Set<String> hdrnames = userHeaders.directMap().keySet();
-
-        hdrnames.removeIf((s) ->
-              DISALLOWED_HEADERS_SET.contains(s.toLowerCase())
-        );
-    }
-
     private synchronized void receiving() {
         if (receiving) {
             throw new IllegalStateException("already receiving response");
@@ -176,6 +194,10 @@
         receiving = true;
     }
 
+    synchronized Stream.PushGroup<?> pushGroup() {
+        return pushGroup;
+    }
+
     /*
      * Response filters may result in a new HttpRequestImpl being created
      * (but still associated with the same API HttpRequest) and the process
@@ -200,10 +222,25 @@
             .thenApply((r) -> (HttpResponse)r);
     }
 
-    public <U> CompletableFuture<U>
-    sendAsyncMulti(HttpResponse.MultiProcessor<U> rspproc) {
-        // To change body of generated methods, choose Tools | Templates.
-        throw new UnsupportedOperationException("Not supported yet.");
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public synchronized <U> CompletableFuture<U>
+    multiResponseAsync(MultiProcessor<U> rspproc) {
+        if (System.getSecurityManager() != null) {
+            acc = AccessController.getContext();
+        }
+        this.pushGroup = new Stream.PushGroup<>(rspproc, this);
+        CompletableFuture<HttpResponse> cf = pushGroup.mainResponse();
+        responseAsync()
+            .whenComplete((HttpResponse r, Throwable t) -> {
+                if (r != null)
+                    cf.complete(r);
+                else
+                    cf.completeExceptionally(t);
+                pushGroup.pushError(t);
+            });
+        return (CompletableFuture<U>)pushGroup.groupResult();
     }
 
     @Override
@@ -255,7 +292,7 @@
     @Override
     public URI uri() { return uri; }
 
-    HttpHeadersImpl getUserHeaders() { return userHeaders; }
+    HttpHeaders getUserHeaders() { return userHeaders; }
 
     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
 
@@ -275,11 +312,4 @@
     }
 
     long timeval() { return timeval; }
-
-    @Override
-    public <U> CompletableFuture<U>
-    multiResponseAsync(MultiProcessor<U> rspproc) {
-        //To change body of generated methods, choose Tools | Templates.
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
 }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java	Wed Jul 05 21:39:33 2017 +0200
@@ -200,8 +200,12 @@
                 if (n == -1) {
                     throw new IOException("Bad Content-Disposition type");
                 }
-                String disposition = dispoHeader.substring(n + 9,
-                                                           dispoHeader.lastIndexOf(';'));
+                int lastsemi = dispoHeader.lastIndexOf(';');
+                String disposition;
+                if (lastsemi < n)
+                    disposition = dispoHeader.substring(n + 9);
+                else
+                    disposition = dispoHeader.substring(n + 9, lastsemi);
                 file = Paths.get(directory.toString(), disposition);
                 fc = FileChannel.open(file, openOptions);
                 return null;
@@ -727,11 +731,14 @@
             }
 
             private CompletableFuture<Path> getBody(HttpRequest req,
-                                                    CompletableFuture<HttpResponse> cf) {
+                                                    CompletableFuture<? extends HttpResponse> cf) {
                 URI u = req.uri();
                 String path = u.getPath();
+                if (path.startsWith("/"))
+                    path = path.substring(1);
+                final String fpath = path;
                 return cf.thenCompose((HttpResponse resp) -> {
-                    return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path)));
+                    return resp.bodyAsync(HttpResponse.asFile(destination.resolve(fpath)));
                 });
             }
 
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -26,6 +26,7 @@
 package java.net.http;
 
 import java.io.IOException;
+import java.io.UncheckedIOException;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.security.AccessControlContext;
@@ -42,17 +43,18 @@
     int responseCode;
     Exchange exchange;
     HttpRequestImpl request;
-    HttpHeaders1 headers;
-    HttpHeaders1 trailers;
+    HttpHeaders headers;
+    HttpHeaders trailers;
     SSLParameters sslParameters;
     URI uri;
     HttpClient.Version version;
     AccessControlContext acc;
     RawChannel rawchan;
     HttpConnection connection;
+    final Stream stream;
 
-    public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers,
-            HttpHeaders1 trailers, SSLParameters sslParameters,
+    public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders headers,
+            HttpHeaders trailers, SSLParameters sslParameters,
             HttpClient.Version version, HttpConnection connection) {
         this.responseCode = responseCode;
         this.exchange = exch;
@@ -63,6 +65,23 @@
         this.uri = request.uri();
         this.version = version;
         this.connection = connection;
+        this.stream = null;
+    }
+
+    // A response to a PUSH_PROMISE
+    public HttpResponseImpl(int responseCode, HttpRequestImpl pushRequest,
+            ImmutableHeaders headers,
+            Stream stream, SSLParameters sslParameters) {
+        this.responseCode = responseCode;
+        this.exchange = null;
+        this.request = pushRequest;
+        this.headers = headers;
+        this.trailers = null;
+        this.sslParameters = sslParameters;
+        this.uri = request.uri(); // TODO: take from headers
+        this.version = HttpClient.Version.HTTP_2;
+        this.connection = null;
+        this.stream = stream;
     }
 
     @Override
@@ -77,26 +96,35 @@
 
     @Override
     public HttpHeaders headers() {
-        headers.makeUnmodifiable();
         return headers;
     }
 
     @Override
     public HttpHeaders trailers() {
-        trailers.makeUnmodifiable();
         return trailers;
     }
 
 
     @Override
     public <T> T body(java.net.http.HttpResponse.BodyProcessor<T> processor) {
-        return exchange.responseBody(processor);
+        try {
+            if (exchange != null) {
+                return exchange.responseBody(processor);
+            } else {
+                return stream.responseBody(processor);
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
     }
 
     @Override
     public <T> CompletableFuture<T> bodyAsync(java.net.http.HttpResponse.BodyProcessor<T> processor) {
         acc = AccessController.getContext();
-        return exchange.responseBodyAsync(processor);
+        if (exchange != null)
+            return exchange.responseBodyAsync(processor);
+        else
+            return stream.responseBodyAsync(processor);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.TreeMap;
+import java.util.function.Predicate;
+
+/**
+ * Immutable HttpHeaders constructed from mutable HttpHeadersImpl.
+ */
+
+class ImmutableHeaders implements HttpHeaders {
+
+    private final Map<String,List<String>> map;
+
+    @SuppressWarnings("unchecked")
+    ImmutableHeaders() {
+        map = (Map<String,List<String>>)Collections.EMPTY_MAP;
+    }
+    // TODO: fix lower case issue. Must be lc for http/2 compares ignoreCase for http/1
+    ImmutableHeaders(HttpHeadersImpl h, Predicate<String> keyAllowed) {
+        Map<String,List<String>> src = h.directMap();
+        Map<String,List<String>> m = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+
+        src.forEach((key, value) -> {
+            if (keyAllowed.test(key))
+                m.put(key, Collections.unmodifiableList(value));
+        });
+        map = Collections.unmodifiableMap(m);
+    }
+
+    @Override
+    public Optional<String> firstValue(String name) {
+        List<String> l = map.get(name);
+        String v = l == null ? null : l.get(0);
+        return Optional.ofNullable(v);
+    }
+
+    @Override
+    public Optional<Long> firstValueAsLong(String name) {
+        return firstValue(name).map((v -> Long.parseLong(v)));
+    }
+
+    @Override
+    public List<String> allValues(String name) {
+        return map.get(name);
+    }
+
+    @Override
+    public Map<String, List<String>> map() {
+        return map;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java	Wed Jul 05 21:39:33 2017 +0200
@@ -26,7 +26,9 @@
 import java.util.Locale;
 
 /**
- * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content
+ * -Djava.net.HttpClient.log=
+ *          errors,requests,headers,
+ *          frames[:type:type2:..],content,ssl,trace
  *
  * Any of errors, requests, headers or content are optional.
  *
@@ -47,6 +49,7 @@
     public static final int CONTENT = 0x8;
     public static final int FRAMES = 0x10;
     public static final int SSL = 0x20;
+    public static final int TRACE = 0x40;
     static int logging;
 
     // Frame types: "control", "data", "window", "all"
@@ -81,8 +84,11 @@
                     case "ssl":
                         logging |= SSL;
                         break;
+                    case "trace":
+                        logging |= TRACE;
+                        break;
                     case "all":
-                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS;
+                        logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS|TRACE;
                         break;
                 }
                 if (val.startsWith("frames")) {
@@ -130,6 +136,10 @@
         return (logging & HEADERS) != 0;
     }
 
+    static boolean trace() {
+        return (logging & TRACE) != 0;
+    }
+
     static boolean ssl() {
         return (logging & SSL) != 0;
     }
@@ -138,9 +148,9 @@
         return (logging & FRAMES) != 0;
     }
 
-    static void logError(String s) {
+    static void logError(String s, Object... s1) {
         if (errors())
-            logger.log(Level.INFO, "ERROR: " + s);
+            logger.log(Level.INFO, "ERROR: " + s, s1);
     }
 
     static void logError(Throwable t) {
@@ -150,24 +160,50 @@
         }
     }
 
-    static void logSSL(String s) {
+    static void logSSL(String s, Object... s1) {
         if (ssl())
-            logger.log(Level.INFO, "SSL: " + s);
+            logger.log(Level.INFO, "SSL: " + s, s1);
+    }
+
+    static void logTrace(String s, Object... s1) {
+        if (trace()) {
+            String format = "TRACE: " + s;
+            logger.log(Level.INFO, format, s1);
+        }
+    }
+
+    static void logRequest(String s, Object... s1) {
+        if (requests())
+            logger.log(Level.INFO, "REQUEST: " + s, s1);
+    }
+
+    static void logResponse(String s, Object... s1) {
+        if (requests())
+            logger.log(Level.INFO, "RESPONSE: " + s, s1);
     }
 
-    static void logRequest(String s) {
-        if (requests())
-            logger.log(Level.INFO, "REQUEST: " + s);
+    static void logHeaders(String s, Object... s1) {
+        if (headers())
+            logger.log(Level.INFO, "HEADERS: " + s, s1);
+    }
+// START HTTP2
+    static boolean loggingFrame(Class<? extends Http2Frame> clazz) {
+        if (frametypes == ALL) {
+            return true;
+        }
+        if (clazz == DataFrame.class) {
+            return (frametypes & DATA) != 0;
+        } else if (clazz == WindowUpdateFrame.class) {
+            return (frametypes & WINDOW_UPDATES) != 0;
+        } else {
+            return (frametypes & CONTROL) != 0;
+        }
     }
 
-    static void logResponse(String s) {
-        if (requests())
-            logger.log(Level.INFO, "RESPONSE: " + s);
-    }
-
-    static void logHeaders(String s) {
-        if (headers())
-            logger.log(Level.INFO, "HEADERS: " + s);
+    static void logFrames(Http2Frame f, String direction) {
+        if (frames() && loggingFrame(f.getClass())) {
+            logger.log(Level.INFO, "FRAME: " + direction + ": " + f.toString());
+        }
     }
 
     // not instantiable
--- a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java	Wed Jul 05 21:39:33 2017 +0200
@@ -54,7 +54,7 @@
 
     final static int DEFAULT_MAX_ATTEMPTS = 5;
     final static int max_attempts = Utils.getIntegerNetProperty(
-            "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
+            "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS
     );
 
     private final List<HeaderFilter> filters;
@@ -187,8 +187,7 @@
     public CompletableFuture<HttpResponseImpl> responseAsync(Void v) {
         CompletableFuture<HttpResponseImpl> cf;
         if (++attempts > max_attempts) {
-            cf = new CompletableFuture<>();
-            cf.completeExceptionally(new IOException("Too many retries"));
+            cf = CompletableFuture.failedFuture(new IOException("Too many retries"));
         } else {
             if (currentreq.timeval() != 0) {
                 // set timer
@@ -241,7 +240,6 @@
      * completed exceptionally.
      */
     private CompletableFuture<HttpResponseImpl> getExceptionalCF(Throwable t) {
-        CompletableFuture<HttpResponseImpl> error = new CompletableFuture<>();
         if ((t instanceof CompletionException) || (t instanceof ExecutionException)) {
             if (t.getCause() != null) {
                 t = t.getCause();
@@ -250,8 +248,7 @@
         if (cancelled && t instanceof IOException) {
             t = new HttpTimeoutException("request timed out");
         }
-        error.completeExceptionally(t);
-        return error;
+        return CompletableFuture.failedFuture(t);
     }
 
     <T> T responseBody(HttpResponse.BodyProcessor<T> processor) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+
+/**
+ * Contains all parameters for outgoing headers. Is converted to
+ * HeadersFrame and ContinuationFrames by Http2Connection.
+ */
+class OutgoingHeaders extends Http2Frame {
+
+    int streamDependency;
+    int weight;
+    boolean exclusive;
+    Stream stream;
+
+    public static final int PRIORITY = 0x20;
+
+    HttpHeaders user, system;
+
+    OutgoingHeaders(HttpHeaders hdrs1, HttpHeaders hdrs2, Stream stream) {
+        this.user = hdrs2;
+        this.system = hdrs1;
+        this.stream = stream;
+    }
+
+    public void setPriority(int streamDependency, boolean exclusive, int weight) {
+        this.streamDependency = streamDependency;
+        this.exclusive = exclusive;
+        this.weight = weight;
+        this.flags |= PRIORITY;
+    }
+
+    public int getStreamDependency() {
+        return streamDependency;
+    }
+
+    public int getWeight() {
+        return weight;
+    }
+
+    public boolean getExclusive() {
+        return exclusive;
+    }
+
+    public Stream getStream() {
+        return stream;
+    }
+
+    public HttpHeaders getUserHeaders() {
+        return user;
+    }
+
+    public HttpHeaders getSystemHeaders() {
+        return system;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        throw new UnsupportedOperationException("Not supported.");
+    }
+
+    @Override
+    void computeLength() {
+        //To change body of generated methods, choose Tools | Templates.
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java	Wed Jul 05 21:39:33 2017 +0200
@@ -43,4 +43,9 @@
     static <T, U> Pair<T, U> pair(T first, U second) {
         return new Pair<>(first, second);
     }
+
+    @Override
+    public String toString() {
+        return "(" + first + ", " + second + ")";
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PingFrame extends Http2Frame {
+
+    PingFrame() {
+        type = TYPE;
+    }
+
+    byte[] data;
+
+    public final static int TYPE = 0x6;
+
+    // Flags
+    public static final int ACK = 0x1;
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case ACK:
+            return "ACK";
+        }
+        return super.flagAsString(flag);
+    }
+
+    public void setData(byte[] data) {
+        if (data.length != 8) {
+            throw new IllegalArgumentException("Ping data not 8 bytes");
+        }
+        this.data = data;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if (length != 8) {
+            throw new IOException("Invalid Ping frame");
+        }
+        data = bc.getBytes(8);
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        if (data == null) {
+            data = new byte[] {0, 0, 0, 0, 0 ,0, 0, 0};
+        }
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(8);
+        buf.put(data);
+    }
+
+    @Override
+    void computeLength() {
+        length = 8;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -31,20 +31,43 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
 import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
 
 /**
- * Plain raw TCP connection direct to destination
+ * Plain raw TCP connection direct to destination. 2 modes
+ * 1) Blocking used by http/1. In this case the connect is actually non
+ *    blocking but the request is sent blocking. The first byte of a response
+ *    is received non-blocking and the remainder of the response is received
+ *    blocking
+ * 2) Non-blocking. In this case (for http/2) the connection is actually opened
+ *    blocking but all reads and writes are done non-blocking under the
+ *    control of a Http2Connection object.
  */
-class PlainHttpConnection extends HttpConnection {
+class PlainHttpConnection extends HttpConnection implements AsyncConnection {
 
     protected SocketChannel chan;
     private volatile boolean connected;
     private boolean closed;
+    Consumer<ByteBuffer> asyncReceiver;
+    Consumer<Throwable> errorReceiver;
+    Queue<ByteBuffer> asyncOutputQ;
+    final Object reading = new Object();
+    final Object writing = new Object();
 
-    class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking {
+    @Override
+    public void startReading() {
+        try {
+            client.registerEvent(new ReadEvent());
+        } catch (IOException e) {
+            shutdown();
+        }
+    }
+
+    class ConnectEvent extends AsyncEvent {
         CompletableFuture<Void> cf;
 
         ConnectEvent(CompletableFuture<Void> cf) {
+            super(AsyncEvent.BLOCKING);
             this.cf = cf;
         }
 
@@ -112,14 +135,62 @@
 
     @Override
     long write(ByteBuffer[] buffers, int start, int number) throws IOException {
-        //debugPrint("Send", buffers, start, number);
-        return chan.write(buffers, start, number);
+        if (mode != Mode.ASYNC)
+            return chan.write(buffers, start, number);
+        // async
+        synchronized(writing) {
+            int qlen = asyncOutputQ.size();
+            ByteBuffer[] bufs = Utils.reduce(buffers, start, number);
+            long n = Utils.remaining(bufs);
+            asyncOutputQ.putAll(bufs);
+            if (qlen == 0)
+                asyncOutput();
+            return n;
+        }
+    }
+
+    ByteBuffer asyncBuffer = null;
+
+    void asyncOutput() {
+        synchronized (writing) {
+            try {
+                while (true) {
+                    if (asyncBuffer == null) {
+                        asyncBuffer = asyncOutputQ.poll();
+                        if (asyncBuffer == null) {
+                            return;
+                        }
+                    }
+                    if (!asyncBuffer.hasRemaining()) {
+                        asyncBuffer = null;
+                        continue;
+                    }
+                    int n = chan.write(asyncBuffer);
+                    //System.err.printf("Written %d bytes to chan\n", n);
+                    if (n == 0) {
+                        client.registerEvent(new WriteEvent());
+                        return;
+                    }
+                }
+            } catch (IOException e) {
+                shutdown();
+            }
+        }
     }
 
     @Override
     long write(ByteBuffer buffer) throws IOException {
-        //debugPrint("Send", buffer);
-        return chan.write(buffer);
+        if (mode != Mode.ASYNC)
+            return chan.write(buffer);
+        // async
+        synchronized(writing) {
+            int qlen = asyncOutputQ.size();
+            long n = buffer.remaining();
+            asyncOutputQ.put(buffer);
+            if (qlen == 0)
+                asyncOutput();
+            return n;
+        }
     }
 
     @Override
@@ -131,7 +202,7 @@
      * Close this connection
      */
     @Override
-    synchronized void close() {
+    public synchronized void close() {
         if (closed)
             return;
         closed = true;
@@ -155,14 +226,49 @@
         return buf;
     }
 
+    void shutdown() {
+        close();
+        errorReceiver.accept(new IOException("Connection aborted"));
+    }
+
+    void asyncRead() {
+        synchronized (reading) {
+            try {
+                while (true) {
+                    ByteBuffer buf = getBuffer();
+                    int n = chan.read(buf);
+                    //System.err.printf("Read %d bytes from chan\n", n);
+                    if (n == -1) {
+                        throw new IOException();
+                    }
+                    if (n == 0) {
+                        returnBuffer(buf);
+                        return;
+                    }
+                    buf.flip();
+                    asyncReceiver.accept(buf);
+                }
+            } catch (IOException e) {
+                shutdown();
+            }
+        }
+    }
+
     @Override
     protected int readImpl(ByteBuffer buf) throws IOException {
         int mark = buf.position();
-        int n = chan.read(buf);
+        int n;
+        // FIXME: this hack works in conjunction with the corresponding change
+        // in java.net.http.RawChannel.registerEvent
+        if ((n = buffer.remaining()) != 0) {
+            buf.put(buffer);
+        } else {
+            n = chan.read(buf);
+        }
         if (n == -1) {
             return -1;
         }
-        Utils.flipToMark(buffer, mark);
+        Utils.flipToMark(buf, mark);
         String s = "Receive (" + n + " bytes) ";
         //debugPrint(s, buf);
         return n;
@@ -178,10 +284,67 @@
         return connected;
     }
 
-    class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking {
+    // used for all output in HTTP/2
+    class WriteEvent extends AsyncEvent {
+        WriteEvent() {
+            super(0);
+        }
+
+        @Override
+        public SelectableChannel channel() {
+            return chan;
+        }
+
+        @Override
+        public int interestOps() {
+            return SelectionKey.OP_WRITE;
+        }
+
+        @Override
+        public void handle() {
+            asyncOutput();
+        }
+
+        @Override
+        public void abort() {
+            shutdown();
+        }
+    }
+
+    // used for all input in HTTP/2
+    class ReadEvent extends AsyncEvent {
+        ReadEvent() {
+            super(AsyncEvent.REPEATING); // && !BLOCKING
+        }
+
+        @Override
+        public SelectableChannel channel() {
+            return chan;
+        }
+
+        @Override
+        public int interestOps() {
+            return SelectionKey.OP_READ;
+        }
+
+        @Override
+        public void handle() {
+            asyncRead();
+        }
+
+        @Override
+        public void abort() {
+            shutdown();
+        }
+
+    }
+
+    // used in blocking channels only
+    class ReceiveResponseEvent extends AsyncEvent {
         CompletableFuture<Void> cf;
 
         ReceiveResponseEvent(CompletableFuture<Void> cf) {
+            super(AsyncEvent.BLOCKING);
             this.cf = cf;
         }
         @Override
@@ -216,6 +379,15 @@
     }
 
     @Override
+    public synchronized void setAsyncCallbacks(Consumer<ByteBuffer> asyncReceiver,
+            Consumer<Throwable> errorReceiver) {
+        this.asyncReceiver = asyncReceiver;
+        this.errorReceiver = errorReceiver;
+        asyncOutputQ = new Queue<>();
+        asyncOutputQ.registerPutCallback(this::asyncOutput);
+    }
+
+    @Override
     CompletableFuture<Void> whenReceivingResponse() {
         CompletableFuture<Void> cf = new CompletableFuture<>();
         try {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -111,7 +111,7 @@
     }
 
     @Override
-    void close() {
+    public void close() {
         delegate.close();
         connected = false;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,82 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PriorityFrame extends Http2Frame {
+
+    int streamDependency;
+    int weight;
+    boolean exclusive;
+
+    public final static int TYPE = 0x2;
+
+    PriorityFrame() {
+        type = TYPE;
+    }
+
+    public PriorityFrame(int streamDependency, boolean exclusive, int weight) {
+        this.streamDependency = streamDependency;
+        this.exclusive = exclusive;
+        this.weight = weight;
+        this.type = TYPE;
+    }
+
+    int streamDependency() {
+        return streamDependency;
+    }
+
+    int weight() {
+        return weight;
+    }
+
+    boolean exclusive() {
+        return exclusive;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        int x = bc.getInt();
+        exclusive = (x & 0x80000000) != 0;
+        streamDependency = x & 0x7fffffff;
+        weight = bc.getByte();
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(5);
+        int x = exclusive ? (1 << 31) + streamDependency : streamDependency;
+        buf.putInt(x);
+        buf.put((byte)weight);
+    }
+
+    @Override
+    void computeLength() {
+        length = 5;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class PushPromiseFrame extends HeaderFrame {
+
+    int padLength;
+    int promisedStream;
+
+    PushPromiseFrame() {
+        type = TYPE;
+    }
+
+    public static final int TYPE = 0x5;
+
+    // Flags
+    public static final int END_HEADERS = 0x4;
+    public static final int PADDED = 0x8;
+
+    @Override
+    public String toString() {
+        return super.toString() + " promisedStreamid: " + promisedStream
+                + " headerLength: " + headerLength;
+    }
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case PADDED:
+            return "PADDED";
+        case END_HEADERS:
+            return "END_HEADERS";
+        }
+        return super.flagAsString(flag);
+    }
+
+    public void setPadLength(int padLength) {
+        this.padLength = padLength;
+        flags |= PADDED;
+    }
+
+    public void setPromisedStream(int stream) {
+        this.promisedStream = stream;
+    }
+
+    public int getPromisedStream() {
+        return promisedStream;
+    }
+
+    /**
+     */
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if ((flags & PADDED) != 0) {
+            padLength = bc.getByte();
+            headerLength = length - (padLength + 5);
+        } else
+            headerLength = length - 4;
+
+        promisedStream = bc.getInt() & 0x7fffffff;
+        headerBlocks = bc.getBuffers(headerLength);
+    }
+
+    @Override
+    void computeLength() {
+        int len = 0;
+        if ((flags & PADDED) != 0) {
+            len += (1 + padLength);
+        }
+        len += (4 + headerLength);
+        this.length = len;
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(length);
+        if ((flags & PADDED) != 0) {
+            buf.put((byte)padLength);
+        }
+        buf.putInt(promisedStream);
+        for (int i=0; i<headerBlocks.length; i++) {
+            bg.addByteBuffer(headerBlocks[i]);
+        }
+        if ((flags & PADDED) != 0) {
+            bg.addPadding(padLength);
+        }
+    }
+
+    @Override
+    public boolean endHeaders() {
+        return getFlag(END_HEADERS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Queue.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,143 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.LinkedList;
+
+// Each stream has one of these for input. Each Http2Connection has one
+// for output. Can be used blocking or asynchronously.
+
+class Queue<T> implements Closeable {
+
+    private final LinkedList<T> q = new LinkedList<>();
+    private volatile boolean closed = false;
+    private Runnable callback;
+    private boolean forceCallback;
+    private int waiters; // true if someone waiting
+
+    synchronized void putAll(T[] objs) throws IOException {
+        if (closed) {
+            throw new IOException("stream closed");
+        }
+        boolean wasEmpty = q.isEmpty();
+
+        for (T obj : objs) {
+            q.add(obj);
+        }
+
+        if (waiters > 0)
+            notifyAll();
+
+        if (wasEmpty || forceCallback) {
+            forceCallback = false;
+            if (callback != null) {
+                callback.run();
+            }
+        }
+    }
+
+    synchronized int size() {
+        return q.size();
+    }
+
+    synchronized void put(T obj) throws IOException {
+        if (closed) {
+            throw new IOException("stream closed");
+        }
+
+        q.add(obj);
+        if (waiters > 0)
+            notifyAll();
+
+        if (q.size() == 1 || forceCallback) {
+            forceCallback = false;
+            if (callback != null) {
+                callback.run();
+            }
+        }
+    }
+
+    /**
+     * callback is invoked any time put is called where
+     * the Queue was empty.
+     */
+    synchronized void registerPutCallback(Runnable callback) {
+        this.callback = callback;
+        if (callback != null && q.size() > 0)
+            callback.run();
+    }
+
+    @Override
+    public synchronized void close() {
+        closed = true;
+        notifyAll();
+    }
+
+    synchronized T take() throws IOException {
+        if (closed) {
+            throw new IOException("stream closed");
+        }
+        try {
+            while (q.size() == 0) {
+                waiters++;
+                wait();
+                waiters--;
+            }
+            return q.removeFirst();
+        } catch (InterruptedException ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    public synchronized T poll() throws IOException {
+        if (closed)
+            throw new IOException("stream closed");
+
+        if (q.isEmpty())
+            return null;
+        T res = q.removeFirst();
+        return res;
+    }
+
+    public synchronized T[] pollAll(T[] type) throws IOException {
+        T[] ret = q.toArray(type);
+        q.clear();
+        return ret;
+    }
+
+    public synchronized void pushback(T v) {
+        forceCallback = true;
+        q.addFirst(v);
+    }
+
+    public synchronized void pushbackAll(T[] v) {
+        forceCallback = true;
+        for (int i=v.length-1; i>=0; i--) {
+            q.addFirst(v[i]);
+        }
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,18 +28,18 @@
 import java.nio.channels.ByteChannel;
 import java.nio.channels.GatheringByteChannel;
 import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
 
-/**
- * Used to implement WebSocket. Each RawChannel corresponds to
- * a TCP connection (SocketChannel) but is connected to a Selector
- * and an ExecutorService for invoking the send and receive callbacks
- * Also includes SSL processing.
- */
-class RawChannel implements ByteChannel, GatheringByteChannel {
+//
+// Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
+// (SocketChannel) but is connected to a Selector and an ExecutorService for
+// invoking the send and receive callbacks. Also includes SSL processing.
+//
+final class RawChannel implements ByteChannel, GatheringByteChannel {
 
     private final HttpClientImpl client;
     private final HttpConnection connection;
-    private boolean closed;
+    private volatile boolean closed;
 
     private interface RawEvent {
 
@@ -50,8 +50,6 @@
         void handle();
     }
 
-    interface BlockingEvent extends RawEvent { }
-
     interface NonBlockingEvent extends RawEvent { }
 
     RawChannel(HttpClientImpl client, HttpConnection connection) {
@@ -64,39 +62,40 @@
         private final RawEvent re;
 
         RawAsyncEvent(RawEvent re) {
+            super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING
             this.re = re;
         }
 
+        RawAsyncEvent(RawEvent re, int flags) {
+            super(flags);
+            this.re = re;
+        }
+
+        @Override
         public SelectableChannel channel() {
             return connection.channel();
         }
 
         // must return the selector interest op flags OR'd
+        @Override
         public int interestOps() {
             return re.interestOps();
         }
 
         // called when event occurs
+        @Override
         public void handle() {
             re.handle();
         }
 
-        public void abort() {}
+        @Override
+        public void abort() { }
     }
 
-    private class BlockingRawAsyncEvent extends RawAsyncEvent
-            implements AsyncEvent.Blocking {
-
-        BlockingRawAsyncEvent(RawEvent re) {
-            super(re);
-        }
-    }
-
-    private class NonBlockingRawAsyncEvent extends RawAsyncEvent
-            implements AsyncEvent.NonBlocking {
+    private class NonBlockingRawAsyncEvent extends RawAsyncEvent {
 
         NonBlockingRawAsyncEvent(RawEvent re) {
-            super(re);
+            super(re, 0); // !BLOCKING & !REPEATING
         }
     }
 
@@ -105,17 +104,24 @@
      * (i.e. register new event for each callback)
      */
     public void registerEvent(RawEvent event) throws IOException {
-        if (event instanceof BlockingEvent) {
-            client.registerEvent(new BlockingRawAsyncEvent(event));
-        } else if (event instanceof NonBlockingEvent) {
+        if (!(event instanceof NonBlockingEvent)) {
+            throw new InternalError();
+        }
+        if ((event.interestOps() & SelectionKey.OP_READ) != 0
+                && connection.buffer.hasRemaining()) {
+            // FIXME: a hack to deal with leftovers from previous reads into an
+            // internal buffer (works in conjunction with change in
+            // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
+            connection.channel().configureBlocking(false);
+            event.handle();
+        } else {
             client.registerEvent(new NonBlockingRawAsyncEvent(event));
-        } else {
-            throw new InternalError();
         }
     }
 
     @Override
     public int read(ByteBuffer dst) throws IOException {
+        assert !connection.channel().isBlocking();
         return connection.read(dst);
     }
 
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -33,17 +33,19 @@
     HttpRequestImpl requestImpl;
     HttpRequest request;
     HttpClientImpl client;
+    HttpClient.Redirect policy;
     String method;
     final static int DEFAULT_MAX_REDIRECTS = 5;
     URI uri;
 
     final static int max_redirects = Utils.getIntegerNetProperty(
-            "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS
+            "java.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS
     );
 
     @Override
     public void request(HttpRequestImpl r) throws IOException {
         this.request = r;
+        this.policy = request.followRedirects();
         this.client = r.getClient();
         this.method = r.method();
         this.requestImpl = r;
@@ -61,7 +63,7 @@
      */
     private HttpRequestImpl handleResponse(HttpResponseImpl r) {
         int rcode = r.statusCode();
-        if (rcode == 200) {
+        if (rcode == 200 || policy == HttpClient.Redirect.NEVER) {
             return null;
         }
         if (rcode >= 300 && rcode <= 399) {
@@ -79,6 +81,7 @@
 
     private URI getRedirectedURI(HttpHeaders headers) {
         URI redirectedURI;
+        String ss = headers.firstValue("Location").orElse("Not present");
         redirectedURI = headers.firstValue("Location")
                 .map((s) -> URI.create(s))
                 .orElseThrow(() -> new UncheckedIOException(
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class ResetFrame extends ErrorFrame {
+
+    public final static int TYPE = 0x3;
+
+    // See ErrorFrame for error values
+
+    ResetFrame() {
+        type = TYPE;
+    }
+
+    public ResetFrame(int errorCode) {
+        this.errorCode = errorCode;
+        this.type = TYPE;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        errorCode = bc.getInt();
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(4);
+        buf.putInt(errorCode);
+    }
+
+    @Override
+    void computeLength() {
+        length = 4;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,7 +48,7 @@
  *
  * This class is not thread-safe
  */
-class ResponseHeaders implements HttpHeaders1 {
+class ResponseHeaders implements HttpHeaders {
 
     static final int DATA_SIZE = 16 * 1024;  // initial space for headers
     static final int NUM_HEADERS = 50; // initial expected max number of headers
@@ -368,10 +368,6 @@
         return Collections.unmodifiableList(l);
     }
 
-    @Override
-    public void makeUnmodifiable() {
-    }
-
     // Delegates map to HashMap but converts keys to lower case
 
     static class HeaderMap implements Map<String,List<String>> {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -121,13 +121,8 @@
     }
 
     @Override
-    void close() {
-        try {
-            //System.err.println ("Closing: " + this);
-            delegate.channel().close(); // TODO: proper close
-        } catch (IOException ex) {
-            Log.logError(ex.toString());
-        }
+    public void close() {
+        Utils.close(delegate.channel());
     }
 
     @Override
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java	Wed Jul 05 21:39:33 2017 +0200
@@ -29,13 +29,9 @@
 import java.util.Arrays;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLEngineResult.Status;
-import javax.net.ssl.SSLParameters;
-import javax.net.ssl.SSLSession;
+import javax.net.ssl.*;
 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
 
 /**
@@ -60,16 +56,18 @@
         engine.setUseClientMode(true);
         SSLParameters sslp = client.sslParameters().orElse(null);
         if (sslp == null) {
-            sslp = context.getDefaultSSLParameters();
+            sslp = context.getSupportedSSLParameters();
         }
         sslParameters = Utils.copySSLParameters(sslp);
         if (alpn != null) {
             sslParameters.setApplicationProtocols(alpn);
             Log.logSSL("Setting application protocols: " + Arrays.toString(alpn));
         } else {
-            Log.logSSL("Warning no application protocols proposed!");
+            Log.logSSL("No application protocols proposed");
         }
         engine.setSSLParameters(sslParameters);
+        engine.setEnabledCipherSuites(sslp.getCipherSuites());
+        engine.setEnabledProtocols(sslp.getProtocols());
         wrapper = new EngineWrapper(chan, engine);
         this.chan = chan;
         this.client = client;
@@ -268,7 +266,7 @@
                 do {
                     if (needData) {
                         do {
-                        x = chan.read (unwrap_src);
+                            x = chan.read (unwrap_src);
                         } while (x == 0);
                         if (x == -1) {
                             throw new IOException ("connection closed for reading");
@@ -440,6 +438,27 @@
         }
     }
 
+    static void printParams(SSLParameters p) {
+        System.out.println("SSLParameters:");
+        if (p == null) {
+            System.out.println("Null params");
+            return;
+        }
+        for (String cipher : p.getCipherSuites()) {
+                System.out.printf("cipher: %s\n", cipher);
+        }
+        for (String approto : p.getApplicationProtocols()) {
+                System.out.printf("application protocol: %s\n", approto);
+        }
+        for (String protocol : p.getProtocols()) {
+                System.out.printf("protocol: %s\n", protocol);
+        }
+        if (p.getServerNames() != null)
+        for (SNIServerName sname : p.getServerNames()) {
+                System.out.printf("server name: %s\n", sname.toString());
+        }
+    }
+
     String getSessionInfo() {
         StringBuilder sb = new StringBuilder();
         String application = engine.getApplicationProtocol();
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -130,12 +130,8 @@
     }
 
     @Override
-    void close() {
-        try {
-            //System.err.println ("Closing: " + this);
-            delegate.channel().close(); // TODO: proper close
-        } catch (IOException ex) {
-        }
+    public void close() {
+        Utils.close(delegate.channel());
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class SettingsFrame extends Http2Frame {
+
+    int[] parameters;
+
+    public static final int TYPE = 0x4;
+
+    // Flags
+    public static final int ACK = 0x1;
+
+    @Override
+    String flagAsString(int flag) {
+        switch (flag) {
+        case ACK:
+            return "ACK";
+        }
+        return super.flagAsString(flag);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString())
+          .append(" Settings: ");
+
+        for (int i = 0; i < MAX_PARAM; i++) {
+            if (parameters[i] != -1) {
+                sb.append(name(i))
+                  .append("=")
+                  .append(Integer.toString(parameters[i]))
+                  .append(' ');
+            }
+        }
+        return sb.toString();
+    }
+
+    // Parameters
+    public static final int HEADER_TABLE_SIZE = 0x1;
+    public static final int ENABLE_PUSH = 0x2;
+    public static final int MAX_CONCURRENT_STREAMS = 0x3;
+    public static final int INITIAL_WINDOW_SIZE = 0x4;
+    public static final int MAX_FRAME_SIZE = 0x5;
+    public static final int MAX_HEADER_LIST_SIZE = 0x6;
+
+    private String name(int i) {
+        switch (i+1) {
+        case HEADER_TABLE_SIZE:
+            return "HEADER_TABLE_SIZE";
+        case ENABLE_PUSH:
+            return "ENABLE_PUSH";
+        case MAX_CONCURRENT_STREAMS:
+            return "MAX_CONCURRENT_STREAMS";
+        case INITIAL_WINDOW_SIZE:
+            return "INITIAL_WINDOW_SIZE";
+        case MAX_FRAME_SIZE:
+            return "MAX_FRAME_SIZE";
+        case MAX_HEADER_LIST_SIZE:
+            return "MAX_HEADER_LIST_SIZE";
+        }
+        return "unknown parameter";
+    }
+    public static final int MAX_PARAM = 0x6;
+
+    public SettingsFrame() {
+        type = TYPE;
+        parameters = new int [MAX_PARAM];
+        for (int i=0; i < parameters.length; i++) {
+            parameters[i] = -1;
+        }
+    }
+
+    public int getParameter(int paramID) {
+        if (paramID > MAX_PARAM) {
+            throw new IllegalArgumentException("illegal parameter");
+        }
+        return parameters[paramID-1];
+    }
+
+    public SettingsFrame setParameter(int paramID, int value) {
+        if (paramID > MAX_PARAM) {
+            throw new IllegalArgumentException("illegal parameter");
+        }
+        parameters[paramID-1] = value;
+        return this;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if (length % 6 != 0) {
+            throw new IOException("Protocol error: invalid settings frame");
+        }
+        int n = length / 6;
+        for (int i=0; i<n; i++) {
+            int id = bc.getShort();
+            int val = bc.getInt();
+            if (id > 0 || id <= MAX_PARAM) {
+                // a known parameter. Ignore otherwise
+                parameters[id-1] = val;
+            }
+        }
+    }
+
+    @Override
+    void computeLength() {
+        length = 0;
+        for (int i : parameters) {
+            if (i != -1) {
+                length += 6;
+            }
+        }
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(length);
+        for (int i = 0; i < MAX_PARAM; i++) {
+            if (parameters[i] != -1) {
+                buf.putShort((short)(i+1));
+                buf.putInt(parameters[i]);
+            }
+        }
+    }
+
+    private static final int K = 1024;
+
+    public static SettingsFrame getDefaultSettings() {
+        SettingsFrame f = new SettingsFrame();
+        // TODO: check these values
+        f.setParameter(ENABLE_PUSH, 1);
+        f.setParameter(HEADER_TABLE_SIZE, 4 * K);
+        f.setParameter(MAX_CONCURRENT_STREAMS, 35);
+        f.setParameter(INITIAL_WINDOW_SIZE, 16 * K);
+        f.setParameter(MAX_FRAME_SIZE, 16 * K);
+        return f;
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * 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,78 +24,819 @@
 
 package java.net.http;
 
+import sun.net.httpclient.hpack.DecodingCallback;
+
 import java.io.IOException;
-import java.io.UncheckedIOException;
 import java.net.URI;
 import java.nio.ByteBuffer;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
+import java.util.function.BiFunction;
 import java.util.function.LongConsumer;
 
 /**
- * Http/2 Stream
+ * Http/2 Stream handling.
+ *
+ * REQUESTS
+ *
+ * sendHeadersOnly() -- assembles HEADERS frame and puts on connection outbound Q
+ *
+ * sendRequest() -- sendHeadersOnly() + sendBody()
+ *
+ * sendBody() -- in calling thread: obeys all flow control (so may block)
+ *               obtains data from request body processor and places on connection
+ *               outbound Q.
+ *
+ * sendBodyAsync() -- calls sendBody() in an executor thread.
+ *
+ * sendHeadersAsync() -- calls sendHeadersOnly() which does not block
+ *
+ * sendRequestAsync() -- calls sendRequest() in an executor thread
+ *
+ * RESPONSES
+ *
+ * Multiple responses can be received per request. Responses are queued up on
+ * a LinkedList of CF<HttpResponse> and the the first one on the list is completed
+ * with the next response
+ *
+ * getResponseAsync() -- queries list of response CFs and returns first one
+ *               if one exists. Otherwise, creates one and adds it to list
+ *               and returns it. Completion is achieved through the
+ *               incoming() upcall from connection reader thread.
+ *
+ * getResponse() -- calls getResponseAsync() and waits for CF to complete
+ *
+ * responseBody() -- in calling thread: blocks for incoming DATA frames on
+ *               stream inputQ. Obeys remote and local flow control so may block.
+ *               Calls user response body processor with data buffers.
+ *
+ * responseBodyAsync() -- calls responseBody() in an executor thread.
+ *
+ * incoming() -- entry point called from connection reader thread. Frames are
+ *               either handled immediately without blocking or for data frames
+ *               placed on the stream's inputQ which is consumed by the stream's
+ *               reader thread.
+ *
+ * PushedStream sub class
+ * ======================
+ * Sending side methods are not used because the request comes from a PUSH_PROMISE
+ * frame sent by the server. When a PUSH_PROMISE is received the PushedStream
+ * is created. PushedStream does not use responseCF list as there can be only
+ * one response. The CF is created when the object created and when the response
+ * HEADERS frame is received the object is completed.
  */
 class Stream extends ExchangeImpl {
 
-    void debugPrint() {
-    }
+    final Queue<Http2Frame> inputQ;
+
+    volatile int streamid;
+
+    long responseContentLen = -1;
+    long responseBytesProcessed = 0;
+    long requestContentLen;
+
+    Http2Connection connection;
+    HttpClientImpl client;
+    final HttpRequestImpl request;
+    final DecodingCallback rspHeadersConsumer;
+    HttpHeadersImpl responseHeaders;
+    final HttpHeadersImpl requestHeaders;
+    final HttpHeadersImpl requestPseudoHeaders;
+    HttpResponse.BodyProcessor<?> responseProcessor;
+    final HttpRequest.BodyProcessor requestProcessor;
+    HttpResponse response;
+
+    // state flags
+    boolean requestSent, responseReceived;
+
+    final FlowController userRequestFlowController =
+            new FlowController();
+    final FlowController remoteRequestFlowController =
+            new FlowController();
+    final FlowController responseFlowController =
+            new FlowController();
+
+    final ExecutorWrapper executor;
 
     @Override
     @SuppressWarnings("unchecked")
     <T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
-            return null;
+        this.responseProcessor = processor;
+        CompletableFuture<T> cf;
+        try {
+            T body = processor.onResponseBodyStart(
+                    responseContentLen, responseHeaders,
+                    responseFlowController); // TODO: filter headers
+            if (body != null) {
+                cf = CompletableFuture.completedFuture(body);
+                receiveDataAsync(processor);
+            } else
+                cf = receiveDataAsync(processor);
+        } catch (IOException e) {
+            cf = CompletableFuture.failedFuture(e);
+        }
+        PushGroup<?> pg = request.pushGroup();
+        if (pg != null) {
+            // if an error occurs make sure it is recorded in the PushGroup
+            cf = cf.whenComplete((t,e) -> pg.pushError(e));
+        }
+        return cf;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("streamid: ")
+                .append(streamid);
+        return sb.toString();
+    }
+
+    // pushes entire response body into response processor
+    // blocking when required by local or remote flow control
+    void receiveData() throws IOException {
+        Http2Frame frame;
+        DataFrame df = null;
+        try {
+            do {
+                frame = inputQ.take();
+                if (!(frame instanceof DataFrame)) {
+                    assert false;
+                    continue;
+                }
+                df = (DataFrame) frame;
+                int len = df.getDataLength();
+                ByteBuffer[] buffers = df.getData();
+                for (ByteBuffer b : buffers) {
+                    responseFlowController.take();
+                    responseProcessor.onResponseBodyChunk(b);
+                }
+                sendWindowUpdate(len);
+            } while (!df.getFlag(DataFrame.END_STREAM));
+        } catch (InterruptedException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private <T> CompletableFuture<T> receiveDataAsync(HttpResponse.BodyProcessor<T> processor) {
+        CompletableFuture<T> cf = new CompletableFuture<>();
+        executor.execute(() -> {
+            try {
+                receiveData();
+                T body = processor.onResponseComplete();
+                cf.complete(body);
+                responseReceived();
+            } catch (Throwable t) {
+                cf.completeExceptionally(t);
+            }
+        }, null);
+        return cf;
+    }
+
+    private void sendWindowUpdate(int increment)
+            throws IOException, InterruptedException {
+        if (increment == 0)
+            return;
+        LinkedList<Http2Frame> list = new LinkedList<>();
+        WindowUpdateFrame frame = new WindowUpdateFrame();
+        frame.streamid(streamid);
+        frame.setUpdate(increment);
+        list.add(frame);
+        frame = new WindowUpdateFrame();
+        frame.streamid(0);
+        frame.setUpdate(increment);
+        list.add(frame);
+        connection.sendFrames(list);
+    }
+
+    @Override
+    CompletableFuture<Void> sendBodyAsync() {
+        final CompletableFuture<Void> cf = new CompletableFuture<>();
+        executor.execute(() -> {
+            try {
+                sendBodyImpl();
+                cf.complete(null);
+            } catch (IOException | InterruptedException e) {
+                cf.completeExceptionally(e);
+            }
+        }, null);
+        return cf;
+    }
+
+    @SuppressWarnings("unchecked")
+    Stream(HttpClientImpl client, Http2Connection connection, Exchange e) {
+        super(e);
+        this.client = client;
+        this.connection = connection;
+        this.request = e.request();
+        this.requestProcessor = request.requestProcessor();
+        responseHeaders = new HttpHeadersImpl();
+        requestHeaders = new HttpHeadersImpl();
+        rspHeadersConsumer = (name, value) -> {
+            responseHeaders.addHeader(name.toString(), value.toString());
+        };
+        this.executor = client.executorWrapper();
+        //this.response_cf = new CompletableFuture<HttpResponseImpl>();
+        this.requestPseudoHeaders = new HttpHeadersImpl();
+        // NEW
+        this.inputQ = new Queue<>();
+    }
+
+    @SuppressWarnings("unchecked")
+    Stream(HttpClientImpl client, Http2Connection connection, HttpRequestImpl req) {
+        super(null);
+        this.client = client;
+        this.connection = connection;
+        this.request = req;
+        this.requestProcessor = null;
+        responseHeaders = new HttpHeadersImpl();
+        requestHeaders = new HttpHeadersImpl();
+        rspHeadersConsumer = (name, value) -> {
+            responseHeaders.addHeader(name.toString(), value.toString());
+        };
+        this.executor = client.executorWrapper();
+        //this.response_cf = new CompletableFuture<HttpResponseImpl>();
+        this.requestPseudoHeaders = new HttpHeadersImpl();
+        // NEW
+        this.inputQ = new Queue<>();
     }
 
-    Stream(HttpClientImpl client, Http2Connection connection, Exchange e) {
-        super(e);
+    /**
+     * Entry point from Http2Connection reader thread.
+     *
+     * Data frames will be removed by response body thread.
+     *
+     * @param frame
+     * @throws IOException
+     */
+    void incoming(Http2Frame frame) throws IOException, InterruptedException {
+        if ((frame instanceof HeaderFrame) && ((HeaderFrame)frame).endHeaders()) {
+            // Complete headers accumulated. handle response.
+            // It's okay if there are multiple HeaderFrames.
+            handleResponse();
+        } else if (frame instanceof DataFrame) {
+            inputQ.put(frame);
+        } else {
+            otherFrame(frame);
+        }
+    }
+
+    void otherFrame(Http2Frame frame) throws IOException {
+        switch (frame.type()) {
+            case WindowUpdateFrame.TYPE:
+                incoming_windowUpdate((WindowUpdateFrame) frame);
+                break;
+            case ResetFrame.TYPE:
+                incoming_reset((ResetFrame) frame);
+                break;
+            case PriorityFrame.TYPE:
+                incoming_priority((PriorityFrame) frame);
+                break;
+            default:
+                String msg = "Unexpected frame: " + frame.toString();
+                throw new IOException(msg);
+        }
+    }
+
+    // The Hpack decoder decodes into one of these consumers of name,value pairs
+
+    DecodingCallback rspHeadersConsumer() {
+        return rspHeadersConsumer;
+    }
+
+    // create and return the HttpResponseImpl
+    protected void handleResponse() throws IOException {
+        HttpConnection c = connection.connection; // TODO: improve
+        long statusCode = responseHeaders
+                .firstValueAsLong(":status")
+                .orElseThrow(() -> new IOException("no statuscode in response"));
+
+        this.response = new HttpResponseImpl((int)statusCode, exchange, responseHeaders, null,
+                c.sslParameters(), HttpClient.Version.HTTP_2, c);
+        this.responseContentLen = responseHeaders
+                .firstValueAsLong("content-length")
+                .orElse(-1L);
+        // different implementations for normal streams and pushed streams
+        completeResponse(response);
+    }
+
+    void incoming_reset(ResetFrame frame) {
+        // TODO: implement reset
+        int error = frame.getErrorCode();
+        IOException e = new IOException(ErrorFrame.stringForCode(error));
+        completeResponseExceptionally(e);
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    void incoming_priority(PriorityFrame frame) {
+        // TODO: implement priority
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    void incoming_windowUpdate(WindowUpdateFrame frame) {
+        int amount = frame.getUpdate();
+        if (amount > 0)
+            remoteRequestFlowController.accept(amount);
+    }
+
+    void incoming_pushPromise(HttpRequestImpl pushReq, PushedStream pushStream) throws IOException {
+        if (Log.requests()) {
+            Log.logRequest("PUSH_PROMISE: " + pushReq.toString());
+        }
+        PushGroup<?> pushGroup = request.pushGroup();
+        if (pushGroup == null) {
+            cancelImpl(new IllegalStateException("unexpected push promise"));
+        }
+        // get the handler and call it.
+        BiFunction<HttpRequest,CompletableFuture<HttpResponse>,Boolean> ph =
+            pushGroup.pushHandler();
+
+        CompletableFuture<HttpResponse> pushCF = pushStream
+                .getResponseAsync(null)
+                .thenApply(r -> (HttpResponse)r);
+        boolean accept = ph.apply(pushReq, pushCF);
+        if (!accept) {
+            IOException ex = new IOException("Stream cancelled by user");
+            cancelImpl(ex);
+            pushCF.completeExceptionally(ex);
+        } else {
+            pushStream.requestSent();
+            pushGroup.addPush();
+        }
+    }
+
+    private OutgoingHeaders headerFrame(long contentLength) {
+        HttpHeadersImpl h = request.getSystemHeaders();
+        if (contentLength > 0) {
+            h.setHeader("content-length", Long.toString(contentLength));
+        }
+        setPseudoHeaderFields();
+        OutgoingHeaders f = new OutgoingHeaders(h, request.getUserHeaders(), this);
+        if (contentLength == 0) {
+            f.setFlag(HeadersFrame.END_STREAM);
+        }
+        return f;
+    }
+
+    private void setPseudoHeaderFields() {
+        HttpHeadersImpl hdrs = requestPseudoHeaders;
+        String method = request.method();
+        hdrs.setHeader(":method", method);
+        URI uri = request.uri();
+        hdrs.setHeader(":scheme", uri.getScheme());
+        // TODO: userinfo deprecated. Needs to be removed
+        hdrs.setHeader(":authority", uri.getAuthority());
+        // TODO: ensure header names beginning with : not in user headers
+        String query = uri.getQuery();
+        String path = uri.getPath();
+        if (path == null) {
+            if (method.equalsIgnoreCase("OPTIONS")) {
+                path = "*";
+            } else {
+                path = "/";
+            }
+        }
+        if (query != null) {
+            path += "?" + query;
+        }
+        hdrs.setHeader(":path", path);
+    }
+
+    HttpHeadersImpl getRequestPseudoHeaders() {
+        return requestPseudoHeaders;
     }
 
     @Override
     HttpResponseImpl getResponse() throws IOException {
-        return null;
+        try {
+            return getResponseAsync(null).join();
+        } catch (Throwable e) {
+            Throwable t = e.getCause();
+            if (t instanceof IOException) {
+                throw (IOException)t;
+            }
+            throw e;
+        }
     }
 
     @Override
     void sendRequest() throws IOException, InterruptedException {
+        sendHeadersOnly();
+        sendBody();
+    }
+
+    /**
+     * A simple general purpose blocking flow controller
+     */
+    class FlowController implements LongConsumer {
+        int permits;
+
+        FlowController() {
+            this.permits = 0;
+        }
+
+        @Override
+        public synchronized void accept(long n) {
+            if (n < 1) {
+                throw new InternalError("FlowController.accept called with " + n);
+            }
+            if (permits == 0) {
+                permits += n;
+                notifyAll();
+            } else {
+                permits += n;
+            }
+        }
+
+        public synchronized void take() throws InterruptedException {
+            take(1);
+        }
+
+        public synchronized void take(int amount) throws InterruptedException {
+            assert permits >= 0;
+            while (permits < amount) {
+                int n = Math.min(amount, permits);
+                permits -= n;
+                amount -= n;
+                if (amount > 0)
+                    wait();
+            }
+        }
     }
 
     @Override
     void sendHeadersOnly() throws IOException, InterruptedException {
+        if (Log.requests() && request != null) {
+            Log.logRequest(request.toString());
+        }
+        requestContentLen = requestProcessor.onRequestStart(request, userRequestFlowController);
+        OutgoingHeaders f = headerFrame(requestContentLen);
+        connection.sendFrame(f);
     }
 
     @Override
     void sendBody() throws IOException, InterruptedException {
+        sendBodyImpl();
     }
 
+    void registerStream(int id) {
+        this.streamid = id;
+        connection.putStream(this, streamid);
+    }
+
+    DataFrame getDataFrame() throws IOException, InterruptedException {
+        userRequestFlowController.take();
+        int maxpayloadLen = connection.getMaxSendFrameSize() - 9;
+        ByteBuffer buffer = connection.getBuffer();
+        buffer.limit(maxpayloadLen);
+        boolean complete = requestProcessor.onRequestBodyChunk(buffer);
+        buffer.flip();
+        int amount = buffer.remaining();
+        // wait for flow control if necessary. Following method will block
+        // until after headers frame is sent, so correct streamid is set.
+        remoteRequestFlowController.take(amount);
+        connection.obtainSendWindow(amount);
+
+        DataFrame df = new DataFrame();
+        df.streamid(streamid);
+        if (complete) {
+            df.setFlag(DataFrame.END_STREAM);
+        }
+        df.setData(buffer);
+        df.computeLength();
+        return df;
+    }
+
+
     @Override
     CompletableFuture<Void> sendHeadersAsync() {
-        return null;
+        try {
+            sendHeadersOnly();
+            return CompletableFuture.completedFuture(null);
+        } catch (IOException | InterruptedException ex) {
+            return CompletableFuture.failedFuture(ex);
+        }
     }
 
+    /**
+     * A List of responses relating to this stream. Normally there is only
+     * one response, but intermediate responses like 100 are allowed
+     * and must be passed up to higher level before continuing. Deals with races
+     * such as if responses are returned before the CFs get created by
+     * getResponseAsync()
+     */
+
+    final List<CompletableFuture<HttpResponseImpl>> response_cfs = new LinkedList<>();
+
     @Override
     CompletableFuture<HttpResponseImpl> getResponseAsync(Void v) {
-        return null;
+        CompletableFuture<HttpResponseImpl> cf;
+        synchronized (response_cfs) {
+            if (!response_cfs.isEmpty()) {
+                cf = response_cfs.remove(0);
+            } else {
+                cf = new CompletableFuture<>();
+                response_cfs.add(cf);
+            }
+        }
+        PushGroup<?> pg = request.pushGroup();
+        if (pg != null) {
+            // if an error occurs make sure it is recorded in the PushGroup
+            cf = cf.whenComplete((t,e) -> pg.pushError(e));
+        }
+        return cf;
+    }
+
+    /**
+     * Completes the first uncompleted CF on list, and removes it. If there is no
+     * uncompleted CF then creates one (completes it) and adds to list
+     */
+    void completeResponse(HttpResponse r) {
+        HttpResponseImpl resp = (HttpResponseImpl)r;
+        synchronized (response_cfs) {
+            for (CompletableFuture<HttpResponseImpl> cf : response_cfs) {
+                if (!cf.isDone()) {
+                    cf.complete(resp);
+                    response_cfs.remove(cf);
+                    //responseHeaders = new HttpHeadersImpl(); // for any following header blocks
+                    return;
+                } else
+                    System.err.println("Stream: " + this + " ALREADY DONE");
+            }
+            response_cfs.add(CompletableFuture.completedFuture(resp));
+            //responseHeaders = new HttpHeadersImpl(); // for any following header blocks
+        }
     }
 
-    @Override
-    CompletableFuture<Void> sendBodyAsync() {
-        return null;
+    // methods to update state and remove stream when finished
+
+    synchronized void requestSent() {
+        requestSent = true;
+        if (responseReceived)
+            connection.deleteStream(this);
+    }
+
+    synchronized void responseReceived() {
+        responseReceived = true;
+        if (requestSent)
+            connection.deleteStream(this);
+        PushGroup<?> pg = request.pushGroup();
+        if (pg != null)
+            pg.noMorePushes();
+    }
+
+    /**
+     * same as above but for errors
+     *
+     * @param t
+     */
+    void completeResponseExceptionally(Throwable t) {
+        synchronized (response_cfs) {
+            for (CompletableFuture<HttpResponseImpl> cf : response_cfs) {
+                if (!cf.isDone()) {
+                    cf.completeExceptionally(t);
+                    response_cfs.remove(cf);
+                    return;
+                }
+            }
+            response_cfs.add(CompletableFuture.failedFuture(t));
+        }
+    }
+
+    void sendBodyImpl() throws IOException, InterruptedException {
+        if (requestContentLen == 0) {
+            // no body
+            return;
+        }
+        DataFrame df;
+        do {
+            df = getDataFrame();
+            // TODO: check accumulated content length (if not checked below)
+            connection.sendFrame(df);
+        } while (!df.getFlag(DataFrame.END_STREAM));
+        requestSent();
     }
 
     @Override
     void cancel() {
+        cancelImpl(new Exception("Cancelled"));
     }
 
 
+    void cancelImpl(Throwable e) {
+        Log.logTrace("cancelling stream: {0}\n", e.toString());
+        inputQ.close();
+        try {
+            connection.resetStream(streamid, ResetFrame.CANCEL);
+        } catch (IOException | InterruptedException ex) {
+            Log.logError(ex);
+        }
+    }
+
     @Override
     CompletableFuture<Void> sendRequestAsync() {
-        return null;
+        CompletableFuture<Void> cf = new CompletableFuture<>();
+        executor.execute(() -> {
+           try {
+               sendRequest();
+               cf.complete(null);
+           } catch (IOException |InterruptedException e) {
+               cf.completeExceptionally(e);
+           }
+        }, null);
+        return cf;
     }
 
     @Override
     <T> T responseBody(HttpResponse.BodyProcessor<T> processor) throws IOException {
-        return null;
+        this.responseProcessor = processor;
+        T body = processor.onResponseBodyStart(
+                    responseContentLen, responseHeaders,
+                    responseFlowController); // TODO: filter headers
+        if (body == null) {
+            receiveData();
+            return processor.onResponseComplete();
+        } else
+            receiveDataAsync(processor);
+        responseReceived();
+        return body;
+    }
+
+    // called from Http2Connection reader thread
+    synchronized void updateOutgoingWindow(int update) {
+        remoteRequestFlowController.accept(update);
+    }
+
+    void close(String msg) {
+        cancel();
+    }
+
+    static class PushedStream extends Stream {
+        final PushGroup<?> pushGroup;
+        final private Stream parent;      // used by server push streams
+        // push streams need the response CF allocated up front as it is
+        // given directly to user via the multi handler callback function.
+        final CompletableFuture<HttpResponseImpl> pushCF;
+        final HttpRequestImpl pushReq;
+
+        PushedStream(PushGroup<?> pushGroup, HttpClientImpl client,
+                Http2Connection connection, Stream parent,
+                HttpRequestImpl pushReq) {
+            super(client, connection, pushReq);
+            this.pushGroup = pushGroup;
+            this.pushReq = pushReq;
+            this.pushCF = new CompletableFuture<>();
+            this.parent = parent;
+        }
+
+        // Following methods call the super class but in case of
+        // error record it in the PushGroup. The error method is called
+        // with a null value when no error occurred (is a no-op)
+        @Override
+        CompletableFuture<Void> sendBodyAsync() {
+            return super.sendBodyAsync()
+                        .whenComplete((v, t) -> pushGroup.pushError(t));
+        }
+
+        @Override
+        CompletableFuture<Void> sendHeadersAsync() {
+            return super.sendHeadersAsync()
+                        .whenComplete((v, t) -> pushGroup.pushError(t));
+        }
+
+        @Override
+        CompletableFuture<Void> sendRequestAsync() {
+            return super.sendRequestAsync()
+                        .whenComplete((v, t) -> pushGroup.pushError(t));
+        }
+
+        @Override
+        CompletableFuture<HttpResponseImpl> getResponseAsync(Void vo) {
+            return pushCF.whenComplete((v, t) -> pushGroup.pushError(t));
+        }
+
+        @Override
+        <T> CompletableFuture<T> responseBodyAsync(HttpResponse.BodyProcessor<T> processor) {
+            return super.responseBodyAsync(processor)
+                        .whenComplete((v, t) -> pushGroup.pushError(t));
+        }
+
+        @Override
+        void completeResponse(HttpResponse r) {
+            HttpResponseImpl resp = (HttpResponseImpl)r;
+            Utils.logResponse(resp);
+            pushCF.complete(resp);
+        }
+
+        @Override
+        void completeResponseExceptionally(Throwable t) {
+            pushCF.completeExceptionally(t);
+        }
+
+        @Override
+        synchronized void responseReceived() {
+            super.responseReceived();
+            pushGroup.pushCompleted();
+        }
+
+        // create and return the PushResponseImpl
+        @Override
+        protected void handleResponse() {
+            HttpConnection c = connection.connection; // TODO: improve
+            long statusCode = responseHeaders
+                .firstValueAsLong(":status")
+                .orElse(-1L);
+
+            if (statusCode == -1L)
+                completeResponseExceptionally(new IOException("No status code"));
+            ImmutableHeaders h = new ImmutableHeaders(responseHeaders, Utils.ALL_HEADERS);
+            this.response = new HttpResponseImpl((int)statusCode, pushReq, h, this,
+                c.sslParameters());
+            this.responseContentLen = responseHeaders
+                .firstValueAsLong("content-length")
+                .orElse(-1L);
+            // different implementations for normal streams and pushed streams
+            completeResponse(response);
+        }
+    }
+
+    /**
+     * One PushGroup object is associated with the parent Stream of
+     * the pushed Streams. This keeps track of all common state associated
+     * with the pushes.
+     */
+    static class PushGroup<T> {
+        // the overall completion object, completed when all pushes are done.
+        final CompletableFuture<T> resultCF;
+        Throwable error; // any exception that occured during pushes
+
+        // CF for main response
+        final CompletableFuture<HttpResponse> mainResponse;
+
+        // user's processor object
+        final HttpResponse.MultiProcessor<T> multiProcessor;
+
+        // per push handler function provided by processor
+        final private BiFunction<HttpRequest,
+                           CompletableFuture<HttpResponse>,
+                           Boolean> pushHandler;
+        int numberOfPushes;
+        int remainingPushes;
+        boolean noMorePushes = false;
+
+        PushGroup(HttpResponse.MultiProcessor<T> multiProcessor, HttpRequestImpl req) {
+            this.resultCF = new CompletableFuture<>();
+            this.mainResponse = new CompletableFuture<>();
+            this.multiProcessor = multiProcessor;
+            this.pushHandler = multiProcessor.onStart(req, mainResponse);
+        }
+
+        CompletableFuture<T> groupResult() {
+            return resultCF;
+        }
+
+        CompletableFuture<HttpResponse> mainResponse() {
+            return mainResponse;
+        }
+
+        private BiFunction<HttpRequest,
+            CompletableFuture<HttpResponse>, Boolean> pushHandler()
+        {
+                return pushHandler;
+        }
+
+        synchronized void addPush() {
+            numberOfPushes++;
+            remainingPushes++;
+        }
+
+        synchronized int numberOfPushes() {
+            return numberOfPushes;
+        }
+        // This is called when the main body response completes because it means
+        // no more PUSH_PROMISEs are possible
+        synchronized void noMorePushes() {
+            noMorePushes = true;
+            checkIfCompleted();
+        }
+
+        synchronized void pushCompleted() {
+            remainingPushes--;
+            checkIfCompleted();
+        }
+
+        synchronized void checkIfCompleted() {
+            if (remainingPushes == 0 && error == null && noMorePushes) {
+                T overallResult = multiProcessor.onComplete();
+                resultCF.complete(overallResult);
+            }
+        }
+
+        synchronized void pushError(Throwable t) {
+            if (t == null)
+                return;
+            this.error = t;
+            resultCF.completeExceptionally(t);
+        }
     }
 }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,28 +21,37 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  */
-
 package java.net.http;
 
+import sun.net.NetProperties;
+
+import javax.net.ssl.SSLParameters;
 import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
 import java.io.PrintStream;
 import java.io.UnsupportedEncodingException;
+import java.net.InetSocketAddress;
 import java.net.NetPermission;
 import java.net.URI;
 import java.net.URLPermission;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.net.ssl.SSLParameters;
-import sun.net.NetProperties;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.LongBinaryOperator;
+import java.util.function.Predicate;
 
 /**
  * Miscellaneous utilities
  */
-class Utils {
+final class Utils {
 
     /**
      * Allocated buffer size. Must never be higher than 16K. But can be lower
@@ -51,7 +60,59 @@
      */
     public static final int BUFSIZE = 16 * 1024;
 
-    /** Validates a RFC7230 token */
+    private static final Set<String> DISALLOWED_HEADERS_SET = Set.of(
+            "authorization", "connection", "cookie", "content-length",
+            "date", "expect", "from", "host", "origin", "proxy-authorization",
+            "referer", "user-agent", "upgrade", "via", "warning");
+
+    static final Predicate<String>
+        ALLOWED_HEADERS = header -> !Utils.DISALLOWED_HEADERS_SET.contains(header);
+
+    static final Predicate<String>
+        ALL_HEADERS = header -> true;
+
+    static InetSocketAddress getAddress(HttpRequestImpl req) {
+        URI uri = req.uri();
+        if (uri == null) {
+            return req.authority();
+        }
+        int port = uri.getPort();
+        if (port == -1) {
+            if (uri.getScheme().equalsIgnoreCase("https")) {
+                port = 443;
+            } else {
+                port = 80;
+            }
+        }
+        String host = uri.getHost();
+        if (req.proxy() == null) {
+            return new InetSocketAddress(host, port);
+        } else {
+            return InetSocketAddress.createUnresolved(host, port);
+        }
+    }
+
+    /**
+     * Puts position to limit and limit to capacity so we can resume reading
+     * into this buffer, but if required > 0 then limit may be reduced so that
+     * no more than required bytes are read next time.
+     */
+    static void resumeChannelRead(ByteBuffer buf, int required) {
+        int limit = buf.limit();
+        buf.position(limit);
+        int capacity = buf.capacity() - limit;
+        if (required > 0 && required < capacity) {
+            buf.limit(limit + required);
+        } else {
+            buf.limit(buf.capacity());
+        }
+    }
+
+    private Utils() { }
+
+    /**
+     * Validates a RFC7230 token
+     */
     static void validateToken(String token, String errormsg) {
         int length = token.length();
         for (int i = 0; i < length; i++) {
@@ -69,7 +130,7 @@
     }
 
     /**
-     * Return sthe security permission required for the given details.
+     * Returns the security permission required for the given details.
      * If method is CONNECT, then uri must be of form "scheme://host:port"
      */
     static URLPermission getPermission(URI uri,
@@ -117,13 +178,13 @@
     }
 
     static int getIntegerNetProperty(String name, int defaultValue) {
-        return AccessController.doPrivileged((PrivilegedAction<Integer>)() ->
-            NetProperties.getInteger(name, defaultValue) );
+        return AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
+                NetProperties.getInteger(name, defaultValue));
     }
 
     static String getNetProperty(String name) {
-        return AccessController.doPrivileged((PrivilegedAction<String>)() ->
-            NetProperties.get(name) );
+        return AccessController.doPrivileged((PrivilegedAction<String>) () ->
+                NetProperties.get(name));
     }
 
     static SSLParameters copySSLParameters(SSLParameters p) {
@@ -134,7 +195,9 @@
         p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm());
         p1.setMaximumPacketSize(p.getMaximumPacketSize());
         p1.setNeedClientAuth(p.getNeedClientAuth());
-        p1.setProtocols(p.getProtocols().clone());
+        String[] protocols = p.getProtocols();
+        if (protocols != null)
+            p1.setProtocols(protocols.clone());
         p1.setSNIMatchers(p.getSNIMatchers());
         p1.setServerNames(p.getServerNames());
         p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder());
@@ -142,33 +205,14 @@
         return p1;
     }
 
-
-    /** Resumes reading into the given buffer. */
-    static void unflip(ByteBuffer buf) {
-        buf.position(buf.limit());
-        buf.limit(buf.capacity());
-    }
-
     /**
      * Set limit to position, and position to mark.
-     *
-     *
-     * @param buffer
-     * @param mark
      */
     static void flipToMark(ByteBuffer buffer, int mark) {
         buffer.limit(buffer.position());
         buffer.position(mark);
     }
 
-    /** Compact and leave ready for reading. */
-    static void compact(List<ByteBuffer> buffers) {
-        for (ByteBuffer b : buffers) {
-            b.compact();
-            b.flip();
-        }
-    }
-
     static String stackTrace(Throwable t) {
         ByteArrayOutputStream bos = new ByteArrayOutputStream();
         String s = null;
@@ -182,8 +226,10 @@
         return s;
     }
 
-    /** Copies as much of src to dst as possible. */
-    static void copy (ByteBuffer src, ByteBuffer dst) {
+    /**
+     * Copies as much of src to dst as possible.
+     */
+    static void copy(ByteBuffer src, ByteBuffer dst) {
         int srcLen = src.remaining();
         int dstLen = dst.remaining();
         if (srcLen > dstLen) {
@@ -204,18 +250,101 @@
         return dst;
     }
 
-    static String combine(String[] s) {
+    //
+    // Helps to trim long names (packages, nested/inner types) in logs/toString
+    //
+    static String toStringSimple(Object o) {
+        return o.getClass().getSimpleName() + "@" +
+                Integer.toHexString(System.identityHashCode(o));
+    }
+
+    //
+    // 1. It adds a number of remaining bytes;
+    // 2. Standard Buffer-type toString for CharBuffer (since it adheres to the
+    // contract of java.lang.CharSequence.toString() which is both not too
+    // useful and not too private)
+    //
+    static String toString(Buffer b) {
+        return toStringSimple(b)
+                + "[pos=" + b.position()
+                + " lim=" + b.limit()
+                + " cap=" + b.capacity()
+                + " rem=" + b.remaining() + "]";
+    }
+
+    static String toString(CharSequence s) {
+        return s == null
+                ? "null"
+                : toStringSimple(s) + "[len=" + s.length() + "]";
+    }
+
+    static String dump(Object... objects) {
+        return Arrays.toString(objects);
+    }
+
+    static final System.Logger logger = System.getLogger("java.net.http.WebSocket");
+
+    static final ByteBuffer EMPTY_BYTE_BUFFER = ByteBuffer.allocate(0);
+
+    static String webSocketSpecViolation(String section, String detail) {
+        return "RFC 6455 " + section + " " + detail;
+    }
+
+    static void logResponse(HttpResponseImpl r) {
+        if (!Log.requests()) {
+            return;
+        }
         StringBuilder sb = new StringBuilder();
-        sb.append('[');
-        boolean first = true;
-        for (String s1 : s) {
-            if (!first) {
-                sb.append(", ");
-                first = false;
+        String method = r.request().method();
+        URI uri = r.uri();
+        String uristring = uri == null ? "" : uri.toString();
+        sb.append('(').append(method).append(" ").append(uristring).append(") ").append(Integer.toString(r.statusCode()));
+        Log.logResponse(sb.toString());
+    }
+
+    static int remaining(ByteBuffer[] bufs) {
+        int remain = 0;
+        for (ByteBuffer buf : bufs)
+            remain += buf.remaining();
+        return remain;
+    }
+
+    // assumes buffer was written into starting at position zero
+    static void unflip(ByteBuffer buf) {
+        buf.position(buf.limit());
+        buf.limit(buf.capacity());
+    }
+
+    static void close(Closeable... chans) {
+        for (Closeable chan : chans) {
+            System.err.println("Closing " + chan);
+            try {
+                chan.close();
+            } catch (IOException e) {
             }
-            sb.append(s1);
         }
-        sb.append(']');
-        return sb.toString();
+    }
+
+    static ByteBuffer[] reduce(ByteBuffer[] bufs, int start, int number) {
+        if (start == 0 && number == bufs.length)
+            return bufs;
+        ByteBuffer[] nbufs = new ByteBuffer[number];
+        int j = 0;
+        for (int i=start; i<start+number; i++)
+            nbufs[j++] = bufs[i];
+        return nbufs;
     }
+
+    static String asString(ByteBuffer buf) {
+        byte[] b = new byte[buf.remaining()];
+        buf.get(b);
+        return new String(b, StandardCharsets.US_ASCII);
+    }
+
+    // Put all these static 'empty' singletons here
+    @SuppressWarnings("rawtypes")
+    static CompletableFuture[] EMPTY_CFARRAY = new CompletableFuture[0];
+
+    static ByteBuffer EMPTY_BYTEBUFFER = ByteBuffer.allocate(0);
+    static ByteBuffer[] EMPTY_BB_ARRAY = new ByteBuffer[0];
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WindowUpdateFrame.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * 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
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+class WindowUpdateFrame extends Http2Frame {
+
+    int windowUpdate;
+
+    WindowUpdateFrame() {
+        type = TYPE;
+    }
+
+    public final static int TYPE = 0x8;
+
+    public void setUpdate(int windowUpdate) {
+        this.windowUpdate = windowUpdate;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.toString())
+          .append(" WindowUpdate: ")
+          .append(windowUpdate);
+        return sb.toString();
+    }
+
+    public int getUpdate() {
+        return this.windowUpdate;
+    }
+
+    /**
+     */
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        if (length != 4) {
+            throw new IOException("Invalid WindowUpdate frame");
+        }
+        windowUpdate = bc.getInt() & 0x7fffffff;
+    }
+
+    @Override
+    void computeLength() {
+        length = 4;
+    }
+
+    @Override
+    void writeOutgoing(ByteBufferGenerator bg) {
+        super.writeOutgoing(bg);
+        ByteBuffer buf = bg.getBuffer(4);
+        buf.putInt(windowUpdate);
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,11 +24,11 @@
  */
 
 /**
- * <h2>High level HTTP API</h2>
- * This provides a high-level client interface to HTTP (versions 1.1 and 2).
- * Synchronous and asynchronous (via
- * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main
- * classes defined are:
+ * <h2>High level HTTP and WebSocket API</h2>
+ * This provides a high-level client interfaces to HTTP (versions 1.1 and 2)
+ * and WebSocket. Synchronous and asynchronous (via {@link
+ * java.util.concurrent.CompletableFuture}) modes are provided for HTTP.
+ * WebSocket works in asynchronous mode only. The main types defined are:
  * <ul>
  *    <li>{@link java.net.http.HttpClient}</li>
  *    <li>{@link java.net.http.HttpRequest}</li>
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -43,6 +43,8 @@
 import jdk.internal.misc.JavaAWTAccess;
 import jdk.internal.misc.SharedSecrets;
 import sun.util.logging.internal.LoggingProviderImpl;
+import java.lang.reflect.Module;
+import static jdk.internal.logger.DefaultLoggerFinder.isSystem;
 
 /**
  * There is a single global LogManager object that is used to
@@ -503,10 +505,16 @@
     // as a LogManager subclass may override the addLogger, getLogger,
     // readConfiguration, and other methods.
     Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
+        final Module module = caller == null ? null : caller.getModule();
+        return demandLogger(name, resourceBundleName, module);
+    }
+
+    Logger demandLogger(String name, String resourceBundleName, Module module) {
         Logger result = getLogger(name);
         if (result == null) {
             // only allocate the new logger once
-            Logger newLogger = new Logger(name, resourceBundleName, caller, this, false);
+            Logger newLogger = new Logger(name, resourceBundleName,
+                    module == null ? null : module, this, false);
             do {
                 if (addLogger(newLogger)) {
                     // We successfully added the new Logger that we
@@ -532,9 +540,14 @@
     }
 
     Logger demandSystemLogger(String name, String resourceBundleName, Class<?> caller) {
+        final Module module = caller == null ? null : caller.getModule();
+        return demandSystemLogger(name, resourceBundleName, module);
+    }
+
+    Logger demandSystemLogger(String name, String resourceBundleName, Module module) {
         // Add a system logger in the system context's namespace
         final Logger sysLogger = getSystemContext()
-                .demandLogger(name, resourceBundleName, caller);
+                .demandLogger(name, resourceBundleName, module);
 
         // Add the system logger to the LogManager's namespace if not exist
         // so that there is only one single logger of the given name.
@@ -619,11 +632,11 @@
             return global;
         }
 
-        Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
+        Logger demandLogger(String name, String resourceBundleName, Module module) {
             // a LogManager subclass may have its own implementation to add and
             // get a Logger.  So delegate to the LogManager to do the work.
             final LogManager owner = getOwner();
-            return owner.demandLogger(name, resourceBundleName, caller);
+            return owner.demandLogger(name, resourceBundleName, module);
         }
 
 
@@ -907,11 +920,13 @@
         // one single logger of the given name.  System loggers are visible
         // to applications unless a logger of the same name has been added.
         @Override
-        Logger demandLogger(String name, String resourceBundleName, Class<?> caller) {
+        Logger demandLogger(String name, String resourceBundleName,
+                            Module module) {
             Logger result = findLogger(name);
             if (result == null) {
                 // only allocate the new system logger once
-                Logger newLogger = new Logger(name, resourceBundleName, caller, getOwner(), true);
+                Logger newLogger = new Logger(name, resourceBundleName,
+                                              module, getOwner(), true);
                 do {
                     if (addLocalLogger(newLogger)) {
                         // We successfully added the new Logger that we
@@ -2622,18 +2637,18 @@
         }
 
         /**
-         * Demands a logger on behalf of the given {@code caller}.
+         * Demands a logger on behalf of the given {@code module}.
          * <p>
-         * If a named logger suitable for the given caller is found
+         * If a named logger suitable for the given module is found
          * returns it.
-         * Otherwise, creates a new logger suitable for the given caller.
+         * Otherwise, creates a new logger suitable for the given module.
          *
          * @param name   The logger name.
-         * @param caller The caller on which behalf the logger is created/retrieved.
-         * @return A logger for the given {@code caller}.
+         * @param module The module on which behalf the logger is created/retrieved.
+         * @return A logger for the given {@code module}.
          *
          * @throws NullPointerException if {@code name} is {@code null}
-         *         or {@code caller} is {@code null}.
+         *         or {@code module} is {@code null}.
          * @throws IllegalArgumentException if {@code manager} is not the default
          *         LogManager.
          * @throws SecurityException if a security manager is present and the
@@ -2641,7 +2656,7 @@
          *        {@link LoggingPermission LoggingPermission("demandLogger", null)}.
          */
         @Override
-        public Logger demandLoggerFor(LogManager manager, String name, /* Module */ Class<?> caller) {
+        public Logger demandLoggerFor(LogManager manager, String name, Module module) {
             if (manager != getLogManager()) {
                 // having LogManager as parameter just ensures that the
                 // caller will have initialized the LogManager before reaching
@@ -2649,15 +2664,16 @@
                 throw new IllegalArgumentException("manager");
             }
             Objects.requireNonNull(name);
+            Objects.requireNonNull(module);
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(controlPermission);
             }
-            if (caller.getClassLoader() == null) {
+            if (isSystem(module)) {
                 return manager.demandSystemLogger(name,
-                    Logger.SYSTEM_LOGGER_RB_NAME, caller);
+                    Logger.SYSTEM_LOGGER_RB_NAME, module);
             } else {
-                return manager.demandLogger(name, null, caller);
+                return manager.demandLogger(name, null, module);
             }
         }
 
--- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java	Wed Jul 05 21:39:33 2017 +0200
@@ -40,6 +40,7 @@
 import java.util.function.Supplier;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
+import static jdk.internal.logger.DefaultLoggerFinder.isSystem;
 
 /**
  * A Logger object is used to log messages for a specific
@@ -379,7 +380,8 @@
         this(name, resourceBundleName, null, LogManager.getLogManager(), false);
     }
 
-    Logger(String name, String resourceBundleName, Class<?> caller, LogManager manager, boolean isSystemLogger) {
+    Logger(String name, String resourceBundleName, Module caller,
+           LogManager manager, boolean isSystemLogger) {
         this.manager = manager;
         this.isSystemLogger = isSystemLogger;
         setupResourceInfo(resourceBundleName, caller);
@@ -387,10 +389,7 @@
         levelValue = Level.INFO.intValue();
     }
 
-    private void setCallerModuleRef(Class<?> caller) {
-        Module callerModule = ((caller != null)
-                                        ? caller.getModule()
-                                        : null);
+    private void setCallerModuleRef(Module callerModule) {
         if (callerModule != null) {
             this.callerModuleRef = new WeakReference<>(callerModule);
         }
@@ -618,7 +617,7 @@
         // all loggers in the system context will default to
         // the system logger's resource bundle - therefore the caller won't
         // be needed and can be null.
-        Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, null);
+        Logger result = manager.demandSystemLogger(name, SYSTEM_LOGGER_RB_NAME, (Module)null);
         return result;
     }
 
@@ -681,8 +680,10 @@
         LogManager manager = LogManager.getLogManager();
         // cleanup some Loggers that have been GC'ed
         manager.drainLoggerRefQueueBounded();
+        final Class<?> callerClass = Reflection.getCallerClass();
+        final Module module = callerClass.getModule();
         Logger result = new Logger(null, resourceBundleName,
-                                   Reflection.getCallerClass(), manager, false);
+                                   module, manager, false);
         result.anonymous = true;
         Logger root = manager.getLogger("");
         result.doSetParent(root);
@@ -2046,6 +2047,11 @@
         }
     }
 
+    private void setupResourceInfo(String name, Class<?> caller) {
+        final Module module = caller == null ? null : caller.getModule();
+        setupResourceInfo(name, module);
+    }
+
     // Private utility method to initialize our one entry
     // resource bundle name cache and the callers Module
     // Note: for consistency reasons, we are careful to check
@@ -2053,7 +2059,7 @@
     // resourceBundleName field.
     // Synchronized to prevent races in setting the fields.
     private synchronized void setupResourceInfo(String name,
-                                                Class<?> callerClass) {
+                                                Module callerModule) {
         final LoggerBundle lb = loggerBundle;
         if (lb.resourceBundleName != null) {
             // this Logger already has a ResourceBundle
@@ -2072,8 +2078,9 @@
             return;
         }
 
-        setCallerModuleRef(callerClass);
-        if (isSystemLogger && (callerClass != null && callerClass.getClassLoader() != null)) {
+        setCallerModuleRef(callerModule);
+
+        if (isSystemLogger && (callerModule != null && !isSystem(callerModule))) {
             checkPermission();
         }
 
--- a/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/java.logging/share/classes/sun/util/logging/internal/LoggingProviderImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -32,6 +32,7 @@
 import java.util.function.Supplier;
 import java.lang.System.LoggerFinder;
 import java.lang.System.Logger;
+import java.lang.reflect.Module;
 import java.util.Objects;
 import java.util.logging.LogManager;
 import jdk.internal.logger.DefaultLoggerFinder;
@@ -398,21 +399,20 @@
     }
 
     /**
-     * Creates a java.util.logging.Logger for the given caller.
+     * Creates a java.util.logging.Logger for the given module.
      * @param name the logger name.
-     * @param caller the caller for which the logger should be created.
-     * @return a Logger suitable for use in the given caller.
+     * @param module the module for which the logger should be created.
+     * @return a Logger suitable for use in the given module.
      */
     private static java.util.logging.Logger demandJULLoggerFor(final String name,
-                                                            /* Module */
-                                                            final Class<?> caller) {
+                                                               Module module) {
         final LogManager manager = LogManager.getLogManager();
         final SecurityManager sm = System.getSecurityManager();
         if (sm == null) {
-            return logManagerAccess.demandLoggerFor(manager, name, caller);
+            return logManagerAccess.demandLoggerFor(manager, name, module);
         } else {
             final PrivilegedAction<java.util.logging.Logger> pa =
-                    () -> logManagerAccess.demandLoggerFor(manager, name, caller);
+                    () -> logManagerAccess.demandLoggerFor(manager, name, module);
             return AccessController.doPrivileged(pa, null, LOGGING_CONTROL_PERMISSION);
         }
     }
@@ -429,17 +429,17 @@
      * {@code RuntimePermission("loggerFinder")}.
      */
     @Override
-    protected Logger demandLoggerFor(String name, /* Module */ Class<?> caller) {
+    protected Logger demandLoggerFor(String name, Module module) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(LOGGERFINDER_PERMISSION);
         }
-        return JULWrapper.of(demandJULLoggerFor(name,caller));
+        return JULWrapper.of(demandJULLoggerFor(name,module));
     }
 
     public static interface LogManagerAccess {
         java.util.logging.Logger demandLoggerFor(LogManager manager,
-                String name, /* Module */ Class<?> caller);
+                String name, Module module);
     }
 
     // Hook for tests
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageLocationWriter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -61,24 +61,32 @@
         String baseName;
         String extensionName = "";
 
-        int offset = fullName.indexOf('/', 1);
-        if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) {
-            moduleName = fullName.substring(1, offset);
-            fullName = fullName.substring(offset + 1);
-        }
+        if (fullName.startsWith("/modules/")) {
+            moduleName = "modules";
+            baseName = fullName.substring("/modules/".length());
+        } else if ( fullName.startsWith("/packages/")) {
+            moduleName = "packages";
+            baseName = fullName.substring("/packages/".length());
+        } else {
+            int offset = fullName.indexOf('/', 1);
+            if (fullName.length() >= 2 && fullName.charAt(0) == '/' && offset != -1) {
+                moduleName = fullName.substring(1, offset);
+                fullName = fullName.substring(offset + 1);
+            }
 
-        offset = fullName.lastIndexOf('/');
-        if (1 < offset) {
-            parentName = fullName.substring(0, offset);
-            fullName = fullName.substring(offset + 1);
-        }
+            offset = fullName.lastIndexOf('/');
+            if (1 < offset) {
+                parentName = fullName.substring(0, offset);
+                fullName = fullName.substring(offset + 1);
+            }
 
-        offset = fullName.lastIndexOf('.');
-        if (offset != -1) {
-            baseName = fullName.substring(0, offset);
-            extensionName = fullName.substring(offset + 1);
-        } else {
-            baseName = fullName;
+            offset = fullName.lastIndexOf('.');
+            if (offset != -1) {
+                baseName = fullName.substring(0, offset);
+                extensionName = fullName.substring(offset + 1);
+            } else {
+                baseName = fullName;
+            }
         }
 
         return new ImageLocationWriter(strings)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/packager/AppRuntimeImageBuilder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal.packager;
+
+
+import jdk.tools.jlink.Jlink;
+import jdk.tools.jlink.builder.ImageBuilder;
+import jdk.tools.jlink.plugin.Plugin;
+import jdk.tools.jlink.builder.*;
+import jdk.tools.jlink.plugin.Pool;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+/**
+ * AppRuntimeImageBuilder is a private API used only by the Java Packager to generate
+ * a Java runtime image using jlink. AppRuntimeImageBuilder encapsulates the
+ * arguments that jlink requires to generate this image. To create the image call the
+ * build() method.
+ */
+public final class AppRuntimeImageBuilder {
+    private Path outputDir = null;
+    private List<Path> modulePath = null;
+    private Set<String> addModules = null;
+    private Set<String> limitModules = null;
+    private String excludeFileList = null;
+    private Map<String, String> userArguments = null;
+    private Boolean stripNativeCommands = null;
+
+    public AppRuntimeImageBuilder() {}
+
+    public void setOutputDir(Path value) {
+        outputDir = value;
+    }
+
+    public void setModulePath(List<Path> value) {
+        modulePath = value;
+    }
+
+    public void setAddModules(Set<String> value) {
+        addModules = value;
+    }
+
+    public void setLimitModules(Set<String> value) {
+        limitModules = value;
+    }
+
+    public void setExcludeFileList(String value) {
+        excludeFileList = value;
+    }
+
+    public void setStripNativeCommands(boolean value) {
+        stripNativeCommands = value;
+    }
+
+    public void setUserArguments(Map<String, String> value) {
+        userArguments = value;
+    }
+
+    public void build() throws IOException {
+        // jlink main arguments
+        Jlink.JlinkConfiguration jlinkConfig = new Jlink.JlinkConfiguration(
+            new File("").toPath(), // Unused
+            modulePath, addModules, limitModules);
+
+        // plugin configuration
+        List<Plugin> plugins = new ArrayList<Plugin>();
+
+        if (stripNativeCommands) {
+            plugins.add(Jlink.newPlugin(
+                        "strip-native-commands",
+                        Collections.singletonMap("strip-native-commands", "on"),
+                        null));
+        }
+
+        if (excludeFileList != null && !excludeFileList.isEmpty()) {
+            plugins.add(Jlink.newPlugin(
+                        "exclude-files",
+                        Collections.singletonMap("exclude-files", excludeFileList),
+                        null));
+        }
+
+        // add user supplied jlink arguments
+        for (Map.Entry<String, String> entry : userArguments.entrySet()) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            plugins.add(Jlink.newPlugin(key,
+                                        Collections.singletonMap(key, value),
+                                        null));
+        }
+
+        plugins.add(Jlink.newPlugin("installed-modules", Collections.emptyMap(), null));
+
+        // build the image
+        Jlink.PluginsConfiguration pluginConfig = new Jlink.PluginsConfiguration(
+            plugins, new DefaultImageBuilder(true, outputDir), null);
+        Jlink jlink = new Jlink();
+        jlink.build(jlinkConfig, pluginConfig);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.jstatd {
+    requires java.rmi;
+    requires jdk.jvmstat;
+
+    // RMI needs to serialize types in this package
+    exports sun.jvmstat.monitor.remote to java.rmi;
+
+    provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jvmstat.monitor.remote;
+
+import sun.jvmstat.monitor.*;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.io.IOException;
+
+/**
+ * Remote Interface for discovering and attaching to remote
+ * monitorable Java Virtual Machines.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public interface RemoteHost extends Remote {
+
+    /**
+     * Remote method to attach to a remote HotSpot Java Virtual Machine
+     * identified by <code>vmid</code>.
+     *
+     * @param vmid The identifier for the target virtual machine.
+     * @return RemoteVm - A remote object for accessing the remote Java
+     *                    Virtual Machine.
+     *
+     * @throws MonitorException Thrown when any other error is encountered
+     *                          while communicating with the target virtual
+     *                          machine.
+     * @throws RemoteException
+     *
+     */
+    RemoteVm attachVm(int vmid, String mode) throws RemoteException,
+                                                    MonitorException;
+
+    /**
+     * Remote method to detach from a remote HotSpot Java Virtual Machine
+     * identified by <code>vmid</code>.
+     *
+     * @param rvm The remote object for the target Java Virtual
+     *            Machine.
+     *
+     * @throws MonitorException Thrown when any other error is encountered
+     *                          while communicating with the target virtual
+     *                          machine.
+     * @throws RemoteException
+     */
+    void detachVm(RemoteVm rvm) throws RemoteException, MonitorException;
+
+    /**
+     * Get a list of Local Virtual Machine Identifiers for the active
+     * Java Virtual Machine the remote system. A Local Virtual Machine
+     * Identifier is also known as an <em>lvmid</em>.
+     *
+     * @return int[] - A array of <em>lvmid</em>s.
+     * @throws MonitorException Thrown when any other error is encountered
+     *                          while communicating with the target virtual
+     *                          machine.
+     * @throws RemoteException
+     */
+    int[] activeVms() throws RemoteException, MonitorException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jvmstat.monitor.remote;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+/**
+ * Interface for accessing the instrumentation exported by a
+ * Java Virtual Machine running on a remote host.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public interface RemoteVm extends Remote {
+
+    /**
+     * Interface to get the bytes associated with the instrumentation
+     * for the remote Java Virtual Machine.
+     *
+     * @return byte[] - a byte array containing the current bytes
+     *                  for the instrumentation exported by the
+     *                  remote Java Virtual Machine.
+     * @throws RemoteException Thrown on any communication error
+     */
+    byte[] getBytes() throws RemoteException;
+
+    /**
+     * Interface to get the size of the instrumentation buffer
+     * for the target Java Virtual Machine.
+     *
+     * @return int - the size of the instrumentation buffer for the
+     *               remote Java Virtual Machine.
+     * @throws RemoteException Thrown on any communication error
+     */
+    int getCapacity() throws RemoteException;
+
+    /**
+     * Interface to return the Local Virtual Machine Identifier for
+     * the remote Java Virtual Machine. The Local Virtual Machine
+     * Identifier is also know as the <em>lvmid</em>.
+     *
+     * @throws RemoteException Thrown on any communication error
+     */
+    int getLocalVmId() throws RemoteException;
+
+    /**
+     * Interface to detach from the remote Java Virtual Machine.
+     *
+     * @throws RemoteException Thrown on any communication error
+     */
+    void detach() throws RemoteException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/monitor/remote/package.html	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,39 @@
+<!doctype html public "-//IETF//DTD HTML/EN">
+<html>
+<head>
+<!--
+ 
+
+ Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+
+-->
+</head>
+<body bgcolor="white">
+<p>
+Provides interfaces supporting remote monitoring for instrumented
+HotSpot Java Virtual Machines.
+</p>
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2004, 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.jvmstat.perfdata.monitor.protocol.rmi;
+
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.event.*;
+import sun.jvmstat.monitor.remote.*;
+import sun.jvmstat.perfdata.monitor.*;
+import java.util.*;
+import java.net.*;
+import java.io.*;
+import java.rmi.*;
+import java.util.HashMap;
+
+/**
+ * Concrete implementation of the MonitoredHost interface for the
+ * <em>rmi</em> protocol of the HotSpot PerfData monitoring implementation.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class MonitoredHostProvider extends MonitoredHost {
+    private static final String serverName = "/JStatRemoteHost";
+    private static final int DEFAULT_POLLING_INTERVAL = 1000;
+
+    private ArrayList<HostListener> listeners;
+    private NotifierTask task;
+    private HashSet<Integer> activeVms;
+    private RemoteVmManager vmManager;
+    private RemoteHost remoteHost;
+    private Timer timer;
+
+    /**
+     * Create a MonitoredHostProvider instance using the given HostIdentifier.
+     *
+     * @param hostId the host identifier for this MonitoredHost
+     * @throws MonitorException Thrown on any error encountered while
+     *                          communicating with the remote host.
+     */
+    public MonitoredHostProvider(HostIdentifier hostId)
+           throws MonitorException {
+        this.hostId = hostId;
+        this.listeners = new ArrayList<HostListener>();
+        this.interval = DEFAULT_POLLING_INTERVAL;
+        this.activeVms = new HashSet<Integer>();
+
+        String rmiName;
+        String sn = serverName;
+        String path = hostId.getPath();
+
+        if ((path != null) && (path.length() > 0)) {
+            sn = path;
+        }
+
+        if (hostId.getPort() != -1) {
+            rmiName = "rmi://" + hostId.getHost() + ":" + hostId.getPort() + sn;
+        } else {
+            rmiName = "rmi://" + hostId.getHost() + sn;
+        }
+
+        try {
+            remoteHost = (RemoteHost)Naming.lookup(rmiName);
+
+        } catch (RemoteException e) {
+            /*
+             * rmi registry not available
+             *
+             * Access control exceptions, where the rmi server refuses a
+             * connection based on policy file configuration, come through
+             * here on the client side. Unfortunately, the RemoteException
+             * doesn't contain enough information to determine the true cause
+             * of the exception. So, we have to output a rather generic message.
+             */
+            String message = "RMI Registry not available at "
+                             + hostId.getHost();
+
+            if (hostId.getPort() == -1) {
+                message = message + ":"
+                          + java.rmi.registry.Registry.REGISTRY_PORT;
+            } else {
+                message = message + ":" + hostId.getPort();
+            }
+
+            if (e.getMessage() != null) {
+                throw new MonitorException(message + "\n" + e.getMessage(), e);
+            } else {
+                throw new MonitorException(message, e);
+            }
+
+        } catch (NotBoundException e) {
+            // no server with given name
+            String message = e.getMessage();
+            if (message == null) message = rmiName;
+            throw new MonitorException("RMI Server " + message
+                                       + " not available", e);
+        } catch (MalformedURLException e) {
+            // this is a programming problem
+            e.printStackTrace();
+            throw new IllegalArgumentException("Malformed URL: " + rmiName);
+        }
+        this.vmManager = new RemoteVmManager(remoteHost);
+        this.timer = new Timer(true);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MonitoredVm getMonitoredVm(VmIdentifier vmid)
+                       throws MonitorException {
+        return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
+                       throws MonitorException {
+        VmIdentifier nvmid = null;
+        try {
+            nvmid = hostId.resolve(vmid);
+            RemoteVm rvm = remoteHost.attachVm(vmid.getLocalVmId(),
+                                               vmid.getMode());
+            RemoteMonitoredVm rmvm = new RemoteMonitoredVm(rvm, nvmid, timer,
+                                                           interval);
+            rmvm.attach();
+            return rmvm;
+
+        } catch (RemoteException e) {
+            throw new MonitorException("Remote Exception attaching to "
+                                       + nvmid.toString(), e);
+        } catch (URISyntaxException e) {
+            /*
+             * the VmIdentifier is expected to be a valid and should resolve
+             * easonably against the host identifier. A URISyntaxException
+             * here is most likely a programming error.
+             */
+            throw new IllegalArgumentException("Malformed URI: "
+                                               + vmid.toString(), e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void detach(MonitoredVm vm) throws MonitorException {
+        RemoteMonitoredVm rmvm = (RemoteMonitoredVm)vm;
+        rmvm.detach();
+        try {
+            remoteHost.detachVm(rmvm.getRemoteVm());
+
+        } catch (RemoteException e) {
+            throw new MonitorException("Remote Exception detaching from "
+                                       + vm.getVmIdentifier().toString(), e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addHostListener(HostListener listener) {
+        synchronized(listeners) {
+            listeners.add(listener);
+            if (task == null) {
+                task = new NotifierTask();
+                timer.schedule(task, 0, interval);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void removeHostListener(HostListener listener) {
+        /*
+         * XXX: if a disconnect method is added, make sure it calls
+         * this method to unregister this object from the watcher. otherwise,
+         * an unused MonitoredHostProvider instance may go uncollected.
+         */
+        synchronized(listeners) {
+            listeners.remove(listener);
+            if (listeners.isEmpty() && (task != null)) {
+                task.cancel();
+                task = null;
+            }
+        }
+    }
+
+    public void setInterval(int newInterval) {
+        synchronized(listeners) {
+            if (newInterval == interval) {
+                return;
+            }
+
+            int oldInterval = interval;
+            super.setInterval(newInterval);
+
+            if (task != null) {
+                task.cancel();
+                NotifierTask oldTask = task;
+                task = new NotifierTask();
+                CountedTimerTaskUtils.reschedule(timer, oldTask, task,
+                                                 oldInterval, newInterval);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Set<Integer> activeVms() throws MonitorException {
+        return vmManager.activeVms();
+    }
+
+    /**
+     * Fire VmStatusChangeEvent events to HostListener objects
+     *
+     * @param active Set of Integer objects containing the local
+     *               Vm Identifiers of the active JVMs
+     * @param started Set of Integer objects containing the local
+     *                Vm Identifiers of new JVMs started since last
+     *                interval.
+     * @param terminated Set of Integer objects containing the local
+     *                   Vm Identifiers of terminated JVMs since last
+     *                   interval.
+     */
+    @SuppressWarnings("unchecked") // Cast of result of clone
+    private void fireVmStatusChangedEvents(Set<Integer> active, Set<Integer> started,
+                                           Set<Integer> terminated) {
+        ArrayList<HostListener> registered = null;
+        VmStatusChangeEvent ev = null;
+
+        synchronized(listeners) {
+            registered = (ArrayList)listeners.clone();
+        }
+
+        for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) {
+            HostListener l = i.next();
+            if (ev == null) {
+                ev = new VmStatusChangeEvent(this, active, started, terminated);
+            }
+            l.vmStatusChanged(ev);
+        }
+    }
+
+    /**
+     * Fire hostDisconnectEvent events.
+     */
+    @SuppressWarnings("unchecked") // Cast of result of clone
+    void fireDisconnectedEvents() {
+        ArrayList<HostListener> registered = null;
+        HostEvent ev = null;
+
+        synchronized(listeners) {
+            registered = (ArrayList)listeners.clone();
+        }
+
+        for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) {
+            HostListener l = i.next();
+            if (ev == null) {
+                ev = new HostEvent(this);
+            }
+            l.disconnected(ev);
+        }
+    }
+
+    /**
+     * class to poll the remote machine and generate local event notifications.
+     */
+    private class NotifierTask extends CountedTimerTask {
+        public void run() {
+            super.run();
+
+            // save the last set of active JVMs
+            Set<Integer> lastActiveVms = activeVms;
+
+            try {
+                // get the current set of active JVMs
+                activeVms = (HashSet<Integer>)vmManager.activeVms();
+
+            } catch (MonitorException e) {
+                // XXX: use logging api
+                System.err.println("MonitoredHostProvider: polling task "
+                                   + "caught MonitorException:");
+                e.printStackTrace();
+
+                // mark the HostManager as errored and notify listeners
+                setLastException(e);
+                fireDisconnectedEvents();
+            }
+
+            if (activeVms.isEmpty()) {
+                return;
+            }
+
+            Set<Integer> startedVms = new HashSet<>();
+            Set<Integer> terminatedVms = new HashSet<>();
+
+            for (Iterator<Integer> i = activeVms.iterator(); i.hasNext(); /* empty */ ) {
+                Integer vmid = i.next();
+                if (!lastActiveVms.contains(vmid)) {
+                    // a new file has been detected, add to set
+                    startedVms.add(vmid);
+                }
+            }
+
+            for (Iterator<Integer> i = lastActiveVms.iterator(); i.hasNext();
+                    /* empty */ ) {
+                Integer o = i.next();
+                if (!activeVms.contains(o)) {
+                    // JVM has terminated, remove it from the active list
+                    terminatedVms.add(o);
+                }
+            }
+
+            if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) {
+                fireVmStatusChangedEvents(activeVms, startedVms, terminatedVms);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.jvmstat.perfdata.monitor.protocol.rmi;
+
+import sun.jvmstat.monitor.HostIdentifier;
+import sun.jvmstat.monitor.MonitorException;
+import sun.jvmstat.monitor.MonitoredHost;
+import sun.jvmstat.monitor.MonitoredHostService;
+
+public final class MonitoredHostRmiService implements MonitoredHostService {
+
+    @Override
+    public MonitoredHost getMonitoredHost(HostIdentifier hostId) throws MonitorException {
+        return new MonitoredHostProvider(hostId);
+    }
+
+    @Override
+    public String getScheme() {
+        return "rmi";
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jvmstat.perfdata.monitor.protocol.rmi;
+
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.remote.*;
+import sun.jvmstat.perfdata.monitor.*;
+import java.io.*;
+import java.rmi.RemoteException;
+import java.nio.ByteBuffer;
+
+/**
+ * The concrete PerfDataBuffer implementation for the <em>rmi:</em>
+ * protocol for the HotSpot PerfData monitoring implementation.
+ * <p>
+ * This class is responsible for acquiring the instrumentation buffer
+ * data for a remote target HotSpot Java Virtual Machine.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class PerfDataBuffer extends AbstractPerfDataBuffer {
+
+    private RemoteVm rvm;
+
+    /**
+     * Create a PerfDataBuffer instance for accessing the specified
+     * instrumentation buffer.
+     *
+     * @param rvm the proxy to the remote MonitredVm object
+     * @param lvmid the local Java Virtual Machine Identifier of the
+     *              remote target.
+     *
+     * @throws MonitorException
+     */
+    public PerfDataBuffer(RemoteVm rvm, int lvmid) throws MonitorException {
+
+        this.rvm = rvm;
+        try {
+            ByteBuffer buffer = ByteBuffer.allocate(rvm.getCapacity());
+            sample(buffer);
+            createPerfDataBuffer(buffer, lvmid);
+
+        } catch (RemoteException e) {
+            throw new MonitorException("Could not read data for remote JVM "
+                                       + lvmid, e);
+        }
+    }
+
+    /**
+     * Get a copy of the remote instrumentation buffer.
+     *<p>
+     * The data in the remote instrumentation buffer is copied into
+     * the local byte buffer.
+     *
+     * @param buffer the buffer to receive the copy of the remote
+     *               instrumentation buffer.
+     * @throws RemoteException Thrown on any communications errors with
+     *                         the remote system.
+     */
+    public void sample(ByteBuffer buffer) throws RemoteException {
+        assert buffer != null;
+        assert rvm != null;
+        synchronized(buffer) {
+            buffer.clear();
+            buffer.put(rvm.getBytes());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2004, 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.jvmstat.perfdata.monitor.protocol.rmi;
+
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.event.*;
+import sun.jvmstat.monitor.remote.*;
+import sun.jvmstat.perfdata.monitor.*;
+import java.lang.reflect.*;
+import java.util.*;
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.rmi.*;
+
+/**
+ * Concrete implementation of the AbstractMonitoredVm class for the
+ * <em>rmi:</em> protocol for the HotSpot PerfData monitoring implementation.
+ * <p>
+ * This class provides the ability to acquire to the instrumentation buffer
+ * of a live, remote target Java Virtual Machine through an RMI server.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class RemoteMonitoredVm extends AbstractMonitoredVm {
+
+    private ArrayList<VmListener> listeners;
+    private NotifierTask notifierTask;
+    private SamplerTask samplerTask;
+    private Timer timer;
+
+    private RemoteVm rvm;
+    private ByteBuffer updateBuffer;
+
+    /**
+     * Create a RemoteMonitoredVm instance.
+     *
+     * @param rvm the proxy to the remote MonitoredVm instance.
+     * @param vmid the vm identifier specifying the remot target JVM
+     * @param timer the timer used to run polling tasks
+     * @param interval the sampling interval
+     */
+    public RemoteMonitoredVm(RemoteVm rvm, VmIdentifier vmid,
+                             Timer timer, int interval)
+           throws MonitorException {
+        super(vmid, interval);
+        this.rvm = rvm;
+        pdb = new PerfDataBuffer(rvm, vmid.getLocalVmId());
+        this.listeners = new ArrayList<VmListener>();
+        this.timer = timer;
+    }
+
+    /**
+     * Method to attach to the remote MonitoredVm.
+     */
+    public void attach() throws MonitorException {
+        updateBuffer = pdb.getByteBuffer().duplicate();
+
+        // if continuous sampling is requested, register with the sampler thread
+        if (interval > 0) {
+            samplerTask = new SamplerTask();
+            timer.schedule(samplerTask, 0, interval);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void detach() {
+        try {
+            if (interval > 0) {
+                if (samplerTask != null) {
+                    samplerTask.cancel();
+                    samplerTask = null;
+                }
+                if (notifierTask != null) {
+                    notifierTask.cancel();
+                    notifierTask = null;
+                }
+                sample();
+            }
+        } catch (RemoteException e) {
+            // XXX: - use logging api? throw an exception instead?
+            System.err.println("Could not read data for remote JVM " + vmid);
+            e.printStackTrace();
+
+        } finally {
+            super.detach();
+        }
+    }
+
+    /**
+     * Get a copy of the remote instrumentation buffer.
+     *<p>
+     * The data in the remote instrumentation buffer is copied into
+     * a local byte buffer.
+     *
+     * @throws RemoteException Thrown on any communications errors with
+     *                         the remote system.
+     */
+    public void sample() throws RemoteException {
+        assert updateBuffer != null;
+        ((PerfDataBuffer)pdb).sample(updateBuffer);
+    }
+
+    /**
+     * Get the proxy to the remote MonitoredVm.
+     *
+     * @return RemoteVm - the proxy to the remote MonitoredVm.
+     */
+    public RemoteVm getRemoteVm() {
+        return rvm;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addVmListener(VmListener l) {
+        synchronized(listeners) {
+            listeners.add(l);
+            if (notifierTask == null) {
+                notifierTask = new NotifierTask();
+                timer.schedule(notifierTask, 0, interval);
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void removeVmListener(VmListener l) {
+        synchronized(listeners) {
+            listeners.remove(l);
+            if (listeners.isEmpty() && (notifierTask != null)) {
+                notifierTask.cancel();
+                notifierTask = null;
+            }
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void setInterval(int newInterval) {
+        synchronized(listeners) {
+            if (newInterval == interval) {
+                return;
+            }
+
+            int oldInterval = interval;
+            super.setInterval(newInterval);
+
+            if (samplerTask != null) {
+                samplerTask.cancel();
+                SamplerTask oldSamplerTask = samplerTask;
+                samplerTask = new SamplerTask();
+                CountedTimerTaskUtils.reschedule(timer, oldSamplerTask,
+                                                 samplerTask, oldInterval,
+                                                 newInterval);
+            }
+            if (notifierTask != null) {
+                notifierTask.cancel();
+                NotifierTask oldNotifierTask = notifierTask;
+                notifierTask = new NotifierTask();
+                CountedTimerTaskUtils.reschedule(timer, oldNotifierTask,
+                                                 notifierTask, oldInterval,
+                                                 newInterval);
+            }
+        }
+    }
+
+    /**
+     * Fire MonitoredVmStructureChanged events.
+     *
+     * @param inserted List of Monitor objects inserted.
+     * @param removed List of Monitor objects removed.
+     */
+    @SuppressWarnings("unchecked") // Cast of result of clone
+    void fireMonitorStatusChangedEvents(List<Monitor> inserted, List<Monitor> removed) {
+        ArrayList<VmListener> registered = null;
+        MonitorStatusChangeEvent ev = null;
+
+        synchronized(listeners) {
+            registered = (ArrayList)listeners.clone();
+        }
+
+        for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) {
+            VmListener l = i.next();
+            if (ev == null) {
+                ev = new MonitorStatusChangeEvent(this, inserted, removed);
+            }
+            l.monitorStatusChanged(ev);
+        }
+    }
+
+    /**
+     * Fire MonitoredVmStructureChanged events.
+     */
+    @SuppressWarnings("unchecked") // Cast of result of clone
+    void fireMonitorsUpdatedEvents() {
+        ArrayList<VmListener> registered = null;
+        VmEvent ev = null;
+
+        synchronized(listeners) {
+            registered = (ArrayList)listeners.clone();
+        }
+
+        for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) {
+            VmListener l = i.next();
+            if (ev == null) {
+                ev = new VmEvent(this);
+            }
+            l.monitorsUpdated(ev);
+        }
+    }
+
+    /*
+     * Timer Tasks. There are two separate timer tasks here. The SamplerTask
+     * is active whenever we are attached to the remote JVM with a periodic
+     * sampling interval > 0. The NotifierTask is only active if a VmListener
+     * has registered with this RemoteMonitoredVm instance. Also, in the future
+     * we may want to run these tasks at different intervals. Currently,
+     * they run at the same interval and some significant work may
+     * need to be done to complete the separation of these two intervals.
+     */
+
+    /**
+     * Class to periodically check the state of the defined monitors
+     * for the remote MonitoredVm instance and to notify listeners of
+     * any detected changes.
+     */
+    private class NotifierTask extends CountedTimerTask {
+        public void run() {
+            super.run();
+            try {
+                MonitorStatus status = getMonitorStatus();
+
+                List<Monitor> inserted = status.getInserted();
+                List<Monitor> removed = status.getRemoved();
+
+                if (!inserted.isEmpty() || !removed.isEmpty()) {
+                    fireMonitorStatusChangedEvents(inserted, removed);
+                }
+            } catch (MonitorException e) {
+                // XXX: use logging api? fire disconnect events? mark errored?
+                // fireDisconnectedEvents();
+                System.err.println("Exception updating monitors for "
+                                   + getVmIdentifier());
+                e.printStackTrace();
+                // XXX: should we cancle the notifierTask here?
+                // this.cancel();
+            }
+        }
+    }
+
+    /**
+     * Class to periodically sample the remote instrumentation byte buffer
+     * and refresh the local copy. Registered listeners are notified of
+     * the completion of a sampling event.
+     */
+    private class SamplerTask extends CountedTimerTask {
+        public void run() {
+            super.run();
+            try {
+                sample();
+                fireMonitorsUpdatedEvents();
+
+            } catch (RemoteException e) {
+                // XXX: use logging api, mark vm as errored.
+                System.err.println("Exception taking sample for "
+                                   + getVmIdentifier());
+                e.printStackTrace();
+                this.cancel();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.jvmstat.perfdata.monitor.protocol.rmi;
+
+import java.util.*;
+import java.util.regex.*;
+import java.io.*;
+import java.rmi.RemoteException;
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.event.*;
+import sun.jvmstat.monitor.remote.*;
+
+/**
+ * Class for managing the RemoteMonitoredVm instances on a remote system.
+ * <p>
+ * This class is responsible for the mechanism that detects the active
+ * HotSpot Java Virtual Machines on the remote host and possibly for a
+ * specific user. The ability to detect all possible HotSpot Java Virtual
+ * Machines on the remote host may be limited by the permissions of the
+ * principal running the RMI server application on the remote host.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class RemoteVmManager {
+
+    private RemoteHost remoteHost;
+    private String user;
+
+    /**
+     * Creates a RemoteVmManager instance for the remote system.
+     * <p>
+     * Manages RemoteMonitordVm instances for which the principal
+     * running the remote server has appropriate permissions.
+     *
+     * @param remoteHost the remote proxy object to the RMI server on
+     *                   the remote system.
+     */
+    public RemoteVmManager(RemoteHost remoteHost) {
+        this(remoteHost, null);
+    }
+
+    /**
+     * Creates a RemoteVmManager instance for the given user.
+     * <p>
+     * Manages RemoteMonitoredVm instances for all remote Java Virtual
+     * machines owned by the specified user on the remote system. The
+     * RMI server on the remote system must have the appropriate permissions
+     * to access the named users Java Virtual Machines.
+     *
+     * @param remoteHost the remote proxy object to the RMI server on
+     *                   the remote system.
+     * @param user the name of the user
+     */
+    public RemoteVmManager(RemoteHost remoteHost, String user) {
+        this.user = user;
+        this.remoteHost = remoteHost;
+    }
+
+    /**
+     * Return the current set of monitorable Java Virtual Machines.
+     * <p>
+     * The set returned by this method depends on the user name passed
+     * to the constructor. If no user name was specified, then this
+     * method will return all candidate JVMs on the system. Otherwise,
+     * only the JVMs for the given user will be returned. This assumes
+     * that the RMI server process has the appropriate permissions to
+     * access the target set of JVMs.
+     *
+     * @return Set - the Set of monitorable Java Virtual Machines
+     */
+    public Set<Integer> activeVms() throws MonitorException {
+        int[] active = null;
+
+        try {
+            active = remoteHost.activeVms();
+
+        } catch (RemoteException e) {
+            throw new MonitorException("Error communicating with remote host: "
+                                       + e.getMessage(), e);
+        }
+
+        Set<Integer> activeSet = new HashSet<Integer>(active.length);
+
+        for (int i = 0; i < active.length; i++) {
+            activeSet.add(active[i]);
+        }
+
+        return activeSet;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,47 @@
+<!doctype html public "-//IETF//DTD HTML/EN">
+<html>
+<head>
+<!--
+ 
+
+ Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+
+ This code is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 2 only, as
+ published by the Free Software Foundation.  Oracle designates this
+ particular file as subject to the "Classpath" exception as provided
+ by Oracle in the LICENSE file that accompanied this code.
+
+ This code is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ version 2 for more details (a copy is included in the LICENSE file that
+ accompanied this code).
+
+ You should have received a copy of the GNU General Public License version
+ 2 along with this work; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ or visit www.oracle.com if you need additional information or have any
+ questions.
+
+-->
+</head>
+<body bgcolor="white">
+<p>
+Provides the implementation classes for the <em>rmi:</em> protocol for
+the HotSpot PerfData instrumentation buffer monitoring implementation.
+</p>
+<p>
+The <em>rmi:</em> protocol is the default protocol for the PerfData
+implementation when a hostname is specified as part of a HostIdentifier
+or VMIdentifier. It communicates with an RMI server on the remote machine
+that provides functions to get a list of available Java Virtual Machines
+and to acquire a copy of a Java Virtual Machine's instrumentation buffer.
+The RMI server may or may not use the PerfData implementation on the
+remote host to acquire this information. The <em>jstatd</em> server
+provides a PerfData implementation of the RMI server.
+</body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/Jstatd.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jstatd;
+
+import java.rmi.*;
+import java.rmi.server.*;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.net.MalformedURLException;
+import sun.jvmstat.monitor.remote.*;
+
+/**
+ * Application providing remote access to the jvmstat instrumentation
+ * exported by local Java Virtual Machine processes. Remote access is
+ * provided through an RMI interface.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class Jstatd {
+
+    private static Registry registry;
+    private static int port = -1;
+    private static boolean startRegistry = true;
+
+    private static void printUsage() {
+        System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]");
+    }
+
+    static void bind(String name, RemoteHostImpl remoteHost)
+                throws RemoteException, MalformedURLException, Exception {
+
+        try {
+            Naming.rebind(name, remoteHost);
+        } catch (java.rmi.ConnectException e) {
+            /*
+             * either the registry is not running or we cannot contact it.
+             * start an internal registry if requested.
+             */
+            if (startRegistry && registry == null) {
+                int localport = (port < 0) ? Registry.REGISTRY_PORT : port;
+                registry = LocateRegistry.createRegistry(localport);
+                bind(name, remoteHost);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    @SuppressWarnings("deprecation") // Use of RMISecurityManager
+    public static void main(String[] args) {
+        String rminame = null;
+        int argc = 0;
+
+        for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) {
+            String arg = args[argc];
+
+            if (arg.compareTo("-nr") == 0) {
+                startRegistry = false;
+            } else if (arg.startsWith("-p")) {
+                if (arg.compareTo("-p") != 0) {
+                    port = Integer.parseInt(arg.substring(2));
+                } else {
+                  argc++;
+                  if (argc >= args.length) {
+                      printUsage();
+                      System.exit(1);
+                  }
+                  port = Integer.parseInt(args[argc]);
+                }
+            } else if (arg.startsWith("-n")) {
+                if (arg.compareTo("-n") != 0) {
+                    rminame = arg.substring(2);
+                } else {
+                    argc++;
+                    if (argc >= args.length) {
+                        printUsage();
+                        System.exit(1);
+                    }
+                    rminame = args[argc];
+                }
+            } else {
+                printUsage();
+                System.exit(1);
+            }
+        }
+
+        if (argc < args.length) {
+            printUsage();
+            System.exit(1);
+        }
+
+        if (System.getSecurityManager() == null) {
+            System.setSecurityManager(new RMISecurityManager());
+        }
+
+        StringBuilder name = new StringBuilder();
+
+        if (port >= 0) {
+            name.append("//:").append(port);
+        }
+
+        if (rminame == null) {
+            rminame = "JStatRemoteHost";
+        }
+
+        name.append("/").append(rminame);
+
+        try {
+            // use 1.5.0 dynamically generated subs.
+            System.setProperty("java.rmi.server.ignoreSubClasses", "true");
+            RemoteHostImpl remoteHost = new RemoteHostImpl();
+            RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject(
+                    remoteHost, 0);
+            bind(name.toString(), remoteHost);
+            System.out.println("jstatd started (bound to " + name.toString() + ")");
+            System.out.flush();
+        } catch (MalformedURLException e) {
+            if (rminame != null) {
+                System.out.println("Bad RMI server name: " + rminame);
+            } else {
+                System.out.println("Bad RMI URL: " + name);
+            }
+            e.printStackTrace(System.out);
+            System.exit(1);
+        } catch (java.rmi.ConnectException e) {
+            // could not attach to or create a registry
+            System.out.println("Could not contact RMI registry");
+            e.printStackTrace(System.out);
+            System.exit(1);
+        } catch (RemoteException e) {
+            System.out.println("Could not bind " + name + " to RMI Registry");
+            e.printStackTrace(System.out);
+            System.exit(1);
+        } catch (Exception e) {
+            System.out.println("Could not create remote object");
+            e.printStackTrace(System.out);
+            System.exit(1);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteHostImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jstatd;
+
+import java.util.*;
+import java.nio.*;
+import java.io.*;
+import java.net.*;
+import java.rmi.*;
+import java.rmi.server.*;
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.event.*;
+import sun.jvmstat.monitor.remote.*;
+
+/**
+ * Concrete implementation of the RemoteHost interface for the HotSpot
+ * PerfData <em>rmi:</em> protocol.
+ * <p>
+ * This class provides remote access to the instrumentation exported
+ * by HotSpot Java Virtual Machines through the PerfData shared memory
+ * interface.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class RemoteHostImpl implements RemoteHost, HostListener {
+
+    private MonitoredHost monitoredHost;
+    private Set<Integer> activeVms;
+
+    public RemoteHostImpl() throws MonitorException {
+        try {
+            monitoredHost = MonitoredHost.getMonitoredHost("localhost");
+        } catch (URISyntaxException e) { }
+
+        activeVms = monitoredHost.activeVms();
+        monitoredHost.addHostListener(this);
+    }
+
+    public RemoteVm attachVm(int lvmid, String mode)
+                    throws RemoteException, MonitorException {
+        Integer v = lvmid;
+        RemoteVm stub = null;
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("local://").append(lvmid).append("@localhost");
+        if (mode != null) {
+            sb.append("?mode=").append(mode);
+        }
+
+        String vmidStr = sb.toString();
+
+        try {
+            VmIdentifier vmid = new VmIdentifier(vmidStr);
+            MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid);
+            RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
+            stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0);
+        }
+        catch (URISyntaxException e) {
+            throw new RuntimeException("Malformed VmIdentifier URI: "
+                                       + vmidStr, e);
+        }
+        return stub;
+    }
+
+    public void detachVm(RemoteVm rvm) throws RemoteException {
+        rvm.detach();
+    }
+
+    public int[] activeVms() throws MonitorException {
+        Object[] vms = null;
+        int[] vmids = null;
+
+        vms = monitoredHost.activeVms().toArray();
+        vmids = new int[vms.length];
+
+        for (int i = 0; i < vmids.length; i++) {
+            vmids[i] = ((Integer)vms[i]).intValue();
+        }
+        return vmids;
+    }
+
+    public void vmStatusChanged(VmStatusChangeEvent ev) {
+        synchronized(this.activeVms) {
+            activeVms.retainAll(ev.getActive());
+        }
+    }
+
+    public void disconnected(HostEvent ev) {
+        // we only monitor the local host, so this event shouldn't occur.
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jstatd/share/classes/sun/tools/jstatd/RemoteVmImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.jstatd;
+
+import sun.jvmstat.monitor.*;
+import sun.jvmstat.monitor.remote.*;
+
+/**
+ * Concrete implementation of the RemoteVm interface for the HotSpot PerfData
+ * shared memory implementation of the jvmstat monitoring APIs. This class
+ * providing remote access to the instrumentation exported by a local HotSpot
+ * Java Virtual Machine. The instrumentation buffer is shipped in whole to
+ * the remote machine, which is responsible for parsing and provide access
+ * to the contained data.
+ *
+ * @author Brian Doherty
+ * @since 1.5
+ */
+public class RemoteVmImpl implements RemoteVm {
+
+    private BufferedMonitoredVm mvm;
+
+    RemoteVmImpl(BufferedMonitoredVm mvm) {
+        this.mvm = mvm;
+    }
+
+    public byte[] getBytes() {
+        return mvm.getBytes();
+    }
+
+    public int getCapacity() {
+        return mvm.getCapacity();
+    }
+
+    public void detach() {
+        mvm.detach();
+    }
+
+    public int getLocalVmId() {
+        return mvm.getVmIdentifier().getLocalVmId();
+    }
+}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/module-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +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.
- */
-
-module jdk.jvmstat.rmi {
-    requires java.rmi;
-    requires jdk.jvmstat;
-
-    // RMI needs to serialize types in this package
-    exports sun.jvmstat.monitor.remote to java.rmi;
-
-    provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.rmi.MonitoredHostRmiService;
-}
-
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteHost.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.jvmstat.monitor.remote;
-
-import sun.jvmstat.monitor.*;
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-import java.io.IOException;
-
-/**
- * Remote Interface for discovering and attaching to remote
- * monitorable Java Virtual Machines.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public interface RemoteHost extends Remote {
-
-    /**
-     * Remote method to attach to a remote HotSpot Java Virtual Machine
-     * identified by <code>vmid</code>.
-     *
-     * @param vmid The identifier for the target virtual machine.
-     * @return RemoteVm - A remote object for accessing the remote Java
-     *                    Virtual Machine.
-     *
-     * @throws MonitorException Thrown when any other error is encountered
-     *                          while communicating with the target virtual
-     *                          machine.
-     * @throws RemoteException
-     *
-     */
-    RemoteVm attachVm(int vmid, String mode) throws RemoteException,
-                                                    MonitorException;
-
-    /**
-     * Remote method to detach from a remote HotSpot Java Virtual Machine
-     * identified by <code>vmid</code>.
-     *
-     * @param rvm The remote object for the target Java Virtual
-     *            Machine.
-     *
-     * @throws MonitorException Thrown when any other error is encountered
-     *                          while communicating with the target virtual
-     *                          machine.
-     * @throws RemoteException
-     */
-    void detachVm(RemoteVm rvm) throws RemoteException, MonitorException;
-
-    /**
-     * Get a list of Local Virtual Machine Identifiers for the active
-     * Java Virtual Machine the remote system. A Local Virtual Machine
-     * Identifier is also known as an <em>lvmid</em>.
-     *
-     * @return int[] - A array of <em>lvmid</em>s.
-     * @throws MonitorException Thrown when any other error is encountered
-     *                          while communicating with the target virtual
-     *                          machine.
-     * @throws RemoteException
-     */
-    int[] activeVms() throws RemoteException, MonitorException;
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/RemoteVm.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.jvmstat.monitor.remote;
-
-import java.rmi.Remote;
-import java.rmi.RemoteException;
-
-/**
- * Interface for accessing the instrumentation exported by a
- * Java Virtual Machine running on a remote host.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public interface RemoteVm extends Remote {
-
-    /**
-     * Interface to get the bytes associated with the instrumentation
-     * for the remote Java Virtual Machine.
-     *
-     * @return byte[] - a byte array containing the current bytes
-     *                  for the instrumentation exported by the
-     *                  remote Java Virtual Machine.
-     * @throws RemoteException Thrown on any communication error
-     */
-    byte[] getBytes() throws RemoteException;
-
-    /**
-     * Interface to get the size of the instrumentation buffer
-     * for the target Java Virtual Machine.
-     *
-     * @return int - the size of the instrumentation buffer for the
-     *               remote Java Virtual Machine.
-     * @throws RemoteException Thrown on any communication error
-     */
-    int getCapacity() throws RemoteException;
-
-    /**
-     * Interface to return the Local Virtual Machine Identifier for
-     * the remote Java Virtual Machine. The Local Virtual Machine
-     * Identifier is also know as the <em>lvmid</em>.
-     *
-     * @throws RemoteException Thrown on any communication error
-     */
-    int getLocalVmId() throws RemoteException;
-
-    /**
-     * Interface to detach from the remote Java Virtual Machine.
-     *
-     * @throws RemoteException Thrown on any communication error
-     */
-    void detach() throws RemoteException;
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/monitor/remote/package.html	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +0,0 @@
-<!doctype html public "-//IETF//DTD HTML/EN">
-<html>
-<head>
-<!--
- 
-
- Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.  Oracle designates this
- particular file as subject to the "Classpath" exception as provided
- by Oracle in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
-
-
--->
-</head>
-<body bgcolor="white">
-<p>
-Provides interfaces supporting remote monitoring for instrumented
-HotSpot Java Virtual Machines.
-</p>
-</body>
-</html>
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostProvider.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2004, 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.jvmstat.perfdata.monitor.protocol.rmi;
-
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.event.*;
-import sun.jvmstat.monitor.remote.*;
-import sun.jvmstat.perfdata.monitor.*;
-import java.util.*;
-import java.net.*;
-import java.io.*;
-import java.rmi.*;
-import java.util.HashMap;
-
-/**
- * Concrete implementation of the MonitoredHost interface for the
- * <em>rmi</em> protocol of the HotSpot PerfData monitoring implementation.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class MonitoredHostProvider extends MonitoredHost {
-    private static final String serverName = "/JStatRemoteHost";
-    private static final int DEFAULT_POLLING_INTERVAL = 1000;
-
-    private ArrayList<HostListener> listeners;
-    private NotifierTask task;
-    private HashSet<Integer> activeVms;
-    private RemoteVmManager vmManager;
-    private RemoteHost remoteHost;
-    private Timer timer;
-
-    /**
-     * Create a MonitoredHostProvider instance using the given HostIdentifier.
-     *
-     * @param hostId the host identifier for this MonitoredHost
-     * @throws MonitorException Thrown on any error encountered while
-     *                          communicating with the remote host.
-     */
-    public MonitoredHostProvider(HostIdentifier hostId)
-           throws MonitorException {
-        this.hostId = hostId;
-        this.listeners = new ArrayList<HostListener>();
-        this.interval = DEFAULT_POLLING_INTERVAL;
-        this.activeVms = new HashSet<Integer>();
-
-        String rmiName;
-        String sn = serverName;
-        String path = hostId.getPath();
-
-        if ((path != null) && (path.length() > 0)) {
-            sn = path;
-        }
-
-        if (hostId.getPort() != -1) {
-            rmiName = "rmi://" + hostId.getHost() + ":" + hostId.getPort() + sn;
-        } else {
-            rmiName = "rmi://" + hostId.getHost() + sn;
-        }
-
-        try {
-            remoteHost = (RemoteHost)Naming.lookup(rmiName);
-
-        } catch (RemoteException e) {
-            /*
-             * rmi registry not available
-             *
-             * Access control exceptions, where the rmi server refuses a
-             * connection based on policy file configuration, come through
-             * here on the client side. Unfortunately, the RemoteException
-             * doesn't contain enough information to determine the true cause
-             * of the exception. So, we have to output a rather generic message.
-             */
-            String message = "RMI Registry not available at "
-                             + hostId.getHost();
-
-            if (hostId.getPort() == -1) {
-                message = message + ":"
-                          + java.rmi.registry.Registry.REGISTRY_PORT;
-            } else {
-                message = message + ":" + hostId.getPort();
-            }
-
-            if (e.getMessage() != null) {
-                throw new MonitorException(message + "\n" + e.getMessage(), e);
-            } else {
-                throw new MonitorException(message, e);
-            }
-
-        } catch (NotBoundException e) {
-            // no server with given name
-            String message = e.getMessage();
-            if (message == null) message = rmiName;
-            throw new MonitorException("RMI Server " + message
-                                       + " not available", e);
-        } catch (MalformedURLException e) {
-            // this is a programming problem
-            e.printStackTrace();
-            throw new IllegalArgumentException("Malformed URL: " + rmiName);
-        }
-        this.vmManager = new RemoteVmManager(remoteHost);
-        this.timer = new Timer(true);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public MonitoredVm getMonitoredVm(VmIdentifier vmid)
-                       throws MonitorException {
-        return getMonitoredVm(vmid, DEFAULT_POLLING_INTERVAL);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public MonitoredVm getMonitoredVm(VmIdentifier vmid, int interval)
-                       throws MonitorException {
-        VmIdentifier nvmid = null;
-        try {
-            nvmid = hostId.resolve(vmid);
-            RemoteVm rvm = remoteHost.attachVm(vmid.getLocalVmId(),
-                                               vmid.getMode());
-            RemoteMonitoredVm rmvm = new RemoteMonitoredVm(rvm, nvmid, timer,
-                                                           interval);
-            rmvm.attach();
-            return rmvm;
-
-        } catch (RemoteException e) {
-            throw new MonitorException("Remote Exception attaching to "
-                                       + nvmid.toString(), e);
-        } catch (URISyntaxException e) {
-            /*
-             * the VmIdentifier is expected to be a valid and should resolve
-             * easonably against the host identifier. A URISyntaxException
-             * here is most likely a programming error.
-             */
-            throw new IllegalArgumentException("Malformed URI: "
-                                               + vmid.toString(), e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void detach(MonitoredVm vm) throws MonitorException {
-        RemoteMonitoredVm rmvm = (RemoteMonitoredVm)vm;
-        rmvm.detach();
-        try {
-            remoteHost.detachVm(rmvm.getRemoteVm());
-
-        } catch (RemoteException e) {
-            throw new MonitorException("Remote Exception detaching from "
-                                       + vm.getVmIdentifier().toString(), e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addHostListener(HostListener listener) {
-        synchronized(listeners) {
-            listeners.add(listener);
-            if (task == null) {
-                task = new NotifierTask();
-                timer.schedule(task, 0, interval);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void removeHostListener(HostListener listener) {
-        /*
-         * XXX: if a disconnect method is added, make sure it calls
-         * this method to unregister this object from the watcher. otherwise,
-         * an unused MonitoredHostProvider instance may go uncollected.
-         */
-        synchronized(listeners) {
-            listeners.remove(listener);
-            if (listeners.isEmpty() && (task != null)) {
-                task.cancel();
-                task = null;
-            }
-        }
-    }
-
-    public void setInterval(int newInterval) {
-        synchronized(listeners) {
-            if (newInterval == interval) {
-                return;
-            }
-
-            int oldInterval = interval;
-            super.setInterval(newInterval);
-
-            if (task != null) {
-                task.cancel();
-                NotifierTask oldTask = task;
-                task = new NotifierTask();
-                CountedTimerTaskUtils.reschedule(timer, oldTask, task,
-                                                 oldInterval, newInterval);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public Set<Integer> activeVms() throws MonitorException {
-        return vmManager.activeVms();
-    }
-
-    /**
-     * Fire VmStatusChangeEvent events to HostListener objects
-     *
-     * @param active Set of Integer objects containing the local
-     *               Vm Identifiers of the active JVMs
-     * @param started Set of Integer objects containing the local
-     *                Vm Identifiers of new JVMs started since last
-     *                interval.
-     * @param terminated Set of Integer objects containing the local
-     *                   Vm Identifiers of terminated JVMs since last
-     *                   interval.
-     */
-    @SuppressWarnings("unchecked") // Cast of result of clone
-    private void fireVmStatusChangedEvents(Set<Integer> active, Set<Integer> started,
-                                           Set<Integer> terminated) {
-        ArrayList<HostListener> registered = null;
-        VmStatusChangeEvent ev = null;
-
-        synchronized(listeners) {
-            registered = (ArrayList)listeners.clone();
-        }
-
-        for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) {
-            HostListener l = i.next();
-            if (ev == null) {
-                ev = new VmStatusChangeEvent(this, active, started, terminated);
-            }
-            l.vmStatusChanged(ev);
-        }
-    }
-
-    /**
-     * Fire hostDisconnectEvent events.
-     */
-    @SuppressWarnings("unchecked") // Cast of result of clone
-    void fireDisconnectedEvents() {
-        ArrayList<HostListener> registered = null;
-        HostEvent ev = null;
-
-        synchronized(listeners) {
-            registered = (ArrayList)listeners.clone();
-        }
-
-        for (Iterator<HostListener> i = registered.iterator(); i.hasNext(); /* empty */) {
-            HostListener l = i.next();
-            if (ev == null) {
-                ev = new HostEvent(this);
-            }
-            l.disconnected(ev);
-        }
-    }
-
-    /**
-     * class to poll the remote machine and generate local event notifications.
-     */
-    private class NotifierTask extends CountedTimerTask {
-        public void run() {
-            super.run();
-
-            // save the last set of active JVMs
-            Set<Integer> lastActiveVms = activeVms;
-
-            try {
-                // get the current set of active JVMs
-                activeVms = (HashSet<Integer>)vmManager.activeVms();
-
-            } catch (MonitorException e) {
-                // XXX: use logging api
-                System.err.println("MonitoredHostProvider: polling task "
-                                   + "caught MonitorException:");
-                e.printStackTrace();
-
-                // mark the HostManager as errored and notify listeners
-                setLastException(e);
-                fireDisconnectedEvents();
-            }
-
-            if (activeVms.isEmpty()) {
-                return;
-            }
-
-            Set<Integer> startedVms = new HashSet<>();
-            Set<Integer> terminatedVms = new HashSet<>();
-
-            for (Iterator<Integer> i = activeVms.iterator(); i.hasNext(); /* empty */ ) {
-                Integer vmid = i.next();
-                if (!lastActiveVms.contains(vmid)) {
-                    // a new file has been detected, add to set
-                    startedVms.add(vmid);
-                }
-            }
-
-            for (Iterator<Integer> i = lastActiveVms.iterator(); i.hasNext();
-                    /* empty */ ) {
-                Integer o = i.next();
-                if (!activeVms.contains(o)) {
-                    // JVM has terminated, remove it from the active list
-                    terminatedVms.add(o);
-                }
-            }
-
-            if (!startedVms.isEmpty() || !terminatedVms.isEmpty()) {
-                fireVmStatusChangedEvents(activeVms, startedVms, terminatedVms);
-            }
-        }
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/MonitoredHostRmiService.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.jvmstat.perfdata.monitor.protocol.rmi;
-
-import sun.jvmstat.monitor.HostIdentifier;
-import sun.jvmstat.monitor.MonitorException;
-import sun.jvmstat.monitor.MonitoredHost;
-import sun.jvmstat.monitor.MonitoredHostService;
-
-public final class MonitoredHostRmiService implements MonitoredHostService {
-
-    @Override
-    public MonitoredHost getMonitoredHost(HostIdentifier hostId) throws MonitorException {
-        return new MonitoredHostProvider(hostId);
-    }
-
-    @Override
-    public String getScheme() {
-        return "rmi";
-    }
-
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/PerfDataBuffer.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.jvmstat.perfdata.monitor.protocol.rmi;
-
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.remote.*;
-import sun.jvmstat.perfdata.monitor.*;
-import java.io.*;
-import java.rmi.RemoteException;
-import java.nio.ByteBuffer;
-
-/**
- * The concrete PerfDataBuffer implementation for the <em>rmi:</em>
- * protocol for the HotSpot PerfData monitoring implementation.
- * <p>
- * This class is responsible for acquiring the instrumentation buffer
- * data for a remote target HotSpot Java Virtual Machine.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class PerfDataBuffer extends AbstractPerfDataBuffer {
-
-    private RemoteVm rvm;
-
-    /**
-     * Create a PerfDataBuffer instance for accessing the specified
-     * instrumentation buffer.
-     *
-     * @param rvm the proxy to the remote MonitredVm object
-     * @param lvmid the local Java Virtual Machine Identifier of the
-     *              remote target.
-     *
-     * @throws MonitorException
-     */
-    public PerfDataBuffer(RemoteVm rvm, int lvmid) throws MonitorException {
-
-        this.rvm = rvm;
-        try {
-            ByteBuffer buffer = ByteBuffer.allocate(rvm.getCapacity());
-            sample(buffer);
-            createPerfDataBuffer(buffer, lvmid);
-
-        } catch (RemoteException e) {
-            throw new MonitorException("Could not read data for remote JVM "
-                                       + lvmid, e);
-        }
-    }
-
-    /**
-     * Get a copy of the remote instrumentation buffer.
-     *<p>
-     * The data in the remote instrumentation buffer is copied into
-     * the local byte buffer.
-     *
-     * @param buffer the buffer to receive the copy of the remote
-     *               instrumentation buffer.
-     * @throws RemoteException Thrown on any communications errors with
-     *                         the remote system.
-     */
-    public void sample(ByteBuffer buffer) throws RemoteException {
-        assert buffer != null;
-        assert rvm != null;
-        synchronized(buffer) {
-            buffer.clear();
-            buffer.put(rvm.getBytes());
-        }
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteMonitoredVm.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,300 +0,0 @@
-/*
- * Copyright (c) 2004, 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.jvmstat.perfdata.monitor.protocol.rmi;
-
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.event.*;
-import sun.jvmstat.monitor.remote.*;
-import sun.jvmstat.perfdata.monitor.*;
-import java.lang.reflect.*;
-import java.util.*;
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.rmi.*;
-
-/**
- * Concrete implementation of the AbstractMonitoredVm class for the
- * <em>rmi:</em> protocol for the HotSpot PerfData monitoring implementation.
- * <p>
- * This class provides the ability to acquire to the instrumentation buffer
- * of a live, remote target Java Virtual Machine through an RMI server.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class RemoteMonitoredVm extends AbstractMonitoredVm {
-
-    private ArrayList<VmListener> listeners;
-    private NotifierTask notifierTask;
-    private SamplerTask samplerTask;
-    private Timer timer;
-
-    private RemoteVm rvm;
-    private ByteBuffer updateBuffer;
-
-    /**
-     * Create a RemoteMonitoredVm instance.
-     *
-     * @param rvm the proxy to the remote MonitoredVm instance.
-     * @param vmid the vm identifier specifying the remot target JVM
-     * @param timer the timer used to run polling tasks
-     * @param interval the sampling interval
-     */
-    public RemoteMonitoredVm(RemoteVm rvm, VmIdentifier vmid,
-                             Timer timer, int interval)
-           throws MonitorException {
-        super(vmid, interval);
-        this.rvm = rvm;
-        pdb = new PerfDataBuffer(rvm, vmid.getLocalVmId());
-        this.listeners = new ArrayList<VmListener>();
-        this.timer = timer;
-    }
-
-    /**
-     * Method to attach to the remote MonitoredVm.
-     */
-    public void attach() throws MonitorException {
-        updateBuffer = pdb.getByteBuffer().duplicate();
-
-        // if continuous sampling is requested, register with the sampler thread
-        if (interval > 0) {
-            samplerTask = new SamplerTask();
-            timer.schedule(samplerTask, 0, interval);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void detach() {
-        try {
-            if (interval > 0) {
-                if (samplerTask != null) {
-                    samplerTask.cancel();
-                    samplerTask = null;
-                }
-                if (notifierTask != null) {
-                    notifierTask.cancel();
-                    notifierTask = null;
-                }
-                sample();
-            }
-        } catch (RemoteException e) {
-            // XXX: - use logging api? throw an exception instead?
-            System.err.println("Could not read data for remote JVM " + vmid);
-            e.printStackTrace();
-
-        } finally {
-            super.detach();
-        }
-    }
-
-    /**
-     * Get a copy of the remote instrumentation buffer.
-     *<p>
-     * The data in the remote instrumentation buffer is copied into
-     * a local byte buffer.
-     *
-     * @throws RemoteException Thrown on any communications errors with
-     *                         the remote system.
-     */
-    public void sample() throws RemoteException {
-        assert updateBuffer != null;
-        ((PerfDataBuffer)pdb).sample(updateBuffer);
-    }
-
-    /**
-     * Get the proxy to the remote MonitoredVm.
-     *
-     * @return RemoteVm - the proxy to the remote MonitoredVm.
-     */
-    public RemoteVm getRemoteVm() {
-        return rvm;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void addVmListener(VmListener l) {
-        synchronized(listeners) {
-            listeners.add(l);
-            if (notifierTask == null) {
-                notifierTask = new NotifierTask();
-                timer.schedule(notifierTask, 0, interval);
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void removeVmListener(VmListener l) {
-        synchronized(listeners) {
-            listeners.remove(l);
-            if (listeners.isEmpty() && (notifierTask != null)) {
-                notifierTask.cancel();
-                notifierTask = null;
-            }
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setInterval(int newInterval) {
-        synchronized(listeners) {
-            if (newInterval == interval) {
-                return;
-            }
-
-            int oldInterval = interval;
-            super.setInterval(newInterval);
-
-            if (samplerTask != null) {
-                samplerTask.cancel();
-                SamplerTask oldSamplerTask = samplerTask;
-                samplerTask = new SamplerTask();
-                CountedTimerTaskUtils.reschedule(timer, oldSamplerTask,
-                                                 samplerTask, oldInterval,
-                                                 newInterval);
-            }
-            if (notifierTask != null) {
-                notifierTask.cancel();
-                NotifierTask oldNotifierTask = notifierTask;
-                notifierTask = new NotifierTask();
-                CountedTimerTaskUtils.reschedule(timer, oldNotifierTask,
-                                                 notifierTask, oldInterval,
-                                                 newInterval);
-            }
-        }
-    }
-
-    /**
-     * Fire MonitoredVmStructureChanged events.
-     *
-     * @param inserted List of Monitor objects inserted.
-     * @param removed List of Monitor objects removed.
-     */
-    @SuppressWarnings("unchecked") // Cast of result of clone
-    void fireMonitorStatusChangedEvents(List<Monitor> inserted, List<Monitor> removed) {
-        ArrayList<VmListener> registered = null;
-        MonitorStatusChangeEvent ev = null;
-
-        synchronized(listeners) {
-            registered = (ArrayList)listeners.clone();
-        }
-
-        for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) {
-            VmListener l = i.next();
-            if (ev == null) {
-                ev = new MonitorStatusChangeEvent(this, inserted, removed);
-            }
-            l.monitorStatusChanged(ev);
-        }
-    }
-
-    /**
-     * Fire MonitoredVmStructureChanged events.
-     */
-    @SuppressWarnings("unchecked") // Cast of result of clone
-    void fireMonitorsUpdatedEvents() {
-        ArrayList<VmListener> registered = null;
-        VmEvent ev = null;
-
-        synchronized(listeners) {
-            registered = (ArrayList)listeners.clone();
-        }
-
-        for (Iterator<VmListener> i = registered.iterator(); i.hasNext(); /* empty */) {
-            VmListener l = i.next();
-            if (ev == null) {
-                ev = new VmEvent(this);
-            }
-            l.monitorsUpdated(ev);
-        }
-    }
-
-    /*
-     * Timer Tasks. There are two separate timer tasks here. The SamplerTask
-     * is active whenever we are attached to the remote JVM with a periodic
-     * sampling interval > 0. The NotifierTask is only active if a VmListener
-     * has registered with this RemoteMonitoredVm instance. Also, in the future
-     * we may want to run these tasks at different intervals. Currently,
-     * they run at the same interval and some significant work may
-     * need to be done to complete the separation of these two intervals.
-     */
-
-    /**
-     * Class to periodically check the state of the defined monitors
-     * for the remote MonitoredVm instance and to notify listeners of
-     * any detected changes.
-     */
-    private class NotifierTask extends CountedTimerTask {
-        public void run() {
-            super.run();
-            try {
-                MonitorStatus status = getMonitorStatus();
-
-                List<Monitor> inserted = status.getInserted();
-                List<Monitor> removed = status.getRemoved();
-
-                if (!inserted.isEmpty() || !removed.isEmpty()) {
-                    fireMonitorStatusChangedEvents(inserted, removed);
-                }
-            } catch (MonitorException e) {
-                // XXX: use logging api? fire disconnect events? mark errored?
-                // fireDisconnectedEvents();
-                System.err.println("Exception updating monitors for "
-                                   + getVmIdentifier());
-                e.printStackTrace();
-                // XXX: should we cancle the notifierTask here?
-                // this.cancel();
-            }
-        }
-    }
-
-    /**
-     * Class to periodically sample the remote instrumentation byte buffer
-     * and refresh the local copy. Registered listeners are notified of
-     * the completion of a sampling event.
-     */
-    private class SamplerTask extends CountedTimerTask {
-        public void run() {
-            super.run();
-            try {
-                sample();
-                fireMonitorsUpdatedEvents();
-
-            } catch (RemoteException e) {
-                // XXX: use logging api, mark vm as errored.
-                System.err.println("Exception taking sample for "
-                                   + getVmIdentifier());
-                e.printStackTrace();
-                this.cancel();
-            }
-        }
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/RemoteVmManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact 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.jvmstat.perfdata.monitor.protocol.rmi;
-
-import java.util.*;
-import java.util.regex.*;
-import java.io.*;
-import java.rmi.RemoteException;
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.event.*;
-import sun.jvmstat.monitor.remote.*;
-
-/**
- * Class for managing the RemoteMonitoredVm instances on a remote system.
- * <p>
- * This class is responsible for the mechanism that detects the active
- * HotSpot Java Virtual Machines on the remote host and possibly for a
- * specific user. The ability to detect all possible HotSpot Java Virtual
- * Machines on the remote host may be limited by the permissions of the
- * principal running the RMI server application on the remote host.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class RemoteVmManager {
-
-    private RemoteHost remoteHost;
-    private String user;
-
-    /**
-     * Creates a RemoteVmManager instance for the remote system.
-     * <p>
-     * Manages RemoteMonitordVm instances for which the principal
-     * running the remote server has appropriate permissions.
-     *
-     * @param remoteHost the remote proxy object to the RMI server on
-     *                   the remote system.
-     */
-    public RemoteVmManager(RemoteHost remoteHost) {
-        this(remoteHost, null);
-    }
-
-    /**
-     * Creates a RemoteVmManager instance for the given user.
-     * <p>
-     * Manages RemoteMonitoredVm instances for all remote Java Virtual
-     * machines owned by the specified user on the remote system. The
-     * RMI server on the remote system must have the appropriate permissions
-     * to access the named users Java Virtual Machines.
-     *
-     * @param remoteHost the remote proxy object to the RMI server on
-     *                   the remote system.
-     * @param user the name of the user
-     */
-    public RemoteVmManager(RemoteHost remoteHost, String user) {
-        this.user = user;
-        this.remoteHost = remoteHost;
-    }
-
-    /**
-     * Return the current set of monitorable Java Virtual Machines.
-     * <p>
-     * The set returned by this method depends on the user name passed
-     * to the constructor. If no user name was specified, then this
-     * method will return all candidate JVMs on the system. Otherwise,
-     * only the JVMs for the given user will be returned. This assumes
-     * that the RMI server process has the appropriate permissions to
-     * access the target set of JVMs.
-     *
-     * @return Set - the Set of monitorable Java Virtual Machines
-     */
-    public Set<Integer> activeVms() throws MonitorException {
-        int[] active = null;
-
-        try {
-            active = remoteHost.activeVms();
-
-        } catch (RemoteException e) {
-            throw new MonitorException("Error communicating with remote host: "
-                                       + e.getMessage(), e);
-        }
-
-        Set<Integer> activeSet = new HashSet<Integer>(active.length);
-
-        for (int i = 0; i < active.length; i++) {
-            activeSet.add(active[i]);
-        }
-
-        return activeSet;
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/jvmstat/perfdata/monitor/protocol/rmi/package.html	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-<!doctype html public "-//IETF//DTD HTML/EN">
-<html>
-<head>
-<!--
- 
-
- Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-
- This code is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License version 2 only, as
- published by the Free Software Foundation.  Oracle designates this
- particular file as subject to the "Classpath" exception as provided
- by Oracle in the LICENSE file that accompanied this code.
-
- This code is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- version 2 for more details (a copy is included in the LICENSE file that
- accompanied this code).
-
- You should have received a copy of the GNU General Public License version
- 2 along with this work; if not, write to the Free Software Foundation,
- Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
-
- Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- or visit www.oracle.com if you need additional information or have any
- questions.
-
--->
-</head>
-<body bgcolor="white">
-<p>
-Provides the implementation classes for the <em>rmi:</em> protocol for
-the HotSpot PerfData instrumentation buffer monitoring implementation.
-</p>
-<p>
-The <em>rmi:</em> protocol is the default protocol for the PerfData
-implementation when a hostname is specified as part of a HostIdentifier
-or VMIdentifier. It communicates with an RMI server on the remote machine
-that provides functions to get a list of available Java Virtual Machines
-and to acquire a copy of a Java Virtual Machine's instrumentation buffer.
-The RMI server may or may not use the PerfData implementation on the
-remote host to acquire this information. The <em>jstatd</em> server
-provides a PerfData implementation of the RMI server.
-</body>
-</html>
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/Jstatd.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jstatd;
-
-import java.rmi.*;
-import java.rmi.server.*;
-import java.rmi.registry.Registry;
-import java.rmi.registry.LocateRegistry;
-import java.net.MalformedURLException;
-import sun.jvmstat.monitor.remote.*;
-
-/**
- * Application providing remote access to the jvmstat instrumentation
- * exported by local Java Virtual Machine processes. Remote access is
- * provided through an RMI interface.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class Jstatd {
-
-    private static Registry registry;
-    private static int port = -1;
-    private static boolean startRegistry = true;
-
-    private static void printUsage() {
-        System.err.println("usage: jstatd [-nr] [-p port] [-n rminame]");
-    }
-
-    static void bind(String name, RemoteHostImpl remoteHost)
-                throws RemoteException, MalformedURLException, Exception {
-
-        try {
-            Naming.rebind(name, remoteHost);
-        } catch (java.rmi.ConnectException e) {
-            /*
-             * either the registry is not running or we cannot contact it.
-             * start an internal registry if requested.
-             */
-            if (startRegistry && registry == null) {
-                int localport = (port < 0) ? Registry.REGISTRY_PORT : port;
-                registry = LocateRegistry.createRegistry(localport);
-                bind(name, remoteHost);
-            } else {
-                throw e;
-            }
-        }
-    }
-
-    @SuppressWarnings("deprecation") // Use of RMISecurityManager
-    public static void main(String[] args) {
-        String rminame = null;
-        int argc = 0;
-
-        for ( ; (argc < args.length) && (args[argc].startsWith("-")); argc++) {
-            String arg = args[argc];
-
-            if (arg.compareTo("-nr") == 0) {
-                startRegistry = false;
-            } else if (arg.startsWith("-p")) {
-                if (arg.compareTo("-p") != 0) {
-                    port = Integer.parseInt(arg.substring(2));
-                } else {
-                  argc++;
-                  if (argc >= args.length) {
-                      printUsage();
-                      System.exit(1);
-                  }
-                  port = Integer.parseInt(args[argc]);
-                }
-            } else if (arg.startsWith("-n")) {
-                if (arg.compareTo("-n") != 0) {
-                    rminame = arg.substring(2);
-                } else {
-                    argc++;
-                    if (argc >= args.length) {
-                        printUsage();
-                        System.exit(1);
-                    }
-                    rminame = args[argc];
-                }
-            } else {
-                printUsage();
-                System.exit(1);
-            }
-        }
-
-        if (argc < args.length) {
-            printUsage();
-            System.exit(1);
-        }
-
-        if (System.getSecurityManager() == null) {
-            System.setSecurityManager(new RMISecurityManager());
-        }
-
-        StringBuilder name = new StringBuilder();
-
-        if (port >= 0) {
-            name.append("//:").append(port);
-        }
-
-        if (rminame == null) {
-            rminame = "JStatRemoteHost";
-        }
-
-        name.append("/").append(rminame);
-
-        try {
-            // use 1.5.0 dynamically generated subs.
-            System.setProperty("java.rmi.server.ignoreSubClasses", "true");
-            RemoteHostImpl remoteHost = new RemoteHostImpl();
-            RemoteHost stub = (RemoteHost) UnicastRemoteObject.exportObject(
-                    remoteHost, 0);
-            bind(name.toString(), remoteHost);
-            System.out.println("jstatd started (bound to " + name.toString() + ")");
-            System.out.flush();
-        } catch (MalformedURLException e) {
-            if (rminame != null) {
-                System.out.println("Bad RMI server name: " + rminame);
-            } else {
-                System.out.println("Bad RMI URL: " + name);
-            }
-            e.printStackTrace(System.out);
-            System.exit(1);
-        } catch (java.rmi.ConnectException e) {
-            // could not attach to or create a registry
-            System.out.println("Could not contact RMI registry");
-            e.printStackTrace(System.out);
-            System.exit(1);
-        } catch (RemoteException e) {
-            System.out.println("Could not bind " + name + " to RMI Registry");
-            e.printStackTrace(System.out);
-            System.exit(1);
-        } catch (Exception e) {
-            System.out.println("Could not create remote object");
-            e.printStackTrace(System.out);
-            System.exit(1);
-        }
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteHostImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jstatd;
-
-import java.util.*;
-import java.nio.*;
-import java.io.*;
-import java.net.*;
-import java.rmi.*;
-import java.rmi.server.*;
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.event.*;
-import sun.jvmstat.monitor.remote.*;
-
-/**
- * Concrete implementation of the RemoteHost interface for the HotSpot
- * PerfData <em>rmi:</em> protocol.
- * <p>
- * This class provides remote access to the instrumentation exported
- * by HotSpot Java Virtual Machines through the PerfData shared memory
- * interface.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class RemoteHostImpl implements RemoteHost, HostListener {
-
-    private MonitoredHost monitoredHost;
-    private Set<Integer> activeVms;
-
-    public RemoteHostImpl() throws MonitorException {
-        try {
-            monitoredHost = MonitoredHost.getMonitoredHost("localhost");
-        } catch (URISyntaxException e) { }
-
-        activeVms = monitoredHost.activeVms();
-        monitoredHost.addHostListener(this);
-    }
-
-    public RemoteVm attachVm(int lvmid, String mode)
-                    throws RemoteException, MonitorException {
-        Integer v = lvmid;
-        RemoteVm stub = null;
-        StringBuilder sb = new StringBuilder();
-
-        sb.append("local://").append(lvmid).append("@localhost");
-        if (mode != null) {
-            sb.append("?mode=").append(mode);
-        }
-
-        String vmidStr = sb.toString();
-
-        try {
-            VmIdentifier vmid = new VmIdentifier(vmidStr);
-            MonitoredVm mvm = monitoredHost.getMonitoredVm(vmid);
-            RemoteVmImpl rvm = new RemoteVmImpl((BufferedMonitoredVm)mvm);
-            stub = (RemoteVm) UnicastRemoteObject.exportObject(rvm, 0);
-        }
-        catch (URISyntaxException e) {
-            throw new RuntimeException("Malformed VmIdentifier URI: "
-                                       + vmidStr, e);
-        }
-        return stub;
-    }
-
-    public void detachVm(RemoteVm rvm) throws RemoteException {
-        rvm.detach();
-    }
-
-    public int[] activeVms() throws MonitorException {
-        Object[] vms = null;
-        int[] vmids = null;
-
-        vms = monitoredHost.activeVms().toArray();
-        vmids = new int[vms.length];
-
-        for (int i = 0; i < vmids.length; i++) {
-            vmids[i] = ((Integer)vms[i]).intValue();
-        }
-        return vmids;
-    }
-
-    public void vmStatusChanged(VmStatusChangeEvent ev) {
-        synchronized(this.activeVms) {
-            activeVms.retainAll(ev.getActive());
-        }
-    }
-
-    public void disconnected(HostEvent ev) {
-        // we only monitor the local host, so this event shouldn't occur.
-    }
-}
--- a/jdk/src/jdk.jvmstat.rmi/share/classes/sun/tools/jstatd/RemoteVmImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.tools.jstatd;
-
-import sun.jvmstat.monitor.*;
-import sun.jvmstat.monitor.remote.*;
-
-/**
- * Concrete implementation of the RemoteVm interface for the HotSpot PerfData
- * shared memory implementation of the jvmstat monitoring APIs. This class
- * providing remote access to the instrumentation exported by a local HotSpot
- * Java Virtual Machine. The instrumentation buffer is shipped in whole to
- * the remote machine, which is responsible for parsing and provide access
- * to the contained data.
- *
- * @author Brian Doherty
- * @since 1.5
- */
-public class RemoteVmImpl implements RemoteVm {
-
-    private BufferedMonitoredVm mvm;
-
-    RemoteVmImpl(BufferedMonitoredVm mvm) {
-        this.mvm = mvm;
-    }
-
-    public byte[] getBytes() {
-        return mvm.getBytes();
-    }
-
-    public int getCapacity() {
-        return mvm.getCapacity();
-    }
-
-    public void detach() {
-        mvm.detach();
-    }
-
-    public int getLocalVmId() {
-        return mvm.getVmIdentifier().getLocalVmId();
-    }
-}
--- a/jdk/src/jdk.jvmstat/share/classes/module-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/jdk.jvmstat/share/classes/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,12 +28,12 @@
         jdk.attach,
         jdk.jcmd,
         jdk.jconsole,
-        jdk.jvmstat.rmi;
+        jdk.jstatd;
     exports sun.jvmstat.monitor.event to
         jdk.jcmd,
-        jdk.jvmstat.rmi;
+        jdk.jstatd;
     exports sun.jvmstat.perfdata.monitor to
-        jdk.jvmstat.rmi;
+        jdk.jstatd;
 
     uses sun.jvmstat.monitor.MonitoredHostService;
     provides sun.jvmstat.monitor.MonitoredHostService with sun.jvmstat.perfdata.monitor.protocol.file.MonitoredHostFileService;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/jdk/net/ExtendedSocketOptions.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.io.FileDescriptor;
+import java.net.SocketException;
+import java.net.SocketOption;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Collections;
+import java.util.Set;
+import jdk.internal.misc.JavaIOFileDescriptorAccess;
+import jdk.internal.misc.SharedSecrets;
+
+/**
+ * Defines extended socket options, beyond those defined in
+ * {@link java.net.StandardSocketOptions}. These options may be platform
+ * specific.
+ *
+ * @since 1.8
+ */
+public final class ExtendedSocketOptions {
+
+    private static class ExtSocketOption<T> implements SocketOption<T> {
+        private final String name;
+        private final Class<T> type;
+        ExtSocketOption(String name, Class<T> type) {
+            this.name = name;
+            this.type = type;
+        }
+        @Override public String name() { return name; }
+        @Override public Class<T> type() { return type; }
+        @Override public String toString() { return name; }
+    }
+
+    private ExtendedSocketOptions() { }
+
+    /**
+     * Service level properties. When a security manager is installed,
+     * setting or getting this option requires a {@link NetworkPermission}
+     * {@code ("setOption.SO_FLOW_SLA")} or {@code "getOption.SO_FLOW_SLA"}
+     * respectively.
+     */
+    public static final SocketOption<SocketFlow> SO_FLOW_SLA = new
+        ExtSocketOption<SocketFlow>("SO_FLOW_SLA", SocketFlow.class);
+
+
+    private static final PlatformSocketOptions platformSocketOptions =
+            PlatformSocketOptions.get();
+
+    private static final boolean flowSupported =
+            platformSocketOptions.flowSupported();
+
+    private static final Set<SocketOption<?>> extendedOptions = options();
+
+    static Set<SocketOption<?>> options() {
+        if (flowSupported)
+            return Set.of(SO_FLOW_SLA);
+        else
+            return Collections.<SocketOption<?>>emptySet();
+    }
+
+    static {
+        // Registers the extended socket options with the base module.
+        sun.net.ext.ExtendedSocketOptions.register(
+                new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
+
+            @Override
+            public void setOption(FileDescriptor fd,
+                                  SocketOption<?> option,
+                                  Object value)
+                throws SocketException
+            {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("setOption." + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if (option == SO_FLOW_SLA) {
+                    assert flowSupported;
+                    SocketFlow flow = checkValueType(value, option.type());
+                    setFlowOption(fd, flow);
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+
+            @Override
+            public Object getOption(FileDescriptor fd,
+                                    SocketOption<?> option)
+                throws SocketException
+            {
+                SecurityManager sm = System.getSecurityManager();
+                if (sm != null)
+                    sm.checkPermission(new NetworkPermission("getOption." + option.name()));
+
+                if (fd == null || !fd.valid())
+                    throw new SocketException("socket closed");
+
+                if (option == SO_FLOW_SLA) {
+                    assert flowSupported;
+                    SocketFlow flow = SocketFlow.create();
+                    getFlowOption(fd, flow);
+                    return flow;
+                } else {
+                    throw new InternalError("Unexpected option " + option);
+                }
+            }
+        });
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T> T checkValueType(Object value, Class<?> type) {
+        if (!type.isAssignableFrom(value.getClass())) {
+            String s = "Found: " + value.getClass() + ", Expected: " + type;
+            throw new IllegalArgumentException(s);
+        }
+        return (T) value;
+    }
+
+    private static final JavaIOFileDescriptorAccess fdAccess =
+            SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private static void setFlowOption(FileDescriptor fd, SocketFlow f)
+        throws SocketException
+    {
+        int status = platformSocketOptions.setFlowOption(fdAccess.get(fd),
+                                                         f.priority(),
+                                                         f.bandwidth());
+        f.status(status);  // augment the given flow with the status
+    }
+
+    private static void getFlowOption(FileDescriptor fd, SocketFlow f)
+        throws SocketException
+    {
+        int status = platformSocketOptions.getFlowOption(fdAccess.get(fd), f);
+        f.status(status);  // augment the given flow with the status
+    }
+
+    static class PlatformSocketOptions {
+
+        protected PlatformSocketOptions() {}
+
+        @SuppressWarnings("unchecked")
+        private static PlatformSocketOptions newInstance(String cn) {
+            Class<PlatformSocketOptions> c;
+            try {
+                c = (Class<PlatformSocketOptions>)Class.forName(cn);
+                return c.getConstructor(new Class<?>[] { }).newInstance();
+            } catch (ReflectiveOperationException x) {
+                throw new AssertionError(x);
+            }
+        }
+
+        private static PlatformSocketOptions create() {
+            String osname = AccessController.doPrivileged(
+                    new PrivilegedAction<String>() {
+                        public String run() {
+                            return System.getProperty("os.name");
+                        }
+                    });
+            if ("SunOS".equals(osname))
+                return newInstance("jdk.net.SolarisSocketOptions");
+            return new PlatformSocketOptions();
+        }
+
+        private static final PlatformSocketOptions instance = create();
+
+        static PlatformSocketOptions get() {
+            return instance;
+        }
+
+        int setFlowOption(int fd, int priority, long bandwidth)
+            throws SocketException
+        {
+            throw new UnsupportedOperationException("unsupported socket option");
+        }
+
+        int getFlowOption(int fd, SocketFlow f) throws SocketException {
+            throw new UnsupportedOperationException("unsupported socket option");
+        }
+
+        boolean flowSupported() {
+            return false;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/jdk/net/NetworkPermission.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.net;
+
+import java.security.BasicPermission;
+
+/**
+ * Represents permission to access the extended networking capabilities
+ * defined in the jdk.net package. These permissions contain a target
+ * name, but no actions list. Callers either possess the permission or not.
+ * <p>
+ * The following targets are defined:
+ *
+ * <table border=1 cellpadding=5 summary="permission target name,
+ *  what the target allows,and associated risks">
+ * <tr>
+ *   <th>Permission Target Name</th>
+ *   <th>What the Permission Allows</th>
+ *   <th>Risks of Allowing this Permission</th>
+ * </tr>
+ * <tr>
+ *   <td>setOption.SO_FLOW_SLA</td>
+ *   <td>set the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA} option
+ *       on any socket that supports it</td>
+ *   <td>allows caller to set a higher priority or bandwidth allocation
+ *       to sockets it creates, than they might otherwise be allowed.</td>
+ * </tr>
+ * <tr>
+ *   <td>getOption.SO_FLOW_SLA</td>
+ *   <td>retrieve the {@link ExtendedSocketOptions#SO_FLOW_SLA SO_FLOW_SLA}
+ *       setting from any socket that supports the option</td>
+ *   <td>allows caller access to SLA information that it might not
+ *       otherwise have</td>
+ * </tr></table>
+ *
+ * @see jdk.net.ExtendedSocketOptions
+ *
+ * @since 1.8
+ */
+
+public final class NetworkPermission extends BasicPermission {
+
+    private static final long serialVersionUID = -2012939586906722291L;
+
+    /**
+     * Creates a NetworkPermission with the given target name.
+     *
+     * @param name the permission target name
+     * @throws NullPointerException if {@code name} is {@code null}.
+     * @throws IllegalArgumentException if {@code name} is empty.
+     */
+    public NetworkPermission(String name)
+    {
+        super(name);
+    }
+
+    /**
+     * Creates a NetworkPermission with the given target name.
+     *
+     * @param name the permission target name
+     * @param actions should be {@code null}. Is ignored if not.
+     * @throws NullPointerException if {@code name} is {@code null}.
+     * @throws IllegalArgumentException if {@code name} is empty.
+     */
+    public NetworkPermission(String name, String actions)
+    {
+        super(name, actions);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/jdk/net/SocketFlow.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.lang.annotation.Native;
+
+/**
+ * Represents the service level properties for the platform specific socket
+ * option {@link ExtendedSocketOptions#SO_FLOW_SLA}.
+ * <p>
+ * The priority and bandwidth parameters must be set before
+ * setting the socket option.
+ * <p>
+ * When the {@code SO_FLOW_SLA} option is set then it may not take effect
+ * immediately. If the value of the socket option is obtained with
+ * {@code getOption()} then the status may be returned as {@code INPROGRESS}
+ * until it takes effect. The priority and bandwidth values are only valid when
+ * the status is returned as OK.
+ * <p>
+ * When a security manager is installed, a {@link NetworkPermission}
+ * is required to set or get this option.
+ *
+ * @since 1.8
+ */
+public class SocketFlow {
+
+    @Native public static final int UNSET = -1;
+    @Native public static final int NORMAL_PRIORITY = 1;
+    @Native public static final int HIGH_PRIORITY = 2;
+
+    @Native private static final int NO_STATUS_VALUE = 0;
+    @Native private static final int OK_VALUE = 1;
+    @Native private static final int NO_PERMISSION_VALUE = 2;
+    @Native private static final int NOT_CONNECTED_VALUE = 3;
+    @Native private static final int NOT_SUPPORTED_VALUE = 4;
+    @Native private static final int ALREADY_CREATED_VALUE = 5;
+    @Native private static final int IN_PROGRESS_VALUE = 6;
+    @Native private static final int OTHER_VALUE = 7;
+
+    /**
+     * Enumeration of the return values from the SO_FLOW_SLA
+     * socket option. Both setting and getting the option return
+     * one of these statuses, which reflect the state of socket's
+     * flow.
+     *
+     * @since 1.8
+     */
+    public enum Status {
+        /**
+         * Set or get socket option has not been called yet. Status
+         * values can only be retrieved after calling set or get.
+         */
+        NO_STATUS(NO_STATUS_VALUE),
+        /**
+         * Flow successfully created.
+         */
+        OK(OK_VALUE),
+        /**
+         * Caller has no permission to create flow.
+         */
+        NO_PERMISSION(NO_PERMISSION_VALUE),
+        /**
+         * Flow can not be created because socket is not connected.
+         */
+        NOT_CONNECTED(NOT_CONNECTED_VALUE),
+        /**
+         * Flow creation not supported for this socket.
+         */
+        NOT_SUPPORTED(NOT_SUPPORTED_VALUE),
+        /**
+         * A flow already exists with identical attributes.
+         */
+        ALREADY_CREATED(ALREADY_CREATED_VALUE),
+        /**
+         * A flow is being created.
+         */
+        IN_PROGRESS(IN_PROGRESS_VALUE),
+        /**
+         * Some other unspecified error.
+         */
+        OTHER(OTHER_VALUE);
+
+        private final int value;
+        Status(int value) { this.value = value; }
+
+        static Status from(int value) {
+            if      (value == NO_STATUS.value)       return NO_STATUS;
+            else if (value == OK.value)              return OK;
+            else if (value == NO_PERMISSION.value)   return NO_PERMISSION;
+            else if (value == NOT_CONNECTED.value)   return NOT_CONNECTED;
+            else if (value == NOT_SUPPORTED.value)   return NOT_SUPPORTED;
+            else if (value == ALREADY_CREATED.value) return ALREADY_CREATED;
+            else if (value == IN_PROGRESS.value)     return IN_PROGRESS;
+            else if (value == OTHER.value)           return OTHER;
+            else     throw new InternalError("Unknown value: " + value);
+        }
+    }
+
+    private int priority = NORMAL_PRIORITY;
+    private long bandwidth = UNSET;
+    private Status status = Status.NO_STATUS;
+
+    /**
+     * Creates a new SocketFlow that can be used to set the SO_FLOW_SLA
+     * socket option and create a socket flow.
+     */
+    public static SocketFlow create() {
+        return new SocketFlow();
+    }
+
+    private SocketFlow() { }
+
+    /**
+     * Sets this SocketFlow's priority. Must be either NORMAL_PRIORITY
+     * HIGH_PRIORITY. If not set, a flow's priority is normal.
+     *
+     * @throws IllegalArgumentException if priority is not NORMAL_PRIORITY or
+     *         HIGH_PRIORITY.
+     */
+    public SocketFlow priority(int priority) {
+        if (priority != NORMAL_PRIORITY && priority != HIGH_PRIORITY)
+            throw new IllegalArgumentException("invalid priority :" + priority);
+        this.priority = priority;
+        return this;
+    }
+
+    /**
+     * Sets this SocketFlow's bandwidth. Must be greater than or equal to zero.
+     * A value of zero drops all packets for the socket.
+     *
+     * @throws IllegalArgumentException if bandwidth is less than zero.
+     */
+    public SocketFlow bandwidth(long bandwidth) {
+        if (bandwidth < 0)
+            throw new IllegalArgumentException("invalid bandwidth: " + bandwidth);
+        this.bandwidth = bandwidth;
+        return this;
+    }
+
+    /**
+     * Returns this SocketFlow's priority.
+     */
+    public int priority() {
+        return priority;
+    }
+
+    /**
+     * Returns this SocketFlow's bandwidth.
+     *
+     * @return this SocketFlow's bandwidth, or {@code -1} if status is not OK.
+     */
+    public long bandwidth() {
+        return bandwidth;
+    }
+
+    /**
+     * Returns the Status value of this SocketFlow. NO_STATUS is returned
+     * if the object was not used in a call to set or get the option.
+     */
+    public Status status() {
+        return status;
+    }
+
+    void status(int status) {
+        this.status = Status.from(status);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder(super.toString());
+        sb.append(" [ priority=").append(priority())
+          .append(", bandwidth=").append(bandwidth())
+          .append(", status=").append(status())
+          .append(" ]");
+        return sb.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/jdk/net/Sockets.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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.net;
+
+import java.net.*;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;
+
+/**
+ * Defines static methods to set and get socket options defined by the
+ * {@link java.net.SocketOption} interface. All of the standard options defined
+ * by {@link java.net.Socket}, {@link java.net.ServerSocket}, and
+ * {@link java.net.DatagramSocket} can be set this way, as well as additional
+ * or platform specific options supported by each socket type.
+ * <p>
+ * The {@link #supportedOptions(Class)} method can be called to determine
+ * the complete set of options available (per socket type) on the
+ * current system.
+ * <p>
+ * When a security manager is installed, some non-standard socket options
+ * may require a security permission before being set or get.
+ * The details are specified in {@link ExtendedSocketOptions}. No permission
+ * is required for {@link java.net.StandardSocketOptions}.
+ *
+ * @see java.nio.channels.NetworkChannel
+ */
+public class Sockets {
+
+    private static final Map<Class<?>,Set<SocketOption<?>>>
+            options = optionSets();
+
+    private Sockets() {}
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.Socket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option. May be null for some
+     *              options.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs, or socket is closed.
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(Socket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a {@link java.net.Socket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(Socket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.ServerSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(ServerSocket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a {@link java.net.ServerSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(ServerSocket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Sets the value of a socket option on a {@link java.net.DatagramSocket}
+     * or {@link java.net.MulticastSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     * @param value The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IllegalArgumentException if the value is not valid for
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> void setOption(DatagramSocket s, SocketOption<T> name, T value) throws IOException
+    {
+        s.setOption(name, value);
+    }
+
+    /**
+     * Returns the value of a socket option from a
+     * {@link java.net.DatagramSocket} or {@link java.net.MulticastSocket}
+     *
+     * @param s the socket
+     * @param name The socket option
+     *
+     * @return The value of the socket option.
+     *
+     * @throws UnsupportedOperationException if the socket does not support
+     *         the option.
+     *
+     * @throws IOException if an I/O error occurs
+     *
+     * @throws NullPointerException if name is null
+     *
+     * @throws SecurityException if a security manager is set and the
+     *         caller does not have any required permission.
+     *
+     * @see java.net.StandardSocketOptions
+     */
+    public static <T> T getOption(DatagramSocket s, SocketOption<T> name) throws IOException
+    {
+        return s.getOption(name);
+    }
+
+    /**
+     * Returns a set of {@link java.net.SocketOption}s supported by the
+     * given socket type. This set may include standard options and also
+     * non standard extended options.
+     *
+     * @param socketType the type of java.net socket
+     *
+     * @throws IllegalArgumentException if socketType is not a valid
+     *         socket type from the java.net package.
+     */
+    public static Set<SocketOption<?>> supportedOptions(Class<?> socketType) {
+        Set<SocketOption<?>> set = options.get(socketType);
+        if (set == null) {
+            throw new IllegalArgumentException("unknown socket type");
+        }
+        return set;
+    }
+
+    private static void checkValueType(Object value, Class<?> type) {
+        if (!type.isAssignableFrom(value.getClass())) {
+            String s = "Found: " + value.getClass().toString() + " Expected: "
+                        + type.toString();
+            throw new IllegalArgumentException(s);
+        }
+    }
+
+    private static volatile boolean checkedReusePort;
+    private static volatile boolean isReusePortAvailable;
+
+    /**
+     * Tells whether SO_REUSEPORT is supported.
+     */
+    static boolean isReusePortAvailable() {
+        if (!checkedReusePort) {
+            Set<SocketOption<?>> s = new Socket().supportedOptions();
+            isReusePortAvailable = s.contains(StandardSocketOptions.SO_REUSEPORT);
+            checkedReusePort = true;
+        }
+        return isReusePortAvailable;
+    }
+
+    private static Map<Class<?>,Set<SocketOption<?>>> optionSets() {
+        Map<Class<?>,Set<SocketOption<?>>> options = new HashMap<>();
+        boolean flowsupported = PlatformSocketOptions.get().flowSupported();
+        boolean reuseportsupported = isReusePortAvailable();
+        // Socket
+
+        Set<SocketOption<?>> set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_KEEPALIVE);
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
+        set.add(StandardSocketOptions.SO_LINGER);
+        set.add(StandardSocketOptions.IP_TOS);
+        set.add(StandardSocketOptions.TCP_NODELAY);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(Socket.class, set);
+
+        // ServerSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
+        set.add(StandardSocketOptions.IP_TOS);
+        set = Collections.unmodifiableSet(set);
+        options.put(ServerSocket.class, set);
+
+        // DatagramSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
+        set.add(StandardSocketOptions.IP_TOS);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(DatagramSocket.class, set);
+
+        // MulticastSocket
+
+        set = new HashSet<>();
+        set.add(StandardSocketOptions.SO_SNDBUF);
+        set.add(StandardSocketOptions.SO_RCVBUF);
+        set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
+        set.add(StandardSocketOptions.IP_TOS);
+        set.add(StandardSocketOptions.IP_MULTICAST_IF);
+        set.add(StandardSocketOptions.IP_MULTICAST_TTL);
+        set.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+        if (flowsupported) {
+            set.add(ExtendedSocketOptions.SO_FLOW_SLA);
+        }
+        set = Collections.unmodifiableSet(set);
+        options.put(MulticastSocket.class, set);
+
+        return Collections.unmodifiableMap(options);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/jdk/net/package-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Platform specific socket options for the {@code java.net} and {@code java.nio.channels}
+ * socket classes.
+ *
+ * @since 1.8
+ */
+
+package jdk.net;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/share/classes/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+ */
+
+module jdk.net {
+    exports jdk.net;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/solaris/classes/jdk/net/SolarisSocketOptions.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.net;
+
+import java.net.SocketException;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import jdk.net.ExtendedSocketOptions.PlatformSocketOptions;
+
+class SolarisSocketOptions extends PlatformSocketOptions {
+
+    public SolarisSocketOptions() { }
+
+    @Override native int setFlowOption(int fd, int priority, long bandwidth)
+            throws SocketException;
+
+    @Override native int getFlowOption(int fd, SocketFlow f)
+            throws SocketException;
+
+    @Override native boolean flowSupported();
+
+    private static native void init();
+
+    static {
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            public Void run() {
+                System.loadLibrary("extnet");
+                return null;
+            }
+        });
+        init();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.c	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+#include "SolarisSocketOptions.h"
+
+static jfieldID sf_priority;
+static jfieldID sf_bandwidth;
+
+static int initialized = 0;
+
+/*
+ * Class:     jdk_net_SolarisSocketOptions
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_jdk_net_SolarisSocketOptions_init
+  (JNIEnv *env, jclass unused)
+{
+    if (!initialized) {
+        jclass c = (*env)->FindClass(env, "jdk/net/SocketFlow");
+        CHECK_NULL(c);
+        sf_priority = (*env)->GetFieldID(env, c, "priority", "I");
+        CHECK_NULL(sf_priority);
+        sf_bandwidth = (*env)->GetFieldID(env, c, "bandwidth", "J");
+        CHECK_NULL(sf_bandwidth);
+        initialized = 1;
+    }
+}
+
+/** Return the Status value. */
+static jint toStatus(int errval)
+{
+    switch (errval) {
+      case 0:           return jdk_net_SocketFlow_OK_VALUE;
+      case EPERM:       return jdk_net_SocketFlow_NO_PERMISSION_VALUE;
+      case ENOTCONN:    return jdk_net_SocketFlow_NOT_CONNECTED_VALUE;
+      case EOPNOTSUPP:  return jdk_net_SocketFlow_NOT_SUPPORTED_VALUE;
+      case EALREADY:    return jdk_net_SocketFlow_ALREADY_CREATED_VALUE;
+      case EINPROGRESS: return jdk_net_SocketFlow_IN_PROGRESS_VALUE;
+      default:          return jdk_net_SocketFlow_OTHER_VALUE;
+    }
+}
+
+void throwByNameWithLastError
+  (JNIEnv *env, const char *name, const char *defaultDetail)
+{
+  char defaultMsg[255];
+  sprintf(defaultMsg, "errno: %d, %s", errno, defaultDetail);
+  JNU_ThrowByNameWithLastError(env, name, defaultMsg);
+}
+
+/*
+ * Class:     jdk_net_SolarisSocketOptions
+ * Method:    setFlowOption0
+ * Signature: (IIJ)I
+ */
+JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_setFlowOption
+  (JNIEnv *env, jobject unused, jint fd, jint priority, jlong bandwidth)
+{
+    int rv;
+    sock_flow_props_t props;
+    memset(&props, 0, sizeof(props));
+    props.sfp_version = SOCK_FLOW_PROP_VERSION1;
+
+    if (priority != jdk_net_SocketFlow_UNSET) {
+        props.sfp_mask |= SFP_PRIORITY;
+        props.sfp_priority = priority;
+    }
+    if (bandwidth > jdk_net_SocketFlow_UNSET)  {
+        props.sfp_mask |= SFP_MAXBW;
+        props.sfp_maxbw = (uint64_t) bandwidth;
+    }
+
+    rv = setsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
+
+    if (rv < 0) {
+        if (errno == ENOPROTOOPT) {
+            JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                            "unsupported socket option");
+        } else if (errno == EACCES || errno == EPERM) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
+        } else {
+            throwByNameWithLastError(env, "java/net/SocketException",
+                                     "set option SO_FLOW_SLA failed");
+        }
+        return 0;
+    }
+    return toStatus(props.sfp_status);
+}
+
+/*
+ * Class:     jdk_net_SolarisSocketOptions
+ * Method:    getFlowOption0
+ * Signature: (ILjdk/net/SocketFlow;)I
+ */
+JNIEXPORT jint JNICALL Java_jdk_net_SolarisSocketOptions_getFlowOption
+  (JNIEnv *env, jobject unused, jint fd, jobject flow)
+{
+    sock_flow_props_t props;
+    socklen_t sz = sizeof(props);
+
+    int rv = getsockopt(fd, SOL_SOCKET, SO_FLOW_SLA, &props, &sz);
+
+    if (rv < 0) {
+        if (errno == ENOPROTOOPT) {
+            JNU_ThrowByName(env, "java/lang/UnsupportedOperationException",
+                            "unsupported socket option");
+        } else if (errno == EACCES || errno == EPERM) {
+            JNU_ThrowByName(env, "java/net/SocketException", "Permission denied");
+        } else {
+            throwByNameWithLastError(env, "java/net/SocketException",
+                                     "get option SO_FLOW_SLA failed");
+        }
+        return -1;
+    }
+    /* first check status to see if flow exists */
+    if (props.sfp_status == 0) { /* OK */
+        /* can set the other fields now */
+        if (props.sfp_mask & SFP_PRIORITY) {
+            (*env)->SetIntField(env, flow, sf_priority, props.sfp_priority);
+        }
+        if (props.sfp_mask & SFP_MAXBW) {
+            (*env)->SetLongField(env, flow, sf_bandwidth,
+                                    (jlong)props.sfp_maxbw);
+        }
+    }
+    return toStatus(props.sfp_status);
+}
+
+JNIEXPORT jboolean JNICALL Java_jdk_net_SolarisSocketOptions_flowSupported
+  (JNIEnv *env, jobject unused)
+{
+    /* Do a simple dummy call, and try to figure out from that */
+    sock_flow_props_t props;
+    int rv, s;
+
+    s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (s < 0) {
+        return JNI_FALSE;
+    }
+    memset(&props, 0, sizeof(props));
+    props.sfp_version = SOCK_FLOW_PROP_VERSION1;
+    props.sfp_mask |= SFP_PRIORITY;
+    props.sfp_priority = SFP_PRIO_NORMAL;
+    rv = setsockopt(s, SOL_SOCKET, SO_FLOW_SLA, &props, sizeof(props));
+    if (rv != 0 && errno == ENOPROTOOPT) {
+        rv = JNI_FALSE;
+    } else {
+        rv = JNI_TRUE;
+    }
+    close(s);
+    return rv;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.net/solaris/native/libextnet/SolarisSocketOptions.h	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 SOLARIS_SOCKET_OPTIONS_H
+#define SOLARIS_SOCKET_OPTIONS_H
+
+#include <sys/socket.h>
+#include <jni.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "jni_util.h"
+#include "jdk_net_SocketFlow.h"
+#include "SolarisSocketOptions.h"
+#include "jdk_net_SolarisSocketOptions.h"
+
+#ifndef SO_FLOW_SLA
+#define SO_FLOW_SLA 0x1018
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
+#endif
+
+/*
+ * Used with the setsockopt(SO_FLOW_SLA, ...) call to set
+ * per socket service level properties.
+ * When the application uses per-socket API, we will enforce the properties
+ * on both outbound and inbound packets.
+ *
+ * For now, only priority and maxbw are supported in SOCK_FLOW_PROP_VERSION1.
+ */
+typedef struct sock_flow_props_s {
+        int             sfp_version;
+        uint32_t        sfp_mask;
+        int             sfp_priority;   /* flow priority */
+        uint64_t        sfp_maxbw;      /* bandwidth limit in bps */
+        int             sfp_status;     /* flow create status for getsockopt */
+} sock_flow_props_t;
+
+#define SOCK_FLOW_PROP_VERSION1 1
+
+/* bit mask values for sfp_mask */
+#define SFP_MAXBW       0x00000001      /* Flow Bandwidth Limit */
+#define SFP_PRIORITY    0x00000008      /* Flow priority */
+
+/* possible values for sfp_priority */
+#define SFP_PRIO_NORMAL 1
+#define SFP_PRIO_HIGH   2
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif /* _LONG_LONG_ALIGNMENT */
+
+#endif /* SO_FLOW_SLA */
+
+#endif /* SOLARIS_SOCKET_OPTIONS_H */
--- a/jdk/src/jdk.policytool/share/classes/module-info.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/src/jdk.policytool/share/classes/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,6 +28,7 @@
     requires java.logging;
     requires java.management;
     requires java.sql;
+    requires jdk.net;
     requires java.security.jgss;
     requires jdk.security.jgss;
 }
--- a/jdk/test/ProblemList.txt	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/ProblemList.txt	Wed Jul 05 21:39:33 2017 +0200
@@ -319,6 +319,8 @@
 
 tools/launcher/FXLauncherTest.java                              8068049 linux-all,macosx-all
 
+tools/pack200/Pack200Props.java                                 8155857 generic-all
+
 ############################################################################
 
 # jdk_jdi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Focus/Cause/FocusCauseTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+  @test
+  @bug 8080395
+  @summary consider making sun.awt.CausedFocusEvent functionality public
+  @run main FocusCauseTest
+*/
+
+
+import java.awt.*;
+import java.awt.event.FocusEvent.Cause;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.lang.IllegalArgumentException;
+import java.lang.Override;
+import java.lang.RuntimeException;
+import java.util.Arrays;
+
+public class FocusCauseTest {
+
+    private static Cause[] causes1 = {Cause.ACTIVATION,
+            Cause.UNKNOWN, Cause.UNKNOWN, Cause.TRAVERSAL_FORWARD,
+            Cause.TRAVERSAL_FORWARD, Cause.TRAVERSAL_BACKWARD,
+            Cause.TRAVERSAL_BACKWARD, Cause.TRAVERSAL_UP,
+            Cause.TRAVERSAL_DOWN, Cause.CLEAR_GLOBAL_FOCUS_OWNER};
+    private static Cause[] causes2 = new Cause[10];
+    private static int cnt;
+
+    static byte[] data =
+            {-84, -19, 0, 5, 115, 114, 0, 24, 115, 117, 110, 46, 97, 119,
+            116, 46, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118,
+            101, 110, 116, -51, 98, 39, -75, 86, 52, 107, 30, 2, 0, 1, 76, 0, 5,
+            99, 97, 117, 115, 101, 116, 0, 32, 76, 115, 117, 110, 47, 97, 119,
+            116, 47, 67, 97, 117, 115, 101, 100, 70, 111, 99, 117, 115, 69, 118,
+            101, 110, 116, 36, 67, 97, 117, 115, 101, 59, 120, 114, 0, 25, 106,
+            97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46, 70,
+            111, 99, 117, 115, 69, 118, 101, 110, 116, 7, 68, -65, 75, 55, -113,
+            98, -52, 2, 0, 1, 90, 0, 9, 116, 101, 109, 112, 111, 114, 97, 114,
+            121, 120, 114, 0, 29, 106, 97, 118, 97, 46, 97, 119, 116, 46, 101,
+            118, 101, 110, 116, 46, 67, 111, 109, 112, 111, 110, 101, 110, 116,
+            69, 118, 101, 110, 116, 112, 109, -6, -107, 79, -87, -38, 69, 2, 0,
+            0, 120, 114, 0, 17, 106, 97, 118, 97, 46, 97, 119, 116, 46, 65, 87,
+            84, 69, 118, 101, 110, 116, -26, -85, 45, -31, 24, -33, -118, -61,
+            2, 0, 3, 90, 0, 8, 99, 111, 110, 115, 117, 109, 101, 100, 73, 0, 2,
+            105, 100, 91, 0, 5, 98, 100, 97, 116, 97, 116, 0, 2, 91, 66, 120,
+            114, 0, 21, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 69, 118,
+            101, 110, 116, 79, 98, 106, 101, 99, 116, 76, -115, 9, 78, 24, 109,
+            125, -88, 2, 0, 0, 120, 112, 0, 0, 0, 3, -20, 112, 0, 126, 114, 0,
+            30, 115, 117, 110, 46, 97, 119, 116, 46, 67, 97, 117, 115, 101, 100,
+            70, 111, 99, 117, 115, 69, 118, 101, 110, 116, 36, 67, 97, 117, 115,
+            101, 0, 0, 0, 0, 0, 0, 0, 0, 18, 0, 0, 120, 114, 0, 14, 106, 97,
+            118, 97, 46, 108, 97, 110, 103, 46, 69, 110, 117, 109, 0, 0, 0, 0,
+            0, 0, 0, 0, 18, 0, 0, 120, 112, 116, 0};
+
+    static byte[] dataOld =
+            {-84, -19, 0, 5, 115, 114, 0, 25, 106, 97, 118, 97, 46, 97, 119,
+            116, 46, 101, 118, 101, 110, 116, 46, 70, 111, 99, 117, 115, 69,
+            118, 101, 110, 116, 7, 68, -65, 75, 55, -113, 98, -52, 2, 0, 1, 90,
+            0, 9, 116, 101, 109, 112, 111, 114, 97, 114, 121, 120, 114, 0, 29,
+            106, 97, 118, 97, 46, 97, 119, 116, 46, 101, 118, 101, 110, 116, 46,
+            67, 111, 109, 112, 111, 110, 101, 110, 116, 69, 118, 101, 110, 116,
+            112, 109, -6, -107, 79, -87, -38, 69, 2, 0, 0, 120, 114, 0, 17, 106,
+            97, 118, 97, 46, 97, 119, 116, 46, 65, 87, 84, 69, 118, 101, 110,
+            116, -26, -85, 45, -31, 24, -33, -118, -61, 2, 0, 3, 90, 0, 8, 99,
+            111, 110, 115, 117, 109, 101, 100, 73, 0, 2, 105, 100, 91, 0, 5, 98,
+            100, 97, 116, 97, 116, 0, 2, 91, 66, 120, 114, 0, 21, 106, 97, 118,
+            97, 46, 117, 116, 105, 108, 46, 69, 118, 101, 110, 116, 79, 98, 106,
+            101, 99, 116, 76, -115, 9, 78, 24, 109, 125, -88, 2, 0, 0, 120, 112,
+            0, 0, 0, 0, 100, 112, 0};
+
+    static String[] causesIn = {"UNKNOWN", "MOUSE_EVENT", "TRAVERSAL",
+            "TRAVERSAL_UP", "TRAVERSAL_DOWN", "TRAVERSAL_FORWARD",
+            "TRAVERSAL_BACKWARD", "MANUAL_REQUEST", "AUTOMATIC_TRAVERSE"
+            ,"ROLLBACK", "NATIVE_SYSTEM", "ACTIVATION",
+            "CLEAR_GLOBAL_FOCUS_OWNER", "RETARGETED"};
+
+    static FocusEvent.Cause[] causesOut = {FocusEvent.Cause.UNKNOWN,
+            FocusEvent.Cause.MOUSE_EVENT,
+            FocusEvent.Cause.TRAVERSAL, FocusEvent.Cause.TRAVERSAL_UP,
+            FocusEvent.Cause.TRAVERSAL_DOWN, FocusEvent.Cause.TRAVERSAL_FORWARD,
+            FocusEvent.Cause.TRAVERSAL_BACKWARD, FocusEvent.Cause.UNKNOWN,
+            FocusEvent.Cause.UNKNOWN, FocusEvent.Cause.ROLLBACK,
+            FocusEvent.Cause.UNEXPECTED, FocusEvent.Cause.ACTIVATION,
+            FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER, FocusEvent.Cause.UNKNOWN
+    };
+
+    public static void main(String[] args) throws Exception {
+        testCauses();
+        testNullCause();
+        testCausedFocusEventDeserialization();
+        testFocusEventDeserialization();
+        System.out.println("ok");
+    }
+
+    private static void testNullCause() {
+        try {
+            new FocusEvent(new Frame(), FocusEvent.FOCUS_GAINED, true,
+                    null, null);
+            throw new RuntimeException("Exception is not thrown when the " +
+                    "cause is null");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    private static void testCauses() throws Exception {
+        cnt = 0;
+        Frame frame = new Frame();
+        TextField comp1 = new TextField();
+        comp1.addFocusListener(new FocusListener() {
+            @Override
+            public void focusGained(FocusEvent e) {
+                System.out.println(e.getCause());
+                causes2[cnt++] = e.getCause();
+            }
+
+            @Override
+            public void focusLost(FocusEvent e) {
+                System.out.println(e.getCause());
+                causes2[cnt++] = e.getCause();
+            }
+        });
+        TextField comp2 = new TextField();
+        comp2.addFocusListener(new FocusListener() {
+            @Override
+            public void focusGained(FocusEvent e) {
+                System.out.println(e.getCause());
+                causes2[cnt++] = e.getCause();
+            }
+
+            @Override
+            public void focusLost(FocusEvent e) {
+                System.out.println(e.getCause());
+                causes2[cnt++] = e.getCause();
+            }
+        });
+        frame.add(comp1, BorderLayout.NORTH);
+        frame.add(comp2, BorderLayout.SOUTH);
+        frame.setVisible(true);
+
+        Robot robot = new Robot();
+        robot.delay(200);
+        robot.waitForIdle();
+        comp2.requestFocus();
+        robot.waitForIdle();
+        comp2.transferFocus();
+        robot.waitForIdle();
+        comp1.transferFocusBackward();
+        robot.waitForIdle();
+        comp2.transferFocusUpCycle();
+        robot.waitForIdle();
+        frame.transferFocusDownCycle();
+        robot.waitForIdle();
+        frame.dispose();
+        robot.waitForIdle();
+        if (!Arrays.equals(causes1, causes2)) {
+            throw new RuntimeException("wrong cause " + causes2);
+        }
+    }
+
+    private static void  testCausedFocusEventDeserialization() throws
+            Exception {
+        for (int i = 0; i < causesIn.length; i++) {
+            final String causeIn = causesIn[i];
+            ObjectInputStream oi = new ObjectInputStream(new InputStream() {
+                int cnt = 0;
+                @Override
+                public int read() throws IOException {
+                    if(cnt < data.length) {
+                        return data[cnt++];
+                    } else if(cnt == data.length){
+                        cnt++;
+                        return causeIn.length();
+                    } else if(cnt - data.length - 1 < causeIn.length()) {
+                        return causeIn.getBytes()[cnt++ - data.length - 1];
+                    }
+                    return -1;
+                }
+            });
+            FocusEvent ev = (FocusEvent) oi.readObject();
+            System.out.println(ev);
+            if(ev.getCause() != causesOut[i]) {
+                throw new RuntimeException("Wrong cause read :" +ev.getCause());
+            }
+        }
+    }
+
+    private static void testFocusEventDeserialization() throws
+            Exception {
+        ObjectInputStream oi = new ObjectInputStream(
+                new ByteArrayInputStream(dataOld));
+        FocusEvent ev = (FocusEvent)oi.readObject();
+        if(ev.getCause() != FocusEvent.Cause.UNKNOWN) {
+            throw new RuntimeException("Wrong cause in deserialized FocusEvent "
+                    + ev.getCause());
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/PrintJob/NullFrameTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ * @test
+ * @bug 8154057
+ * @summary  getPrintJob doesn't throw NPE if frame is null
+ * @run main NullFrameTest
+ */
+import java.awt.JobAttributes;
+import java.awt.Toolkit;
+
+public class NullFrameTest {
+    public static void main(String[] args) {
+        JobAttributes ja = new JobAttributes();
+        ja.setDialog(JobAttributes.DialogType.COMMON);
+        boolean npeThrown = false;
+        try {
+            Toolkit.getDefaultToolkit().getPrintJob(null,
+                                               "test Printing", ja, null);
+        } catch (NullPointerException ex) {
+            npeThrown = true;
+        }
+        if (!npeThrown) {
+            throw
+            new RuntimeException("getPrintJob didn't throw NPE for null Frame");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/TrayIcon/UpdatePopupMenu/UpdatePopupMenu.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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 8147841
+ @summary Updating Tray Icon popup menu does not update menu items on Mac OS X
+ @run main/manual UpdatePopupMenu
+ */
+
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.PopupMenu;
+import java.awt.MenuItem;
+import java.awt.Image;
+import java.awt.Graphics2D;
+import java.awt.Color;
+import java.awt.image.BufferedImage;
+import java.awt.RenderingHints;
+import java.awt.AWTException;
+import java.awt.Button;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Panel;
+import java.awt.TextArea;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+public class UpdatePopupMenu implements ActionListener {
+
+    private static final int imageSize = 32;
+    private static final int imageInset = 4;
+    private static GridBagLayout layout;
+    private static Panel mainControlPanel;
+    private static Panel resultButtonPanel;
+    private static TextArea instructionTextArea;
+    private static Button passButton;
+    private static Button failButton;
+    private static Frame mainFrame;
+    private static Thread mainThread = null;
+    private static boolean testPassed = false;
+    private static boolean isInterrupted = false;
+    private static final int testTimeOut = 300000;
+
+    private Image createSystemTrayIconImage() {
+        final BufferedImage trayImage = new BufferedImage(
+                imageSize,
+                imageSize,
+                BufferedImage.TYPE_INT_ARGB);
+
+        final Graphics2D imageGraphics = (Graphics2D) trayImage.getGraphics();
+
+        imageGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+                RenderingHints.VALUE_ANTIALIAS_ON);
+
+        imageGraphics.setColor(new Color(255, 255, 255, 0));
+        imageGraphics.fillRect(0, 0, trayImage.getWidth(),
+                trayImage.getHeight());
+
+        imageGraphics.setColor(Color.green);
+
+        int imageWidth = trayImage.getWidth() - 2 * imageInset;
+        int imageHeight = trayImage.getHeight() - 2 * imageInset;
+
+        imageGraphics.fillOval(imageInset, imageInset, imageWidth, imageHeight);
+        imageGraphics.setColor(Color.darkGray);
+        imageGraphics.drawOval(imageInset, imageInset, imageWidth, imageHeight);
+
+        return trayImage;
+    }
+
+    private PopupMenu createPopupMenu(final TrayIcon trayIcon,
+            final int menuCount) {
+
+        final PopupMenu trayIconPopupMenu = new PopupMenu();
+
+        for (int i = 1; i <= menuCount; ++i) {
+            final MenuItem popupMenuItem = new MenuItem("MenuItem_" + i);
+
+            popupMenuItem.addActionListener(new ActionListener() {
+                @Override
+                public void actionPerformed(final ActionEvent ae) {
+                    trayIcon.setPopupMenu(createPopupMenu(trayIcon,
+                            menuCount + 1));
+                }
+            });
+
+            trayIconPopupMenu.add(popupMenuItem);
+        }
+
+        return trayIconPopupMenu;
+    }
+
+    private void createSystemTrayIcons() {
+
+        final TrayIcon trayIcon = new TrayIcon(createSystemTrayIconImage());
+        trayIcon.setImageAutoSize(true);
+        trayIcon.setToolTip("Update Popup Menu items");
+
+        try {
+            trayIcon.setPopupMenu(createPopupMenu(trayIcon, 2));
+            SystemTray.getSystemTray().add(trayIcon);
+
+        } catch (AWTException ex) {
+            throw new RuntimeException("System Tray cration failed");
+        }
+    }
+
+    private void createInstructionUI() {
+        mainFrame = new Frame("Updating TrayIcon Popup Menu Item Test");
+        layout = new GridBagLayout();
+        mainControlPanel = new Panel(layout);
+        resultButtonPanel = new Panel(layout);
+
+        GridBagConstraints gbc = new GridBagConstraints();
+        String instructions
+                = "INSTRUCTIONS:"
+                + "\n   1. Click on the System Tray Icon"
+                + "\n   2. Click on any of the displayed Menu items"
+                + "\n   3. Repeat step 1 and count the number of items in the "
+                + "Menu"
+                + "\n   4. The number of items in the Menu should increase by 1"
+                + "\n   5. Repeating steps 1, 2 and 3 should not break 4th step"
+                + "\n   6. Click Fail if the 4th step is broken, Otherwise "
+                + "click Pass ";
+
+        instructionTextArea = new TextArea();
+        instructionTextArea.setText(instructions);
+        instructionTextArea.setEnabled(false);
+        instructionTextArea.setBackground(Color.white);
+
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        mainControlPanel.add(instructionTextArea, gbc);
+
+        passButton = new Button("Pass");
+        passButton.setName("Pass");
+        passButton.addActionListener(this);
+
+        failButton = new Button("Fail");
+        failButton.setName("Fail");
+        failButton.addActionListener(this);
+
+        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);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent ae) {
+        if (ae.getSource() instanceof Button) {
+            Button btn = (Button) ae.getSource();
+            switch (btn.getName()) {
+                case "Pass":
+                    testPassed = true;
+                    isInterrupted = true;
+                    mainThread.interrupt();
+                    break;
+
+                case "Fail":
+                    testPassed = false;
+                    isInterrupted = true;
+                    mainThread.interrupt();
+                    break;
+            }
+        }
+    }
+
+    private static void cleanUp() {
+        mainFrame.dispose();
+    }
+
+    public static void main(final String[] args) throws Exception {
+        if (SystemTray.isSupported()) {
+
+            UpdatePopupMenu updatePopupMenu = new UpdatePopupMenu();
+            updatePopupMenu.createInstructionUI();
+            updatePopupMenu.createSystemTrayIcons();
+
+            mainThread = Thread.currentThread();
+            try {
+                mainThread.sleep(testTimeOut);
+            } catch (InterruptedException ex) {
+                if (!testPassed) {
+                    throw new RuntimeException("Updating TrayIcon popup menu"
+                            + " items FAILED");
+                }
+            } finally {
+                cleanUp();
+            }
+
+            if (!isInterrupted) {
+                throw new RuntimeException("Test Timed out after "
+                        + testTimeOut / 1000 + " seconds");
+            }
+
+        } else {
+            System.out.println("System Tray is not supported on this platform");
+        }
+    }
+}
--- a/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/awt/dnd/DisposeFrameOnDragCrash/DisposeFrameOnDragTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,17 +56,24 @@
             }
         });
 
-        Util.waitForIdle(null);
+        Robot testRobot = null;
         try {
-            Point loc = textArea.getLocationOnScreen();
-            Util.drag(new Robot(),
-                    new Point((int) loc.x + 3, (int) loc.y + 3),
-                    new Point((int) loc.x + 40, (int) loc.y + 40),
-                    InputEvent.BUTTON1_MASK);
-        } catch (AWTException ex) {
-            throw new RuntimeException("Could not initiate a drag operation");
+            testRobot = new Robot();
+        } catch(AWTException ex) {
+            throw new RuntimeException("Error while creating Robot");
         }
-        Util.waitForIdle(null);
+
+        Util.waitForIdle(testRobot);
+
+        Point loc = textArea.getLocationOnScreen();
+        Util.drag(testRobot,
+                new Point((int) loc.x + 3, (int) loc.y + 3),
+                new Point((int) loc.x + 40, (int) loc.y + 40),
+                InputEvent.BUTTON1_MASK);
+
+        Util.waitForIdle(testRobot);
+
+        testRobot.delay(200);
     }
 
     private static void constructTestUI() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/DummyPrintTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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      6921664
+ * @summary  Verifies number of copies and the job name are passed to a
+ *           3rd party PrintService.
+ * @run      main DummyPrintTest
+ */
+import java.awt.Graphics;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.util.HashSet;
+import java.util.Set;
+import javax.print.Doc;
+import javax.print.DocFlavor;
+import javax.print.DocPrintJob;
+import javax.print.PrintException;
+import javax.print.PrintService;
+import javax.print.PrintServiceLookup;
+import javax.print.ServiceUIFactory;
+import javax.print.attribute.Attribute;
+import javax.print.attribute.AttributeSet;
+import javax.print.attribute.HashPrintJobAttributeSet;
+import javax.print.attribute.HashPrintServiceAttributeSet;
+import javax.print.attribute.PrintJobAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.PrintServiceAttribute;
+import javax.print.attribute.PrintServiceAttributeSet;
+import javax.print.attribute.standard.Copies;
+import javax.print.attribute.standard.JobName;
+import javax.print.attribute.standard.PrinterName;
+import javax.print.attribute.standard.PrinterState;
+import javax.print.event.PrintJobAttributeListener;
+import javax.print.event.PrintJobListener;
+import javax.print.event.PrintServiceAttributeListener;
+
+
+public class DummyPrintTest {
+
+    public static void main(String[] args) throws Exception {
+        // register custom print service implementation
+        String printerName = "myDummyPrintService";
+        PrintServiceLookup.registerService(new DummyPrintService(printerName));
+        // calling third party print logic
+        thirdPartyPrintLogic(printerName);
+    }
+
+    static void thirdPartyPrintLogic(String printerName) throws Exception {
+        PrinterJob printerjob = PrinterJob.getPrinterJob();
+        printerjob.setCopies(2);
+        printerjob.setJobName("myJobName");
+        printerjob.setPrintable(new DummyPrintable());
+        for (PrintService printService : PrinterJob.lookupPrintServices()) {
+            System.out.println("check printer name of service " + printService);
+            if (printerName.equals(printService.getName())) {
+                System.out.println("correct printer service do print...");
+                printerjob.setPrintService(printService);
+                printerjob.print();
+                break;
+            }
+        }
+    }
+}
+
+class DummyPrintService implements PrintService {
+    private final String _name;
+    private final Set<DocFlavor> _supportedFlavors;
+    private final PrintServiceAttributeSet _printServiceAttributeSet;
+
+    public DummyPrintService(String name) {
+        _name = name;
+        _supportedFlavors = new HashSet<DocFlavor>();
+        _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PAGEABLE);
+        _supportedFlavors.add(DocFlavor.SERVICE_FORMATTED.PRINTABLE);
+        _printServiceAttributeSet = new HashPrintServiceAttributeSet();
+        _printServiceAttributeSet.add(new PrinterName(name, null));
+        _printServiceAttributeSet.add(PrinterState.IDLE);
+    }
+
+    @Override
+    public String toString() {
+        return "Dummy Printer : " + getName();
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    @Override
+    public DocPrintJob createPrintJob() {
+        return new DummyDocPrintJob(this);
+    }
+
+    @Override
+    public boolean isDocFlavorSupported(DocFlavor flavor) {
+        return _supportedFlavors.contains(flavor);
+    }
+
+    @Override
+    public <T extends PrintServiceAttribute> T getAttribute(Class<T> category) {
+        return category.cast(_printServiceAttributeSet.get(category));
+    }
+
+    @Override
+    public PrintServiceAttributeSet getAttributes() {
+        return _printServiceAttributeSet;
+    }
+
+    @Override
+    public DocFlavor[] getSupportedDocFlavors() {
+        return _supportedFlavors.toArray(new DocFlavor[_supportedFlavors.size()]);
+    }
+
+    @Override
+    public Object getDefaultAttributeValue(Class<? extends Attribute> category) {
+        return null;
+    }
+
+    @Override
+    public ServiceUIFactory getServiceUIFactory() {
+        return null;
+    }
+
+    @Override
+    public Class<?>[] getSupportedAttributeCategories() {
+        return null;
+    }
+
+    @Override
+    public Object getSupportedAttributeValues(Class<? extends Attribute> category,
+                                    DocFlavor flavor, AttributeSet attributes) {
+        return null;
+    }
+
+    @Override
+    public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
+                                                 AttributeSet attributes) {
+        return null;
+    }
+
+    @Override
+    public boolean isAttributeCategorySupported(Class<? extends Attribute> category) {
+        return false;
+    }
+
+    @Override
+    public boolean isAttributeValueSupported(Attribute attrval,
+                                             DocFlavor flavor,
+                                             AttributeSet attributes) {
+        return false;
+    }
+
+    @Override
+    public void addPrintServiceAttributeListener(PrintServiceAttributeListener listener) {
+    }
+
+    @Override
+    public void removePrintServiceAttributeListener(PrintServiceAttributeListener listener) {
+    }
+}
+
+class DummyDocPrintJob implements DocPrintJob {
+    private static int _counter;
+    private final PrintService _printService;
+    private final PrintJobAttributeSet _printJobAttributeSet;
+
+    public DummyDocPrintJob(PrintService printService) {
+        _counter++;
+        _printService = printService;
+        _printJobAttributeSet = new HashPrintJobAttributeSet();
+    }
+
+    @Override
+    public PrintService getPrintService() {
+        return _printService;
+    }
+
+    @Override
+    public PrintJobAttributeSet getAttributes() {
+        return _printJobAttributeSet;
+    }
+
+    @Override
+    public void addPrintJobAttributeListener(PrintJobAttributeListener listener,
+                                    PrintJobAttributeSet printJobAttributeSet) {
+    }
+
+    @Override
+    public void removePrintJobAttributeListener(PrintJobAttributeListener listener) {
+    }
+
+    @Override
+    public void addPrintJobListener(PrintJobListener listener) {
+    }
+
+    @Override
+    public void removePrintJobListener(PrintJobListener listener) {
+    }
+
+    @Override
+    public void print(Doc doc,
+                      PrintRequestAttributeSet printRequestAttributeSet)
+          throws PrintException {
+        System.out.println("job name: " + printRequestAttributeSet.get(JobName.class));
+        System.out.println("copies: " + printRequestAttributeSet.get(Copies.class));
+        if(printRequestAttributeSet.get(JobName.class) == null ||
+            printRequestAttributeSet.get(Copies.class) == null) {
+            throw new RuntimeException("Copies and JobName is not passed correctly");
+        }
+    }
+}
+
+class DummyPrintable implements Printable {
+    @Override
+    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
+            throws PrinterException {
+        if (pageIndex == 0) {
+            return Printable.PAGE_EXISTS;
+        } else {
+            return Printable.NO_SUCH_PAGE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 6197099
+ * @summary Verifies PrinterJob's getUserName() throws a security exception when
+ *          username permission is not given
+ * @run main/othervm/java.security.policy=GetUserNameTest.policy GetUserNameTest
+ */
+import java.awt.print.PrinterJob;
+
+public class GetUserNameTest {
+
+    public static void main(String args[]) {
+        System.setSecurityManager(new SecurityManager());
+        PrinterJob pj = PrinterJob.getPrinterJob();
+        boolean secExcpn = false;
+        try {
+            System.out.println(pj.getUserName());
+        } catch (SecurityException ex) {
+            secExcpn = true;
+            System.out.println("SecurityException thrown as user.name permission "
+                    + "not given");
+        }
+        if (!secExcpn) {
+            throw new RuntimeException("SecurityException not thrown");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/GetUserNameTest.policy	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+ */
+grant {
+  permission java.lang.RuntimePermission "setSecurityManager";
+  permission java.lang.RuntimePermission "createSecurityManager";
+  permission java.lang.RuntimePermission "usePolicy";
+  permission java.lang.RuntimePermission "queuePrintJob";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/print/PrinterJob/PageDialogMarginTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
+ * @bug      6801613
+ * @summary  Verifies if cross-platform pageDialog and printDialog top margin
+ *           entry is working
+ * @run      main/manual PageDialogMarginTest
+ */
+import java.awt.Component;
+import java.awt.print.PageFormat;
+import java.awt.print.PrinterJob;
+import javax.print.attribute.HashPrintRequestAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
+import javax.print.attribute.standard.MediaPrintableArea;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+public class PageDialogMarginTest {
+
+    public static void main(String args[]) throws Exception {
+        String[] instructions
+                = {
+                    "Page Dialog will be shown.",
+                    "Change top(in) margin value from 1.0 to 2.0",
+                    "Then select OK."
+                };
+        SwingUtilities.invokeAndWait(() -> {
+            JOptionPane.showMessageDialog((Component) null,
+                    instructions, "Instructions",
+                    JOptionPane.INFORMATION_MESSAGE);
+        });
+        PrinterJob pj = PrinterJob.getPrinterJob();
+        try {
+            HashPrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
+            PageFormat pf;
+            pf = pj.pageDialog(aset);
+            double left = pf.getImageableX();
+            double top = pf.getImageableY();
+            System.out.println("pageDialog - left/top from pageFormat: " + left / 72
+                    + " " + top / 72);
+            System.out.println("pageDialog - left/top from attribute set: "
+                    + getPrintableXFromASet(aset) + " "
+                    + getPrintableYFromASet(aset));
+            if (top / 72 != 2.0f || getPrintableYFromASet(aset) != 2.0f) {
+                throw new RuntimeException("Top margin value not updated");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    static double getPrintableXFromASet(PrintRequestAttributeSet aset) {
+        try {
+            return ((MediaPrintableArea) aset.get(
+                    MediaPrintableArea.class)).getX(MediaPrintableArea.INCH);
+        } catch (Exception e) {
+            return -1.0;
+        }
+    }
+
+    static double getPrintableYFromASet(PrintRequestAttributeSet aset) {
+        try {
+            return ((MediaPrintableArea) aset.get(
+                    MediaPrintableArea.class)).getY(MediaPrintableArea.INCH);
+        } catch (Exception e) {
+            return -1.0;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/AnonymousClassBeanPropertyTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,867 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.beans.BeanInfo;
+import java.beans.BeanProperty;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyDescriptor;
+
+import java.util.Arrays;
+
+
+/**
+ * @test
+ * @bug 8132973 8132732 8155013
+ * @summary Some check for BeanProperty annotation
+ * @author a.stepanov
+ * @run main AnonymousClassBeanPropertyTest
+ */
+
+
+public class AnonymousClassBeanPropertyTest {
+
+    private final static String  DESCRIPTION = "TEST";
+    private final static boolean BOUND       = true;
+    private final static boolean EXPERT      = false;
+    private final static boolean HIDDEN      = true;
+    private final static boolean PREFERRED   = false;
+    private final static boolean REQUIRED    = true;
+    private final static boolean UPDATE      = false;
+
+    private final static double X = java.lang.Math.PI;
+
+    private final static String
+        V_NAME  = "java.lang.Math.PI",
+        V_SHORT = "PI",
+        V = Double.toString(X);
+
+    private final static String DESCRIPTION_2 = "XYZ";
+
+
+    // ---------- test cases (interfaces) ----------
+
+    private interface IGet {
+        double getX();
+    }
+
+    private interface ISet {
+        void setX(double v);
+    }
+
+    private interface IGetByIndex {
+        double getX(int i);
+    }
+
+    private interface ISetByIndex {
+        void setX(int i, double v);
+    }
+
+    private interface IGetArray {
+        double[] getX();
+    }
+
+    private interface ISetArray {
+        void setX(double a[]);
+    }
+
+    private interface IGetBoth {
+        double   getX(int i);
+        double[] getX();
+    }
+
+    private interface ISetBoth {
+        void setX(int i, double v);
+        void setX(double a[]);
+    }
+
+    private interface IGetSet {
+        double getX();
+        void setX(double v);
+    }
+
+    private interface IGetSetByIndex {
+        double getX(int i);
+        void setX(int i, double v);
+    }
+
+    private interface IGetSetBoth {
+        double   getX(int i);
+        double[] getX();
+        void setX(int i, double v);
+        void setX(double a[]);
+    }
+
+
+    // ---------- checks ----------
+
+    private static boolean check(String what, boolean v, boolean ref) {
+
+        boolean ok = (v == ref);
+        if (!ok) { System.out.println(
+            "invalid " + what + ": " + v + ", expected: " + ref); }
+        return ok;
+    }
+
+    private static boolean checkInfo(Class<?> c, String what) {
+
+        BeanInfo i;
+        try { i = Introspector.getBeanInfo(c, Object.class); }
+        catch (IntrospectionException e) { throw new RuntimeException(e); }
+
+        System.out.println("\nchecking info for " + what);
+
+        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+        int nd = descriptors.length;
+        if (nd != 1) {
+            System.out.println("invalid number of descriptors: " + nd);
+            return false;
+        }
+
+        PropertyDescriptor d = descriptors[0];
+
+        String descr = d.getShortDescription();
+        boolean ok = descr.equals(DESCRIPTION);
+        if (!ok) { System.out.println("invalid description: " + descr +
+                ", expected: " + DESCRIPTION); }
+
+        ok &= check("isBound",  d.isBound(),  BOUND);
+        ok &= check("isExpert", d.isExpert(), EXPERT);
+        ok &= check("isHidden", d.isHidden(), HIDDEN);
+        ok &= check("isPreferred", d.isPreferred(), PREFERRED);
+        ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
+        ok &= check("visualUpdate",
+            (boolean) d.getValue("visualUpdate"), UPDATE);
+
+        Object vals[] = (Object[]) d.getValue("enumerationValues");
+        if (vals == null) {
+            System.out.println("null enumerationValues");
+            return false;
+        }
+
+        if (vals.length == 0) {
+            System.out.println("empty enumerationValues");
+            return false;
+        }
+
+        boolean okVals = (
+            (vals.length == 3) &&
+             vals[0].toString().equals(V_SHORT) &&
+             vals[1].toString().equals(V)       &&
+             vals[2].toString().equals(V_NAME));
+
+        if (!okVals) {
+            System.out.println("invalid enumerationValues:");
+            for (Object v: vals) { System.out.println(v.toString()); }
+        }
+
+        return (ok && okVals);
+    }
+
+    private static boolean checkAlternativeInfo(Class<?> c, String what) {
+
+        BeanInfo i;
+        try { i = Introspector.getBeanInfo(c, Object.class); }
+        catch (IntrospectionException e) { throw new RuntimeException(e); }
+
+        System.out.println("checking alternative info for " + what);
+
+        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+        int nd = descriptors.length;
+        if (nd != 1) {
+            System.out.println("invalid number of descriptors: " + nd);
+            return false;
+        }
+
+        PropertyDescriptor d = descriptors[0];
+
+        String descr = d.getShortDescription();
+        boolean ok = descr.equals(DESCRIPTION_2);
+        if (!ok) { System.out.println("invalid alternative description: " +
+            descr + ", expected: " + DESCRIPTION_2); }
+
+        ok &= check("isBound",  d.isBound(),  !BOUND);
+        ok &= check("isExpert", d.isExpert(), !EXPERT);
+        ok &= check("isHidden", d.isHidden(), !HIDDEN);
+        ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
+        ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
+        ok &= check("visualUpdate",
+            (boolean) d.getValue("visualUpdate"), !UPDATE);
+
+        Object vals[] = (Object[]) d.getValue("enumerationValues");
+        if (vals != null || vals.length > 0) {
+            System.out.println("non-empty enumerationValues");
+            return false;
+        }
+
+        return ok;
+    }
+
+
+
+    // ---------- run tests ----------
+
+    public static void main(String[] args) {
+
+        boolean passed = true, ok, ok2;
+
+        //----------------------------------------------------------------------
+
+        IGet testGet = new IGet() {
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX() { return X; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGet.getClass(), "IGet");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        //----------------------------------------------------------------------
+
+        ISet testSet = new ISet() {
+
+            private double x;
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(double v) { x = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSet.getClass(), "ISet");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        //----------------------------------------------------------------------
+
+        IGetByIndex testGetByIndex = new IGetByIndex() {
+
+            private final double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) { return x[i]; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetByIndex.getClass(), "IGetByIndex");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        //----------------------------------------------------------------------
+
+        ISetByIndex testSetByIndex = new ISetByIndex() {
+
+            private final double x[] = {X, X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSetByIndex.getClass(), "ISetByIndex");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        //----------------------------------------------------------------------
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        IGetArray testGetArray = new IGetArray() {
+
+            private final double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double[] getX() { return x; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetArray.getClass(), "IGetArray");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        //----------------------------------------------------------------------
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        ISetArray testSetArray = new ISetArray() {
+
+            private double x[];
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(double a[]) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSetArray.getClass(), "ISetArray");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        //----------------------------------------------------------------------
+
+        IGetBoth testGetBoth_1 = new IGetBoth() {
+
+            private final double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) { return x[i]; }
+            @Override
+            public double[] getX() { return x; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetBoth_1.getClass(), "IGetBoth-1");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        IGetBoth testGetBoth_2 = new IGetBoth() {
+
+            private final double x[] = {X, X};
+
+            @Override
+            public double getX(int i) { return x[i]; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double[] getX() { return x; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetBoth_2.getClass(), "IGetBoth-2");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        // TODO: please uncomment/update after 8132732 fix
+        /*
+        IGetBoth testGetBoth_3 = new IGetBoth() {
+
+            private final double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) { return x[i]; }
+            @BeanProperty(
+                description  = DESCRIPTION_2,
+                bound        = !BOUND,
+                expert       = !EXPERT,
+                hidden       = !HIDDEN,
+                preferred    = !PREFERRED,
+                required     = !REQUIRED,
+                visualUpdate = !UPDATE)
+            @Override
+            public double[] getX() { return x; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetBoth_3.getClass(), "IGetBoth-3");
+        System.out.println("OK = " + ok);
+        ok2 = checkAlternativeInfo(testGetBoth_3.getClass(), "IGetBoth-3");
+        System.out.println("OK = " + ok2);
+        passed = passed && ok && ok2;
+        */
+
+        //----------------------------------------------------------------------
+
+        ISetBoth testSetBoth_1 = new ISetBoth() {
+
+            private double x[] = new double[3];
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSetBoth_1.getClass(), "ISetBoth-1");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        ISetBoth testSetBoth_2 = new ISetBoth() {
+
+            private double x[] = new double[3];
+
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSetBoth_2.getClass(), "ISetBoth-2");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        // TODO: please uncomment/update after 8132732 fix
+        /*
+        ISetBoth testSetBoth_3 = new ISetBoth() {
+
+            private double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @BeanProperty(
+                description  = DESCRIPTION_2,
+                bound        = !BOUND,
+                expert       = !EXPERT,
+                hidden       = !HIDDEN,
+                preferred    = !PREFERRED,
+                required     = !REQUIRED,
+                visualUpdate = !UPDATE)
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testSetBoth_3.getClass(), "ISetBoth-3");
+        System.out.println("OK = " + ok);
+        ok2 = checkAlternativeInfo(testSetBoth_3.getClass(), "ISetBoth-3");
+        System.out.println("OK = " + ok2);
+        passed = passed && ok && ok2;
+        */
+
+        //----------------------------------------------------------------------
+
+        IGetSet testGetSet_1 = new IGetSet() {
+
+            private double x;
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX() { return x; }
+            @Override
+            public void setX(double v) { x = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSet_1.getClass(), "IGetSet-1");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+
+        IGetSet testGetSet_2 = new IGetSet() {
+
+            private double x;
+
+            @Override
+            public double getX() { return x; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(double v) { x = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSet_2.getClass(), "IGetSet-2");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        // TODO: please uncomment/update after 8132973 fix
+        /*
+        IGetSet testGetSet_3 = new IGetSet() {
+
+            private double x;
+
+            @Override
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            public double getX() { return x; }
+            @BeanProperty(
+                description  = DESCRIPTION_2,
+                bound        = !BOUND,
+                expert       = !EXPERT,
+                hidden       = !HIDDEN,
+                preferred    = !PREFERRED,
+                required     = !REQUIRED,
+                visualUpdate = !UPDATE)
+            @Override
+            public void setX(double v) { x = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSet_3.getClass(), "IGetSet-3");
+        System.out.println("OK = " + ok);
+        ok2 = checkAlternativeInfo(testGetSet_3.getClass(), "IGetSet-3");
+        System.out.println("OK = " + ok2);
+        passed = passed && ok && ok2;
+        */
+
+        //----------------------------------------------------------------------
+
+        IGetSetByIndex testGetSetByIndex_1 = new IGetSetByIndex() {
+
+            private final double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) { return x[i]; }
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetByIndex_1.getClass(), "IGetSetByIndex-1");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+
+        IGetSetByIndex testGetSetByIndex_2 = new IGetSetByIndex() {
+
+            private final double x[] = {X, X};
+
+            @Override
+            public double getX(int i) { return x[i]; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetByIndex_2.getClass(), "IGetSetByIndex-2");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+
+        // TODO: please uncomment/update after 8132973 fix
+        /*
+        IGetSetByIndex testGetSetByIndex_3 = new IGetSetByIndex() {
+
+            private double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) {
+                return x[i];
+            }
+            @BeanProperty(
+                description  = DESCRIPTION_2,
+                bound        = !BOUND,
+                expert       = !EXPERT,
+                hidden       = !HIDDEN,
+                preferred    = !PREFERRED,
+                required     = !REQUIRED,
+                visualUpdate = !UPDATE)
+            @Override
+            public void setX(int i, double v) {
+                x[i] = v;
+            }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetByIndex_3.getClass(), "IGetSetByIndex-3");
+        System.out.println("OK = " + ok);
+        ok2 = checkAlternativeInfo(
+            testGetSetByIndex_3.getClass(), "IGetSetByIndex-3");
+        System.out.println("OK = " + ok2);
+        passed = passed && ok && ok2;
+        */
+
+        //----------------------------------------------------------------------
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        IGetSetBoth testGetSetBoth_1 = new IGetSetBoth() {
+
+            private double x[] = {X, X};
+
+            @Override
+            public double getX(int i) { return x[i]; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double[] getX() { return x; }
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetBoth_1.getClass(), "IGetSetBoth-1");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        // TODO: please uncomment/update after 8155013 fix
+        /*
+        IGetSetBoth testGetSetBoth_2 = new IGetSetBoth() {
+
+            private double x[] = {X, X};
+
+            @Override
+            public double getX(int i) { return x[i]; }
+            @Override
+            public double[] getX() { return x; }
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetBoth_2.getClass(), "IGetSetBoth-2");
+        System.out.println("OK = " + ok);
+        passed = passed && ok;
+        */
+
+        // TODO: please uncomment/update after 8132973 fix
+        /*
+        IGetSetBoth testGetSetBoth_3 = new IGetSetBoth() {
+
+            private double x[] = {X, X};
+
+            @BeanProperty(
+                description  = DESCRIPTION,
+                bound        = BOUND,
+                expert       = EXPERT,
+                hidden       = HIDDEN,
+                preferred    = PREFERRED,
+                required     = REQUIRED,
+                visualUpdate = UPDATE,
+                enumerationValues = {V_NAME})
+            @Override
+            public double getX(int i) { return x[i]; }
+            @Override
+            public double[] getX() { return x; }
+            @Override
+            public void setX(int i, double v) { x[i] = v; }
+            @BeanProperty(
+                description  = DESCRIPTION_2,
+                bound        = !BOUND,
+                expert       = !EXPERT,
+                hidden       = !HIDDEN,
+                preferred    = !PREFERRED,
+                required     = !REQUIRED,
+                visualUpdate = !UPDATE)
+            @Override
+            public void setX(double[] a) { x = Arrays.copyOf(a, a.length); }
+
+            public void addPropertyChangeListener(PropertyChangeListener l)    {}
+            public void removePropertyChangeListener(PropertyChangeListener l) {}
+        };
+        ok = checkInfo(testGetSetBoth_3.getClass(), "IGetSetBoth-3");
+        System.out.println("OK = " + ok);
+        ok2 = checkAlternativeInfo(
+            testGetSetBoth_3.getClass(), "IGetSetBoth-3");
+        System.out.println("OK = " + ok2);
+        passed = passed && ok && ok2;
+        */
+
+        if (!passed) { throw new RuntimeException("test failed"); }
+        System.out.println("\ntest passed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/BeanPropertyTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.beans.BeanInfo;
+import java.beans.BeanProperty;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyDescriptor;
+
+import java.util.Arrays;
+
+
+/**
+ * @test
+ * @bug 8132703 8132163 8132732 8132973 8154756 8132888
+ * @summary Some check for BeanProperty annotation
+ * @author a.stepanov
+ * @run main BeanPropertyTest
+ */
+
+
+public class BeanPropertyTest {
+
+    private final static String  DESCRIPTION = "TEST";
+    private final static boolean BOUND       = true;
+    private final static boolean EXPERT      = false;
+    private final static boolean HIDDEN      = true;
+    private final static boolean PREFERRED   = false;
+    private final static boolean REQUIRED    = true;
+    private final static boolean UPDATE      = false;
+    private final static String
+        V_NAME  = "javax.swing.SwingConstants.TOP",
+        V_SHORT = "TOP",
+        V = Integer.toString(javax.swing.SwingConstants.TOP);
+    private final static int X = javax.swing.SwingConstants.TOP;
+
+    private final static String DESCRIPTION_2 = "XYZ";
+
+
+    // ---------- test cases ----------
+
+    public static class G01 {
+
+        private final static String TESTCASE = "arbitrary getter name";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int get1() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class S01 {
+
+        private final static String TESTCASE = "arbitrary setter name";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setXXXXX(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132703
+    public static class G02 {
+
+        private final static String TESTCASE = "arbitrary getter name";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int get() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132703
+    public static class S02 {
+
+        private final static String TESTCASE = "arbitrary setter name";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void set(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132703
+    public static class G03 {
+
+        private final static String TESTCASE = "arbitrary getter name";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int GetX() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132703
+    public static class S03 {
+
+        private final static String TESTCASE = "arbitrary setter name";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void SetX(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132163
+    public static class G04 {
+
+        private final static String TESTCASE = "arbitrary getter return type";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public Object getX() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132163
+    public static class S04 {
+
+        private final static String TESTCASE = "arbitrary setter argument type";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(short v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G05 {
+
+        private final static String TESTCASE =
+            "annotated getter + arbitrary setter argument type";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getX() { return x; }
+        public void setX(short v) { x = v; }
+
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132163
+    public static class S05 {
+
+        private final static String TESTCASE =
+            "annotated setter + arbitrary getter return type";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int v) { x = v; }
+        public Object getX() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G06 {
+
+        private final static String TESTCASE = "indexed getter";
+
+        private final int x[] = {X, X, X};
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getX(int i) { return x[i]; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class S06 {
+
+        private final static String TESTCASE = "indexed setter";
+
+        private final int x[] = {X, X, X};
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int i, int v) { x[i] = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G07 {
+
+        private final static String TESTCASE =
+            "indexed (annotated) + non-indexed getters";
+
+        private final int x[] = {X, X, X};
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getX(int i) { return x[i]; }
+
+        public int[] getX() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class S07 {
+
+        private final static String TESTCASE =
+            "indexed (annotated) + non-indexed setters";
+
+        private int x[] = new int[3];
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int i, int v) { x[i] = v; }
+
+        public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132732
+    public static class G08 {
+
+        private final static String TESTCASE =
+            "non-indexed (annotated) + indexed getters";
+
+        private final int x[] = {X, X, X};
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int[] getX() { return x; }
+
+        public int getX(int i) { return x[i]; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132732
+    public static class S08 {
+
+        private final static String TESTCASE =
+            "non-indexed (annotated) + indexed setters";
+
+        private int x[] = new int[3];
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+        public void setX(int i, int v) { x[i] = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132732
+    public static class G09 {
+
+        private final static String TESTCASE = "two annotated getters";
+
+        private final int x[] = {X, X, X};
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int[] getX() { return x; }
+
+        @BeanProperty(
+            description  = DESCRIPTION_2,
+            bound        = !BOUND,
+            expert       = !EXPERT,
+            hidden       = !HIDDEN,
+            preferred    = !PREFERRED,
+            required     = !REQUIRED,
+            visualUpdate = !UPDATE)
+        public int getX(int i) { return x[i]; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132732
+    public static class S09 {
+
+        private final static String TESTCASE = "two annotated setters";
+
+        private int x[] = new int[3];
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int a[]) { x = Arrays.copyOf(a, a.length); }
+
+        @BeanProperty(
+            description  = DESCRIPTION_2,
+            bound        = !BOUND,
+            expert       = !EXPERT,
+            hidden       = !HIDDEN,
+            preferred    = !PREFERRED,
+            required     = !REQUIRED,
+            visualUpdate = !UPDATE)
+        public void setX(int i, int v) { x[i] = v; }
+
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G10 {
+
+        private final static String TESTCASE =
+            "getter + similarly named field";
+
+        public int prop, Prop, setProp, getProp;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getProp() { return X; }
+        public void setProp(int v) { prop = Prop = setProp = getProp = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class S10 {
+
+        private final static String TESTCASE =
+            "setter + similarly named field";
+
+        public int prop, Prop, setProp, getProp;
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getProp() { return x; }
+        public void setProp(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G11 {
+
+        private final static String TESTCASE =
+            "getter + similarly named field of other type";
+
+        public Object prop, Prop, setProp, getProp;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getProp() { return X; }
+        public void setProp(int v) { prop = Prop = setProp = getProp = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class S11 {
+
+        private final static String TESTCASE =
+            "setter + similarly named field of other type";
+
+        public String prop, Prop, setProp, getProp;
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getProp() { return x; }
+        public void setProp(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132163
+    public static class G12 {
+
+        private final static String TESTCASE =
+            "getter having wrapper class return type";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public Integer getProp() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132163
+    public static class S12 {
+
+        private final static String TESTCASE =
+            "setter with wrapper class argument type";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(Integer v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class G13 {
+
+        private final static String TESTCASE =
+            "getter + overloading methods";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getX() { return x; }
+        public int getX(boolean arg) { return (arg ? x : 0); }
+        public int getX(int ... dummy) { return 0; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8154756
+    public static class S13 {
+
+        private final static String TESTCASE =
+            "setter + overloading methods";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int v) { x = v; }
+        public int  setX() { return (x = X); }
+        public void setX(int ... dummy) {}
+        private void setX(Object ... dummy) {}
+
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+
+    // JDK-8132888
+    public static class G14 {
+
+        private final static String TESTCASE = "non-public getter";
+
+        private final int x = X;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        int getX() { return x; } // getter is not public
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132888
+    public static class S14 {
+
+        private final static String TESTCASE = "non-public setter";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        void setX(int v) { x = v; } // setter is not public
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class getX {
+
+        private final static String TESTCASE =
+            "class name coincides with getter name";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int  getX() { return x; }
+        public void setX(int v) { x = v; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class setX {
+
+        private final static String TESTCASE =
+            "class name coincides with setter name";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public void setX(int v) { x = v; }
+        public int  getX() { return x; }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    // JDK-8132973
+    public static class GS {
+
+        private final static String TESTCASE =
+            "both getter and setter are annotated";
+
+        private int x;
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE,
+            enumerationValues = {V_NAME})
+        public int getX() { return x; }
+
+        @BeanProperty(
+            description  = DESCRIPTION_2,
+            bound        = !BOUND,
+            expert       = !EXPERT,
+            hidden       = !HIDDEN,
+            preferred    = !PREFERRED,
+            required     = !REQUIRED,
+            visualUpdate = !UPDATE)
+        public void setX(int v) { x = v; }
+
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class Self {
+
+        private final static String TESTCASE = "trivial singleton";
+
+        private static Self instance = null;
+        private Self() {}
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE)
+        public Self getSelf() {
+            if (instance == null) { instance = new Self(); }
+            return instance;
+        }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+    public static class SelfArr {
+
+        private final static String TESTCASE = "trivial singleton + array";
+
+        private static SelfArr arr[] = null;
+        private SelfArr() {}
+
+        @BeanProperty(
+            description  = DESCRIPTION,
+            bound        = BOUND,
+            expert       = EXPERT,
+            hidden       = HIDDEN,
+            preferred    = PREFERRED,
+            required     = REQUIRED,
+            visualUpdate = UPDATE)
+        public SelfArr[] getSelfArr() {
+            if (arr == null) { arr = new SelfArr[]{new SelfArr(), new SelfArr()}; }
+            return arr;
+        }
+
+        public void addPropertyChangeListener(PropertyChangeListener l)    {}
+        public void removePropertyChangeListener(PropertyChangeListener l) {}
+    }
+
+
+    // ---------- checks ----------
+
+    private static boolean check(String what, boolean v, boolean ref) {
+
+        boolean ok = (v == ref);
+        if (!ok) { System.out.println(
+            "invalid " + what + ": " + v + ", expected: " + ref); }
+        return ok;
+    }
+
+    private static boolean checkInfo(BeanInfo i, boolean checkVals) {
+
+        System.out.println("checking info...");
+
+        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+        int nd = descriptors.length;
+        if (nd != 1) {
+            System.out.println("invalid number of descriptors: " + nd);
+            return false;
+        }
+
+        PropertyDescriptor d = descriptors[0];
+
+        String descr = d.getShortDescription();
+        boolean ok = descr.equals(DESCRIPTION);
+        if (!ok) { System.out.println("invalid description: " + descr +
+                ", expected: " + DESCRIPTION); }
+
+        ok &= check("isBound",  d.isBound(),  BOUND);
+        ok &= check("isExpert", d.isExpert(), EXPERT);
+        ok &= check("isHidden", d.isHidden(), HIDDEN);
+        ok &= check("isPreferred", d.isPreferred(), PREFERRED);
+        ok &= check("required", (boolean) d.getValue("required"), REQUIRED);
+        ok &= check("visualUpdate",
+            (boolean) d.getValue("visualUpdate"), UPDATE);
+
+        if (!checkVals) { return ok; }
+
+        Object vals[] = (Object[]) d.getValue("enumerationValues");
+        if (vals == null) {
+            System.out.println("null enumerationValues");
+            return false;
+        }
+
+        boolean okVals = (
+            (vals.length == 3) &&
+             vals[0].toString().equals(V_SHORT) &&
+             vals[1].toString().equals(V)       &&
+             vals[2].toString().equals(V_NAME));
+
+        if (!okVals) { System.out.println("invalid enumerationValues"); }
+
+        return (ok && okVals);
+    }
+
+    private static boolean checkAlternativeInfo(BeanInfo i) {
+
+        System.out.println("checking alternative info...");
+
+        PropertyDescriptor descriptors[] = i.getPropertyDescriptors();
+        int nd = descriptors.length;
+        if (nd != 1) {
+            System.out.println("invalid number of descriptors: " + nd);
+            return false;
+        }
+
+        PropertyDescriptor d = descriptors[0];
+
+        String descr = d.getShortDescription();
+        boolean ok = descr.equals(DESCRIPTION_2);
+        if (!ok) { System.out.println("invalid alternative description: " +
+            descr + ", expected: " + DESCRIPTION_2); }
+
+        ok &= check("isBound",  d.isBound(),  !BOUND);
+        ok &= check("isExpert", d.isExpert(), !EXPERT);
+        ok &= check("isHidden", d.isHidden(), !HIDDEN);
+        ok &= check("isPreferred", d.isPreferred(), !PREFERRED);
+        ok &= check("required", (boolean) d.getValue("required"), !REQUIRED);
+        ok &= check("visualUpdate",
+            (boolean) d.getValue("visualUpdate"), !UPDATE);
+
+        Object vals[] = (Object[]) d.getValue("enumerationValues");
+        if (vals != null || vals.length > 0) {
+            System.out.println("non-null enumerationValues");
+            return false;
+        }
+
+        return ok;
+    }
+
+
+    private static boolean checkAlternative(Class<?> c) {
+        return (
+            c.equals(G09.class) ||
+            c.equals(S09.class) ||
+            c.equals(GS.class));
+    }
+
+    private static boolean ignoreVals(Class<?> c) {
+        return (c.equals(Self.class) || c.equals(SelfArr.class));
+    }
+
+
+    // ---------- run test ----------
+
+    public static void main(String[] args) throws Exception {
+
+        Class<?> cases[] = {
+
+            G01.class, S01.class,
+            // G02.class, S02.class, // TODO: please update after 8132703 fix
+            // G03.class, S03.class, // TODO: please update after 8132703 fix
+            // G04.class, S04.class, // TODO: please update after 8132163 fix
+            G05.class, // S05.class, // TODO: please update after 8132163 fix
+            G06.class, S06.class,
+            G07.class, S07.class,
+            // G08.class, S08.class, // TODO: please update after 8132732 fix
+            // G09.class, S09.class, // TODO: please update after 8132732 fix
+            G10.class, S10.class,
+            G11.class, S11.class,
+            // G12.class, S12.class, // TODO: please update after 8132163 fix
+            G13.class, // S13.class, // TODO: please update after 8154756 fix
+            // G14.class, S14.class, // TODO: please update after 8132888 fix or
+                                     // remove these cases if it is not an issue
+            // GS.class, // TODO: please update after 8132973 fix
+            getX.class, setX.class,
+            Self.class, SelfArr.class
+        };
+
+        boolean passed = true;
+
+        for (Class<?> c: cases) {
+
+            java.lang.reflect.Field f = c.getDeclaredField("TESTCASE");
+            f.setAccessible(true);
+            String descr = f.get(c).toString();
+
+            System.out.println("\n" + c.getSimpleName() + " (" + descr + "):");
+            BeanInfo i;
+            try { i = Introspector.getBeanInfo(c, Object.class); }
+            catch (IntrospectionException e) { throw new RuntimeException(e); }
+            boolean ok = checkInfo(i, !ignoreVals(c));
+            if (checkAlternative(c)) {
+                ok |= checkAlternativeInfo(i);
+            }
+            System.out.println(ok ? "OK" : "NOK");
+            passed = passed && ok;
+        }
+
+        if (!passed) { throw new RuntimeException("test failed"); }
+        System.out.println("\ntest passed");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/String/concat/WithSecurityManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.Permission;
+
+/**
+ * @test
+ * @summary String concatenation fails with a custom SecurityManager that uses concatenation
+ * @bug 8155090
+ *
+ * @compile WithSecurityManager.java
+ *
+ * @run main/othervm -Xverify:all WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB                  WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED            WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED            WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=BC_SB_SIZED_EXACT      WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_SB_SIZED_EXACT      WithSecurityManager
+ * @run main/othervm -Xverify:all -Djava.lang.invoke.stringConcat=MH_INLINE_SIZED_EXACT  WithSecurityManager
+*/
+public class WithSecurityManager {
+    public static void main(String[] args) throws Throwable {
+        SecurityManager sm = new SecurityManager() {
+            @Override
+            public void checkPermission(Permission perm) {
+                String abc = "abc";
+                String full = abc + "def";
+            }
+        };
+        System.setSecurityManager(sm);
+        ClassLoader cl = new ClassLoader() {};
+    }
+}
--- a/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/Logger/custom/CustomLoggerTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -46,6 +46,8 @@
 import java.lang.System.Logger;
 import java.lang.System.Logger.Level;
 import java.util.stream.Stream;
+import java.lang.reflect.Module;
+import java.security.AllPermission;
 
 /**
  * @test
@@ -70,6 +72,12 @@
             return  new AtomicBoolean(false);
         }
     };
+    static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
+        @Override
+        protected AtomicBoolean initialValue() {
+            return  new AtomicBoolean(false);
+        }
+    };
 
     public static class MyBundle extends ResourceBundle {
 
@@ -241,7 +249,7 @@
         }
 
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             // We should check the permission to obey the API contract, but
             // what happens if we don't?
             // This is the main difference compared with what we test in
@@ -251,8 +259,13 @@
                 sm.checkPermission(SimplePolicy.LOGGERFINDER_PERMISSION);
             }
 
-            PrivilegedAction<ClassLoader> pa = () -> caller.getClassLoader();
-            ClassLoader callerLoader = AccessController.doPrivileged(pa);
+            final boolean before = allowAll.get().getAndSet(true);
+            final ClassLoader callerLoader;
+            try {
+                callerLoader = caller.getClassLoader();
+            } finally {
+                allowAll.get().set(before);
+            }
             if (callerLoader == null) {
                 return system.computeIfAbsent(name, (n) -> new LoggerImpl(n));
             } else {
@@ -267,7 +280,7 @@
 
     static void setSecurityManager() {
         if (System.getSecurityManager() == null) {
-            Policy.setPolicy(new SimplePolicy(allowControl));
+            Policy.setPolicy(new SimplePolicy(allowControl, allowAll));
             System.setSecurityManager(new SecurityManager());
         }
     }
@@ -284,9 +297,9 @@
         BaseLoggerFinder provider =
                 BaseLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
         BaseLoggerFinder.LoggerImpl appSink =
-                BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class));
+                BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class.getModule()));
         BaseLoggerFinder.LoggerImpl sysSink =
-                BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class));
+                BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule()));
 
 
         Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {
@@ -695,34 +708,46 @@
         static final RuntimePermission LOGGERFINDER_PERMISSION =
                 new RuntimePermission("loggerFinder");
         final Permissions permissions;
+        final Permissions controlPermissions;
         final Permissions allPermissions;
         final ThreadLocal<AtomicBoolean> allowControl;
-        public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl) {
+        final ThreadLocal<AtomicBoolean> allowAll;
+        public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAll) {
             this.allowControl = allowControl;
+            this.allowAll = allowAll;
             permissions = new Permissions();
 
             // these are used for configuring the test itself...
+            controlPermissions = new Permissions();
+            controlPermissions.add(LOGGERFINDER_PERMISSION);
+
+            // these are used for simulating a doPrivileged call from
+            // a class in the BCL
             allPermissions = new Permissions();
-            allPermissions.add(LOGGERFINDER_PERMISSION);
+            allPermissions.add(new AllPermission());
+
+        }
+
+        Permissions permissions() {
+            if (allowAll.get().get()) return allPermissions;
+            if (allowControl.get().get()) return controlPermissions;
+            return permissions;
 
         }
 
         @Override
         public boolean implies(ProtectionDomain domain, Permission permission) {
-            if (allowControl.get().get()) return allPermissions.implies(permission);
-            return permissions.implies(permission);
+            return permissions().implies(permission);
         }
 
         @Override
         public PermissionCollection getPermissions(CodeSource codesource) {
-            return new PermissionsBuilder().addAll(allowControl.get().get()
-                    ? allPermissions : permissions).toPermissions();
+            return new PermissionsBuilder().addAll(permissions()).toPermissions();
         }
 
         @Override
         public PermissionCollection getPermissions(ProtectionDomain domain) {
-            return new PermissionsBuilder().addAll(allowControl.get().get()
-                    ? allPermissions : permissions).toPermissions();
+            return new PermissionsBuilder().addAll(permissions()).toPermissions();
         }
     }
 }
--- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -25,13 +25,14 @@
 import java.security.PrivilegedAction;
 import java.lang.System.LoggerFinder;
 import java.lang.System.Logger;
+import java.lang.reflect.Module;
 
 public  class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
 
     static final RuntimePermission LOGGERFINDER_PERMISSION =
                 new RuntimePermission("loggerFinder");
     @Override
-    public Logger getLogger(String name, Class<?> caller) {
+    public Logger getLogger(String name, Module caller) {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(LOGGERFINDER_PERMISSION);
--- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/BaseLoggerFinderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -182,8 +182,8 @@
         TestLoggerFinder.LoggerImpl appLogger1 = null;
         try {
             appLogger1 =
-                TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class));
-            loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)");
+                TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule()));
+            loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a logger without permission");
             }
@@ -199,8 +199,8 @@
             allowControl.get().set(true);
             try {
                 appLogger1 =
-                    TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class));
-                    loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)");
+                    TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class.getModule()));
+                    loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -208,8 +208,8 @@
 
         TestLoggerFinder.LoggerImpl sysLogger1 = null;
         try {
-            sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class));
-            loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)");
+            sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule()));
+            loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -224,8 +224,8 @@
             final boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class));
-                loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)");
+                sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule()));
+                loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -254,8 +254,8 @@
         //   callers and non system callers
         Logger appLogger2 = null;
         try {
-            appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class);
-            loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)");
+            appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule());
+            loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a logger without permission");
             }
@@ -270,8 +270,8 @@
             final boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class);
-                loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)");
+                appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class.getModule());
+                loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -279,8 +279,8 @@
 
         Logger sysLogger2 = null;
         try {
-            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)");
+            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -295,8 +295,8 @@
             final boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-                loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class))");
+                sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+                loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule()))");
             } finally {
                 allowControl.get().set(old);
             }
--- a/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/BaseLoggerFinderTest/TestLoggerFinder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,6 +30,7 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Supplier;
 import java.lang.System.Logger;
+import java.lang.reflect.Module;
 
 /**
  * What our test provider needs to implement.
@@ -176,6 +177,6 @@
         }
     }
 
-    public Logger getLogger(String name, Class<?> caller);
-    public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class<?> caller);
+    public Logger getLogger(String name, Module caller);
+    public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
 }
--- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -364,8 +364,8 @@
 
         Logger appLogger1 = null;
         try {
-            appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class);
-            loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")");
+            appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule());
+            loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a logger without permission");
             }
@@ -380,8 +380,8 @@
             boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class);
-                loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")");
+                appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class.getModule());
+                loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", DefaultLoggerFinderTest.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -389,8 +389,8 @@
 
         Logger sysLogger1 = null;
         try {
-            sysLogger1 = provider.getLogger("foo", Thread.class);
-            loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")");
+            sysLogger1 = provider.getLogger("foo", Thread.class.getModule());
+            loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -405,8 +405,8 @@
             boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                sysLogger1 = provider.getLogger("foo", Thread.class);
-                loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")");
+                sysLogger1 = provider.getLogger("foo", Thread.class.getModule());
+                loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -417,8 +417,8 @@
 
         Logger appLogger2 = null;
         try {
-            appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class);
-            loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)");
+            appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule());
+            loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a logger without permission");
             }
@@ -433,8 +433,8 @@
             boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class);
-                loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)");
+                appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class.getModule());
+                loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, DefaultLoggerFinderTest.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
@@ -442,8 +442,8 @@
 
         Logger sysLogger2 = null;
         try {
-            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-            loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)");
+            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -458,8 +458,8 @@
             boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-                loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)");
+                sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+                loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             } finally {
                 allowControl.get().set(old);
             }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseDefaultLoggerFinderTest/BaseDefaultLoggerFinderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -55,6 +55,7 @@
 import jdk.internal.logger.DefaultLoggerFinder;
 import jdk.internal.logger.SimpleConsoleLogger;
 import sun.util.logging.PlatformLogger;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -112,10 +113,10 @@
         public final static AtomicLong sequencer = new AtomicLong();
 
 
-        public Logger getLogger(String name, Class<?> caller);
-        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class<?> caller);
-        void setLevel(Logger logger, Level level, Class<?> caller);
-        void setLevel(Logger logger, PlatformLogger.Level level, Class<?> caller);
+        public Logger getLogger(String name, Module caller);
+        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
+        void setLevel(Logger logger, Level level, Module caller);
+        void setLevel(Logger logger, PlatformLogger.Level level, Module caller);
         PlatformLogger.Bridge asPlatformLoggerBridge(Logger logger);
     }
 
@@ -130,7 +131,7 @@
         }
 
         @Override
-        public void setLevel(Logger logger, Level level, Class<?> caller) {
+        public void setLevel(Logger logger, Level level, Module caller) {
             PrivilegedAction<Void> pa = () -> {
                 setLevel(logger, PlatformLogger.toPlatformLevel(level), caller);
                 return null;
@@ -139,7 +140,7 @@
         }
 
         @Override
-        public void setLevel(Logger logger, PlatformLogger.Level level, Class<?> caller) {
+        public void setLevel(Logger logger, PlatformLogger.Level level, Module caller) {
             PrivilegedAction<Logger> pa = () -> demandLoggerFor(logger.getName(), caller);
             Logger impl = AccessController.doPrivileged(pa);
             SimpleConsoleLogger.class.cast(impl)
@@ -606,11 +607,12 @@
             String name,
             ResourceBundle loggerBundle,
             Logger logger,
-            Class<?> caller) {
+            Class<?> callerClass) {
 
         System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]");
         AtomicLong sequencer = TestLoggerFinder.sequencer;
 
+        Module caller = callerClass.getModule();
         Foo foo = new Foo();
         String fooMsg = foo.toString();
         for (Level loggerLevel : Level.values()) {
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BaseLoggerBridgeTest/BaseLoggerBridgeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,6 +47,7 @@
 import java.lang.System.Logger;
 import java.lang.System.Logger.Level;
 import java.util.stream.Stream;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -209,8 +210,6 @@
                 return Arrays.deepToString(toArray(false));
             }
 
-
-
             @Override
             public boolean equals(Object obj) {
                 return obj instanceof LogEvent
@@ -342,15 +341,15 @@
 
         }
 
-        public Logger getLogger(String name, Class<?> caller);
-        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class<?> caller);
+        public Logger getLogger(String name, Module caller);
+        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
     }
 
     public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
         static final RuntimePermission LOGGERFINDER_PERMISSION =
                 new RuntimePermission("loggerFinder");
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(LOGGERFINDER_PERMISSION);
@@ -375,7 +374,7 @@
         }
     }
 
-    static Logger getLogger(String name, Class<?> caller) {
+    static Logger getLogger(String name, Module caller) {
         boolean old = allowAll.get().get();
         allowAccess.get().set(true);
         try {
@@ -465,7 +464,7 @@
 
         TestLoggerFinder.LoggerImpl appSink = null;
         try {
-            appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class));
+            appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule()));
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -480,7 +479,7 @@
             boolean old = allowControl.get().get();
             allowControl.get().set(true);
             try {
-                appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class));
+                appSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerBridgeTest.class.getModule()));
             } finally {
                 allowControl.get().set(old);
             }
@@ -489,7 +488,7 @@
 
         TestLoggerFinder.LoggerImpl sysSink = null;
         try {
-            sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class));
+            sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule()));
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -527,13 +526,13 @@
 
         Logger sysLogger1 = null;
         try {
-            sysLogger1 = getLogger("foo", Thread.class);
+            sysLogger1 = getLogger("foo", Thread.class.getModule());
             loggerDescMap.put(sysLogger1,
-                    "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)");
+                    "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())");
 
             if (!hasRequiredPermissions) {
                 // check that the provider would have thrown an exception
-                provider.getLogger("foo", Thread.class);
+                provider.getLogger("foo", Thread.class.getModule());
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
         } catch (AccessControlException acx) {
@@ -572,8 +571,8 @@
 
         Logger sysLogger2 = null;
         try {
-            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)");
+            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BasePlatformLoggerTest/BasePlatformLoggerTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,6 +47,7 @@
 import java.security.AccessControlException;
 import java.util.stream.Stream;
 import sun.util.logging.PlatformLogger;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -327,12 +328,12 @@
             }
         }
 
-        public Logger getLogger(String name, Class<?> caller);
+        public Logger getLogger(String name, Module caller);
     }
 
     public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(LOGGERFINDER_PERMISSION);
@@ -433,7 +434,7 @@
         try {
             allowControl.get().set(true);
             appSink = TestLoggerFinder.LoggerImpl.class.cast(
-                        provider.getLogger("foo", BasePlatformLoggerTest.class));
+                        provider.getLogger("foo", BasePlatformLoggerTest.class.getModule()));
         } finally {
             allowControl.get().set(before);
         }
@@ -442,7 +443,8 @@
         before = allowControl.get().get();
         try {
             allowControl.get().set(true);
-            sysSink = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class));
+            sysSink = TestLoggerFinder.LoggerImpl.class.cast(
+                        provider.getLogger("foo", Thread.class.getModule()));
         } finally {
             allowControl.get().set(before);
         }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerAPIsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,7 +30,7 @@
 import java.util.List;
 import java.util.ResourceBundle;
 import java.util.Set;
-
+import java.lang.reflect.Module;
 import jdk.internal.logger.BootstrapLogger;
 import jdk.internal.logger.LazyLoggers;
 
@@ -69,7 +69,7 @@
         }
 
         final Logger LOGGER =
-                LazyLoggers.getLogger("foo.bar", Thread.class);
+                LazyLoggers.getLogger("foo.bar", Thread.class.getModule());
         final sun.util.logging.PlatformLogger.Level PLATFORM_LEVEL =
                 sun.util.logging.PlatformLogger.Level.SEVERE;
         final MyResources BUNDLE = new MyResources();
--- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -43,6 +43,7 @@
 import java.util.stream.Stream;
 import jdk.internal.logger.BootstrapLogger;
 import jdk.internal.logger.LazyLoggers;
+import java.lang.reflect.Module;
 
 /*
  * @test
@@ -105,7 +106,7 @@
         if (BootstrapLogger.isBooted()) {
             throw new RuntimeException("VM should not be booted!");
         }
-        Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class);
+        Logger logger = LazyLoggers.getLogger("foo.bar", Thread.class.getModule());
 
         if (test != TestCase.NO_SECURITY) {
             LogStream.err.println("Setting security manager");
@@ -261,7 +262,7 @@
         SimplePolicy.allowAll.set(Boolean.TRUE);
         try {
             bazbaz = java.lang.System.LoggerFinder
-                    .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class);
+                    .getLoggerFinder().getLogger("foo.bar.baz.baz", BootstrapLoggerTest.class.getModule());
         } finally {
             SimplePolicy.allowAll.set(Boolean.FALSE);
         }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -51,6 +51,7 @@
 import java.lang.System.Logger.Level;
 import java.util.stream.Stream;
 import sun.util.logging.PlatformLogger;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -164,6 +165,7 @@
                     null, null, level, bundle, key,
                     thrown, params);
         }
+
         public static LogEvent of(long sequenceNumber,
                 boolean isLoggable, String name,
                 sun.util.logging.PlatformLogger.Level level, ResourceBundle bundle,
@@ -231,7 +233,7 @@
         try {
             // Preload classes before the security manager is on.
             providerClass = ClassLoader.getSystemClassLoader().loadClass("LoggerBridgeTest$LogProducerFinder");
-            ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass);
+            ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule());
         } catch (Exception ex) {
             throw new ExceptionInInitializerError(ex);
         }
@@ -415,7 +417,7 @@
         }
 
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(LOGGERFINDER_PERMISSION);
@@ -430,6 +432,15 @@
         }
     }
 
+    static ClassLoader getClassLoader(Module m) {
+        final boolean before = allowAll.get().getAndSet(true);
+        try {
+            return m.getClassLoader();
+        } finally {
+            allowAll.get().set(before);
+        }
+    }
+
     static final sun.util.logging.PlatformLogger.Level[] julLevels = {
         sun.util.logging.PlatformLogger.Level.ALL,
         sun.util.logging.PlatformLogger.Level.FINEST,
@@ -497,14 +508,14 @@
         try {
             Class<?> bridgeClass = Class.forName("jdk.internal.logger.LazyLoggers");
             lazyGetLogger = bridgeClass.getDeclaredMethod("getLogger",
-                    String.class, Class.class);
+                    String.class, Module.class);
             lazyGetLogger.setAccessible(true);
         } catch (Throwable ex) {
             throw new ExceptionInInitializerError(ex);
         }
     }
 
-    static Logger getLogger(LoggerFinder provider, String name, Class<?> caller) {
+    static Logger getLogger(LoggerFinder provider, String name, Module caller) {
         Logger logger;
         try {
             logger = Logger.class.cast(lazyGetLogger.invoke(null, name, caller));
@@ -522,14 +533,14 @@
         // The method above does not throw exception...
         // call the provider here to verify that an exception would have
         // been thrown by the provider.
-        if (logger != null && caller == Thread.class) {
+        if (logger != null && caller == Thread.class.getModule()) {
             Logger log = provider.getLogger(name, caller);
         }
         return logger;
     }
 
-    static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Class<?> caller) {
-        if (caller.getClassLoader() != null) {
+    static Logger getLogger(LoggerFinder provider, String name, ResourceBundle bundle, Module caller) {
+        if (getClassLoader(caller) != null) {
             return System.getLogger(name,bundle);
         } else {
             return provider.getLocalizedLogger(name, bundle, caller);
@@ -614,12 +625,12 @@
 
 
         Logger appLogger1 = System.getLogger("foo");
-        loggerDescMap.put(appLogger1, "LogProducer.getApplicationLogger(\"foo\")");
+        loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")");
 
         Logger sysLogger1 = null;
         try {
-            sysLogger1 = getLogger(provider, "foo", Thread.class);
-            loggerDescMap.put(sysLogger1, "LogProducer.getSystemLogger(\"foo\")");
+            sysLogger1 = getLogger(provider, "foo", Thread.class.getModule());
+            loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -636,12 +647,12 @@
 
         Logger appLogger2 =
                 System.getLogger("foo", loggerBundle);
-        loggerDescMap.put(appLogger2, "LogProducer.getApplicationLogger(\"foo\", loggerBundle)");
+        loggerDescMap.put(appLogger2, "System.getLogger(\"foo\", loggerBundle)");
 
         Logger sysLogger2 = null;
         try {
-            sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class);
-            loggerDescMap.put(sysLogger2, "provider.getSystemLogger(\"foo\", loggerBundle)");
+            sysLogger2 = getLogger(provider, "foo", loggerBundle, Thread.class.getModule());
+            loggerDescMap.put(sysLogger2, "provider.getLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -671,9 +682,9 @@
         allowControl.get().set(true);
         try {
            appSink = LogProducerFinder.LoggerImpl.class.cast(
-                   provider.getLogger("foo",  LoggerBridgeTest.class));
+                   provider.getLogger("foo",  LoggerBridgeTest.class.getModule()));
            sysSink = LogProducerFinder.LoggerImpl.class.cast(
-                        provider.getLogger("foo", Thread.class));
+                        provider.getLogger("foo", Thread.class.getModule()));
         } finally {
             allowControl.get().set(old);
         }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -53,6 +53,7 @@
 import java.util.ServiceLoader;
 import java.util.concurrent.atomic.AtomicReference;
 import jdk.internal.logger.SimpleConsoleLogger;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -166,8 +167,8 @@
 
         }
 
-        public Logger getLogger(String name, Class<?> caller);
-        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Class<?> caller);
+        public Logger getLogger(String name, Module caller);
+        public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
     }
 
     public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
@@ -187,7 +188,7 @@
 
 
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(LOGGERFINDER_PERMISSION);
@@ -210,7 +211,7 @@
             throw new ServiceConfigurationError("Should not come here");
         }
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             throw new ServiceConfigurationError("Should not come here");
         }
     }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -49,6 +49,7 @@
 import java.lang.System.Logger.Level;
 import java.util.stream.Stream;
 import sun.util.logging.PlatformLogger;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -94,7 +95,7 @@
         try {
             // Preload classes before the security manager is on.
             providerClass = ClassLoader.getSystemClassLoader().loadClass("PlatformLoggerBridgeTest$LogProducerFinder");
-            ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass);
+            ((LoggerFinder)providerClass.newInstance()).getLogger("foo", providerClass.getModule());
         } catch (Exception ex) {
             throw new ExceptionInInitializerError(ex);
         }
@@ -415,7 +416,7 @@
         }
 
         @Override
-        public Logger getLogger(String name, Class<?> caller) {
+        public Logger getLogger(String name, Module caller) {
             SecurityManager sm = System.getSecurityManager();
             if (sm != null) {
                 sm.checkPermission(LOGGERFINDER_PERMISSION);
@@ -598,7 +599,7 @@
         allowControl.get().set(true);
         try {
            sysSink = LogProducerFinder.LoggerImpl.class.cast(
-                        provider.getLogger("foo", Thread.class));
+                        provider.getLogger("foo", Thread.class.getModule()));
         } finally {
             allowControl.get().set(old);
         }
--- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -469,12 +469,12 @@
         errors.append(test.testGetLoggerOverriddenOnSpi());
         java.lang.System.Logger julLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLogger("foo", LoggerFinderAPITest.class);
+                        .getLogger("foo", LoggerFinderAPITest.class.getModule());
         errors.append(test.testDefaultJULLogger(julLogger));
         if (errors.length() > 0) throw new RuntimeException(errors.toString());
         java.lang.System.Logger julSystemLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLogger("bar", Thread.class);
+                        .getLogger("bar", Thread.class.getModule());
         errors.append(test.testDefaultJULLogger(julSystemLogger));
         if (errors.length() > 0) throw new RuntimeException(errors.toString());
         java.lang.System.Logger julLocalizedLogger =
@@ -482,7 +482,7 @@
                 System.getLogger("baz", bundleLocalized);
         java.lang.System.Logger julLocalizedSystemLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLocalizedLogger("oof", bundleLocalized, Thread.class);
+                        .getLocalizedLogger("oof", bundleLocalized, Thread.class.getModule());
         final String error = errors.toString();
         if (!error.isEmpty()) throw new RuntimeException(error);
         for (java.lang.System.Logger logger : new java.lang.System.Logger[] {
--- a/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/backend/LoggerFinderBackendTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -77,6 +77,7 @@
 import java.util.logging.LogRecord;
 import java.util.logging.Logger;
 import sun.util.logging.internal.LoggingProviderImpl;
+import java.lang.reflect.Module;
 
 /**
  * @author danielfuchs
@@ -1506,7 +1507,7 @@
         Logger getBackendLogger(String name) {
             if (isSystem) {
                 return LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
-                        LogManager.getLogManager(), name, Thread.class);
+                        LogManager.getLogManager(), name, Thread.class.getModule());
             } else {
                 return Logger.getLogger(name);
             }
@@ -1699,7 +1700,7 @@
                 Collections.synchronizedMap(new HashMap<>());
 
         @Override
-        public java.lang.System.Logger getLogger(String name, Class<?> caller) {
+        public java.lang.System.Logger getLogger(String name, Module caller) {
             ClassLoader callerLoader = caller.getClassLoader();
             if (callerLoader == null) {
                 systemLoggers.putIfAbsent(name, new CustomLogger(name));
@@ -1827,8 +1828,8 @@
             public void setLevel(java.lang.System.Logger logger, Level level) {
                 final CustomLoggerFinder.CustomLogger l =
                         (CustomLoggerFinder.CustomLogger)
-                        (isSystem ? provider.getLogger(logger.getName(), Thread.class) :
-                        provider.getLogger(logger.getName(), LoggerFinderBackendTest.class));
+                        (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) :
+                        provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule()));
                 l.setLevel(provider.fromJul(level));
             }
             @Override
@@ -1840,8 +1841,8 @@
             CustomLoggerFinder.CustomLevel getLevel(java.lang.System.Logger logger) {
                 final CustomLoggerFinder.CustomLogger l =
                         (CustomLoggerFinder.CustomLogger)
-                        (isSystem ? provider.getLogger(logger.getName(), Thread.class) :
-                        provider.getLogger(logger.getName(), LoggerFinderBackendTest.class));
+                        (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) :
+                        provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule()));
                 return l.level;
             }
 
@@ -1962,7 +1963,7 @@
         try {
             Class<?> lazyLoggers = jdk.internal.logger.LazyLoggers.class;
             getLazyLogger = lazyLoggers.getMethod("getLazyLogger",
-                    String.class, Class.class);
+                    String.class, Module.class);
             getLazyLogger.setAccessible(true);
             Class<?> loggerFinderLoader =
                     Class.forName("java.lang.System$LoggerFinder");
@@ -1973,7 +1974,7 @@
         }
     }
 
-    static java.lang.System.Logger getSystemLogger(String name, Class<?> caller) throws Exception {
+    static java.lang.System.Logger getSystemLogger(String name, Module caller) throws Exception {
         try {
             return java.lang.System.Logger.class.cast(getLazyLogger.invoke(null, name, caller));
         } catch (InvocationTargetException x) {
@@ -1986,7 +1987,7 @@
         }
     }
     static java.lang.System.Logger getSystemLogger(String name,
-            ResourceBundle bundle, Class<?> caller) throws Exception {
+            ResourceBundle bundle, Module caller) throws Exception {
         try {
             LoggerFinder provider = LoggerFinder.class.cast(accessLoggerFinder.invoke(null));
             return provider.getLocalizedLogger(name, bundle, caller);
@@ -2047,14 +2048,14 @@
         final BackendTester tester = factory.createBackendTester(false);
         final java.lang.System.Logger logger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLogger("foo", LoggerFinderBackendTest.class);
+                        .getLogger("foo", LoggerFinderBackendTest.class.getModule());
 
         testLogger(tester, logger, nb);
 
         // Test a simple system logger with JUL backend
         final java.lang.System.Logger system =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLogger("bar", Thread.class);
+                        .getLogger("bar", Thread.class.getModule());
         final BackendTester systemTester = factory.createBackendTester(true);
         testLogger(systemTester, system, nb);
 
@@ -2062,7 +2063,7 @@
         // JUL backend
         final java.lang.System.Logger noBundleLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class);
+                        .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class.getModule());
         final BackendTester noBundleTester =
                 factory.createBackendTester(false, spiLoggerClass);
         testLogger(noBundleTester, noBundleLogger, nb);
@@ -2071,7 +2072,7 @@
         // backend
         final java.lang.System.Logger noBundleSysLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLocalizedLogger("oof", null, Thread.class);
+                        .getLocalizedLogger("oof", null, Thread.class.getModule());
         final BackendTester noBundleSysTester =
                 factory.createBackendTester(true, spiLoggerClass);
         testLogger(noBundleSysTester, noBundleSysLogger, nb);
@@ -2085,14 +2086,14 @@
             System.out.println("System.Loggers.getLogger(\"baz\", null): got expected " + x);
         }
         final java.lang.System.Logger noBundleExtensionLogger =
-                getSystemLogger("baz", null, LoggerFinderBackendTest.class);
+                getSystemLogger("baz", null, LoggerFinderBackendTest.class.getModule());
         final BackendTester noBundleExtensionTester =
                 factory.createBackendTester(false, jdkLoggerClass);
         testLogger(noBundleExtensionTester, noBundleExtensionLogger, nb);
 
         // Test a simple system logger with JUL backend
         final java.lang.System.Logger sysExtensionLogger =
-                getSystemLogger("oof", Thread.class);
+                getSystemLogger("oof", Thread.class.getModule());
         final BackendTester sysExtensionTester =
                 factory.createBackendTester(true, jdkLoggerClass);
         testLogger(sysExtensionTester, sysExtensionLogger, nb);
@@ -2100,7 +2101,7 @@
         // Test a localized system logger with null resource bundle and JUL
         // backend
         final java.lang.System.Logger noBundleSysExtensionLogger =
-                getSystemLogger("oof", null, Thread.class);
+                getSystemLogger("oof", null, Thread.class.getModule());
         final BackendTester noBundleSysExtensionTester =
                 factory.createBackendTester(true, jdkLoggerClass);
         testLogger(noBundleSysExtensionTester, noBundleSysExtensionLogger, nb);
@@ -2127,7 +2128,7 @@
                 ResourceBundle.getBundle(ResourceBundeLocalized.class.getName());
         final java.lang.System.Logger bundleLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class);
+                        .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class.getModule());
         final BackendTester bundleTester =
                 factory.createBackendTester(false, spiLoggerClass, bundle);
         testLogger(bundleTester, bundleLogger, nb);
@@ -2135,7 +2136,7 @@
         // Test a localized system logger with resource bundle and JUL backend
         final java.lang.System.Logger bundleSysLogger =
                 java.lang.System.LoggerFinder.getLoggerFinder()
-                        .getLocalizedLogger("titi", bundle, Thread.class);
+                        .getLocalizedLogger("titi", bundle, Thread.class.getModule());
         final BackendTester bundleSysTester =
                 factory.createBackendTester(true, spiLoggerClass, bundle);
         testLogger(bundleSysTester, bundleSysLogger, nb);
@@ -2151,7 +2152,7 @@
         // Test a localized Jdk system logger with resource bundle and JUL
         // backend
         final java.lang.System.Logger bundleExtensionSysLogger =
-                getSystemLogger("titu", bundle, Thread.class);
+                getSystemLogger("titu", bundle, Thread.class.getModule());
         final BackendTester bundleExtensionSysTester =
                 factory.createBackendTester(true, jdkLoggerClass, bundle);
         testLogger(bundleExtensionSysTester, bundleExtensionSysLogger, nb);
--- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultLoggerBridgeTest/DefaultLoggerBridgeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,6 +48,7 @@
 import java.lang.System.Logger;
 import java.util.stream.Stream;
 import sun.util.logging.internal.LoggingProviderImpl;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -246,7 +247,7 @@
         }
     }
 
-    static Logger getLogger(String name, Class<?> caller) {
+    static Logger getLogger(String name, Module caller) {
         boolean old = allowAccess.get().get();
         allowAccess.get().set(true);
         try {
@@ -311,8 +312,8 @@
                 ResourceBundle.getBundle(MyLoggerBundle.class.getName());
         final Map<Object, String> loggerDescMap = new HashMap<>();
 
-        Logger sysLogger1a = getLogger("foo", Thread.class);
-        loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class)");
+        Logger sysLogger1a = getLogger("foo", Thread.class.getModule());
+        loggerDescMap.put(sysLogger1a, "jdk.internal.logger.LazyLoggers.getLogger(\"foo\", Thread.class.getModule())");
 
         Logger appLogger1 = System.getLogger("foo");
         loggerDescMap.put(appLogger1, "System.getLogger(\"foo\")");
@@ -341,9 +342,9 @@
 
         Logger sysLogger1b = null;
         try {
-            sysLogger1b = provider.getLogger("foo", Thread.class);
+            sysLogger1b = provider.getLogger("foo", Thread.class.getModule());
             if (sysLogger1b != sysLogger1a) {
-                loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class)");
+                loggerDescMap.put(sysLogger1b, "provider.getLogger(\"foo\", Thread.class.getModule())");
             }
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
@@ -367,8 +368,8 @@
 
         Logger sysLogger2 = null;
         try {
-            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class);
-            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)");
+            sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class.getModule());
+            loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class.getModule())");
             if (!hasRequiredPermissions) {
                 throw new RuntimeException("Managed to obtain a system logger without permission");
             }
@@ -396,9 +397,9 @@
         allowAll.get().set(true);
         try {
             sysSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
-                    LogManager.getLogManager(), "foo", Thread.class);
+                    LogManager.getLogManager(), "foo", Thread.class.getModule());
             appSink = LoggingProviderImpl.getLogManagerAccess().demandLoggerFor(
-                    LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class);
+                    LogManager.getLogManager(), "foo", DefaultLoggerBridgeTest.class.getModule());
             if (appSink == sysSink) {
                 throw new RuntimeException("identical backend loggers");
             }
--- a/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/System/LoggerFinder/jdk/DefaultPlatformLoggerTest/DefaultPlatformLoggerTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -44,6 +44,7 @@
 import java.lang.System.LoggerFinder;
 import sun.util.logging.PlatformLogger;
 import sun.util.logging.internal.LoggingProviderImpl;
+import java.lang.reflect.Module;
 
 /**
  * @test
@@ -244,9 +245,9 @@
         LoggerFinder provider = LoggerFinder.getLoggerFinder();
         java.util.logging.Logger appSink = LoggingProviderImpl.getLogManagerAccess()
                 .demandLoggerFor(LogManager.getLogManager(), "foo",
-                        DefaultPlatformLoggerTest.class);
+                        DefaultPlatformLoggerTest.class.getModule());
         java.util.logging.Logger sysSink = LoggingProviderImpl.getLogManagerAccess()
-                .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class);
+                .demandLoggerFor(LogManager.getLogManager(),"foo", Thread.class.getModule());
         appSink.addHandler(new MyHandler());
         sysSink.addHandler(new MyHandler());
         appSink.setUseParentHandlers(VERBOSE);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/ArrayConstructorTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+ * @bug 8155106
+ * @run testng/othervm -ea -esa test.java.lang.invoke.ArrayConstructorTest
+ */
+package test.java.lang.invoke;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+import static java.lang.invoke.MethodType.methodType;
+
+import static org.testng.AssertJUnit.*;
+
+import org.testng.annotations.*;
+
+
+public class ArrayConstructorTest {
+
+    static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    @Test
+    public static void testFindConstructorArray() {
+        boolean caught = false;
+        try {
+            MethodHandle h = LOOKUP.findConstructor(Object[].class, methodType(void.class));
+        } catch (NoSuchMethodException nsme) {
+            assertEquals("no constructor for array class: [Ljava.lang.Object;", nsme.getMessage());
+            caught = true;
+        } catch (Exception e) {
+            throw new AssertionError("unexpected exception: " + e);
+        }
+        assertTrue(caught);
+    }
+
+    @DataProvider
+    static Object[][] arrayConstructorNegative() {
+        return new Object[][]{
+                {String.class, IllegalArgumentException.class, "not an array class: java.lang.String"},
+                {null, NullPointerException.class, null}
+        };
+    }
+
+    @Test(dataProvider = "arrayConstructorNegative")
+    public static void testArrayConstructorNegative(Class<?> clazz, Class<?> exceptionClass, String message) {
+        boolean caught = false;
+        try {
+            MethodHandle h = MethodHandles.arrayConstructor(clazz);
+        } catch (Exception e) {
+            assertEquals(exceptionClass, e.getClass());
+            if (message != null) {
+                assertEquals(message, e.getMessage());
+            }
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+
+    @Test
+    public static void testArrayConstructor() throws Throwable {
+        MethodHandle h = MethodHandles.arrayConstructor(String[].class);
+        assertEquals(methodType(String[].class, int.class), h.type());
+        String[] a = (String[]) h.invoke(17);
+        assertEquals(17, a.length);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/JavaUtilConcurrentLookupTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
+ * @summary Tests that Lookup can be produced from classes under java.util.concurrent
+ * @bug 8154447
+ * @compile/module=java.base java/util/concurrent/LookupTester.java
+ * @run testng/othervm JavaUtilConcurrentLookupTest
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.concurrent.LookupTester;
+
+public class JavaUtilConcurrentLookupTest {
+
+    @Test
+    public void testLookup() {
+        LookupTester.getLookup();
+    }
+
+    @Test
+    public void testLookupIn() {
+        LookupTester.getLookupIn();
+    }
+}
--- a/jdk/test/java/lang/invoke/PermuteArgsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/PermuteArgsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -23,6 +23,7 @@
 
 /* @test
  * @summary unit tests for method handles which permute their arguments
+ * @library /lib/testlibrary/jsr292 /lib/testlibrary
  * @run testng/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest
  */
 /* Examples of manual runs:
@@ -36,6 +37,8 @@
 import org.testng.*;
 import org.testng.annotations.*;
 
+import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor;
+
 import java.util.*;
 import java.lang.reflect.*;
 
@@ -122,9 +125,15 @@
         }
         new PermuteArgsTest().test();
     }
+
     static int testCases;
+
     @Test
     public void test() throws Throwable {
+        CodeCacheOverflowProcessor.runMHTest(this::test0);
+    }
+
+    public void test0() throws Throwable {
         testCases = 0;
         Lookup lookup = lookup();
         for (Method m : lookup.lookupClass().getDeclaredMethods()) {
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleBaseTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -148,6 +148,7 @@
         COMPARE_AND_EXCHANGE_ACQUIRE(TestAccessType.COMPARE_AND_EXCHANGE),
         COMPARE_AND_EXCHANGE_RELEASE(TestAccessType.COMPARE_AND_EXCHANGE),
         WEAK_COMPARE_AND_SET(TestAccessType.COMPARE_AND_SET),
+        WEAK_COMPARE_AND_SET_VOLATILE(TestAccessType.COMPARE_AND_SET),
         WEAK_COMPARE_AND_SET_ACQUIRE(TestAccessType.COMPARE_AND_SET),
         WEAK_COMPARE_AND_SET_RELEASE(TestAccessType.COMPARE_AND_SET),
         GET_AND_SET(TestAccessType.GET_AND_SET),
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessBoolean.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(true, false);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(true, false);
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, true, false);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, true, false);
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(true, false);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(true, false);
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, true, false);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, true, false);
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessByte.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, (byte)1, (byte)2);
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile((byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire((byte)1, (byte)2);
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, (byte)1, (byte)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, (byte)1, (byte)2);
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessChar.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile('a', 'b');
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire('a', 'b');
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 'a', 'b');
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 'a', 'b');
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile('a', 'b');
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire('a', 'b');
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, 'a', 'b');
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, 'a', 'b');
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessDouble.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 1.0d, 2.0d);
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(1.0d, 2.0d);
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0d, 2.0d);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0d, 2.0d);
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessFloat.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, 1.0f, 2.0f);
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(1.0f, 2.0f);
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, 1.0f, 2.0f);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, 1.0f, 2.0f);
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessInt.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -422,12 +422,19 @@
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
+        {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 2, 1);
+            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            int x = (int) vh.get(recv);
+            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+        }
+
         // Compare set and get
         {
-            int o = (int) vh.getAndSet(recv, 1);
-            assertEquals(o, 2, "getAndSet int");
+            int o = (int) vh.getAndSet(recv, 2);
+            assertEquals(o, 1, "getAndSet int");
             int x = (int) vh.get(recv);
-            assertEquals(x, 1, "getAndSet int value");
+            assertEquals(x, 2, "getAndSet int value");
         }
 
         vh.set(recv, 1);
@@ -550,18 +557,25 @@
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease( 1, 2);
+            boolean r = (boolean) vh.weakCompareAndSetRelease(1, 2);
             assertEquals(r, true, "weakCompareAndSetRelease int");
             int x = (int) vh.get();
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
+        {
+            boolean r = (boolean) vh.weakCompareAndSetVolatile(2, 1);
+            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            int x = (int) vh.get();
+            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+        }
+
         // Compare set and get
         {
-            int o = (int) vh.getAndSet( 1);
-            assertEquals(o, 2, "getAndSet int");
+            int o = (int) vh.getAndSet( 2);
+            assertEquals(o, 1, "getAndSet int");
             int x = (int) vh.get();
-            assertEquals(x, 1, "getAndSet int value");
+            assertEquals(x, 2, "getAndSet int value");
         }
 
         vh.set(1);
@@ -693,12 +707,19 @@
                 assertEquals(x, 2, "weakCompareAndSetRelease int");
             }
 
+            {
+                boolean r = vh.weakCompareAndSetVolatile(array, i, 2, 1);
+                assertEquals(r, true, "weakCompareAndSetVolatile int");
+                int x = (int) vh.get(array, i);
+                assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+            }
+
             // Compare set and get
             {
-                int o = (int) vh.getAndSet(array, i, 1);
-                assertEquals(o, 2, "getAndSet int");
+                int o = (int) vh.getAndSet(array, i, 2);
+                assertEquals(o, 1, "getAndSet int");
                 int x = (int) vh.get(array, i);
-                assertEquals(x, 1, "getAndSet int value");
+                assertEquals(x, 2, "getAndSet int value");
             }
 
             vh.set(array, i, 1);
@@ -779,6 +800,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, 1, 2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, 1, 2);
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessLong.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -422,12 +422,19 @@
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
+        {
+            boolean r = vh.weakCompareAndSetVolatile(recv, 2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            long x = (long) vh.get(recv);
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+        }
+
         // Compare set and get
         {
-            long o = (long) vh.getAndSet(recv, 1L);
-            assertEquals(o, 2L, "getAndSet long");
+            long o = (long) vh.getAndSet(recv, 2L);
+            assertEquals(o, 1L, "getAndSet long");
             long x = (long) vh.get(recv);
-            assertEquals(x, 1L, "getAndSet long value");
+            assertEquals(x, 2L, "getAndSet long value");
         }
 
         vh.set(recv, 1L);
@@ -550,18 +557,25 @@
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease( 1L, 2L);
+            boolean r = (boolean) vh.weakCompareAndSetRelease(1L, 2L);
             assertEquals(r, true, "weakCompareAndSetRelease long");
             long x = (long) vh.get();
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
+        {
+            boolean r = (boolean) vh.weakCompareAndSetVolatile(2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            long x = (long) vh.get();
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+        }
+
         // Compare set and get
         {
-            long o = (long) vh.getAndSet( 1L);
-            assertEquals(o, 2L, "getAndSet long");
+            long o = (long) vh.getAndSet( 2L);
+            assertEquals(o, 1L, "getAndSet long");
             long x = (long) vh.get();
-            assertEquals(x, 1L, "getAndSet long value");
+            assertEquals(x, 2L, "getAndSet long value");
         }
 
         vh.set(1L);
@@ -693,12 +707,19 @@
                 assertEquals(x, 2L, "weakCompareAndSetRelease long");
             }
 
+            {
+                boolean r = vh.weakCompareAndSetVolatile(array, i, 2L, 1L);
+                assertEquals(r, true, "weakCompareAndSetVolatile long");
+                long x = (long) vh.get(array, i);
+                assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+            }
+
             // Compare set and get
             {
-                long o = (long) vh.getAndSet(array, i, 1L);
-                assertEquals(o, 2L, "getAndSet long");
+                long o = (long) vh.getAndSet(array, i, 2L);
+                assertEquals(o, 1L, "getAndSet long");
                 long x = (long) vh.get(array, i);
-                assertEquals(x, 1L, "getAndSet long value");
+                assertEquals(x, 2L, "getAndSet long value");
             }
 
             vh.set(array, i, 1L);
@@ -779,6 +800,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, 1L, 2L);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, 1L, 2L);
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessShort.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -281,6 +281,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
         });
 
@@ -363,6 +367,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
         });
 
@@ -435,6 +443,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, (short)1, (short)2);
         });
 
@@ -507,6 +519,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile((short)1, (short)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire((short)1, (short)2);
         });
 
@@ -586,6 +602,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, (short)1, (short)2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, (short)1, (short)2);
         });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestAccessString.java	Wed Jul 05 21:39:33 2017 +0200
@@ -104,9 +104,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -436,12 +436,19 @@
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
+        {
+            boolean r = vh.weakCompareAndSetVolatile(recv, "bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            String x = (String) vh.get(recv);
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+        }
+
         // Compare set and get
         {
-            String o = (String) vh.getAndSet(recv, "foo");
-            assertEquals(o, "bar", "getAndSet String");
+            String o = (String) vh.getAndSet(recv, "bar");
+            assertEquals(o, "foo", "getAndSet String");
             String x = (String) vh.get(recv);
-            assertEquals(x, "foo", "getAndSet String value");
+            assertEquals(x, "bar", "getAndSet String value");
         }
 
     }
@@ -562,18 +569,25 @@
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease( "foo", "bar");
+            boolean r = (boolean) vh.weakCompareAndSetRelease("foo", "bar");
             assertEquals(r, true, "weakCompareAndSetRelease String");
             String x = (String) vh.get();
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
+        {
+            boolean r = (boolean) vh.weakCompareAndSetVolatile("bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            String x = (String) vh.get();
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+        }
+
         // Compare set and get
         {
-            String o = (String) vh.getAndSet( "foo");
-            assertEquals(o, "bar", "getAndSet String");
+            String o = (String) vh.getAndSet( "bar");
+            assertEquals(o, "foo", "getAndSet String");
             String x = (String) vh.get();
-            assertEquals(x, "foo", "getAndSet String value");
+            assertEquals(x, "bar", "getAndSet String value");
         }
 
     }
@@ -703,12 +717,19 @@
                 assertEquals(x, "bar", "weakCompareAndSetRelease String");
             }
 
+            {
+                boolean r = vh.weakCompareAndSetVolatile(array, i, "bar", "foo");
+                assertEquals(r, true, "weakCompareAndSetVolatile String");
+                String x = (String) vh.get(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+            }
+
             // Compare set and get
             {
-                String o = (String) vh.getAndSet(array, i, "foo");
-                assertEquals(o, "bar", "getAndSet String");
+                String o = (String) vh.getAndSet(array, i, "bar");
+                assertEquals(o, "foo", "getAndSet String");
                 String x = (String) vh.get(array, i);
-                assertEquals(x, "foo", "getAndSet String value");
+                assertEquals(x, "bar", "getAndSet String value");
             }
 
         }
@@ -787,6 +808,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, "foo", "bar");
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, "foo", "bar");
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsChar.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsChar
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsChar
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsChar
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(char[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(char[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(char[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(char[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -203,6 +205,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
         });
 
@@ -264,6 +270,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -305,6 +315,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsDouble.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsDouble
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsDouble
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsDouble
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(double[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(double[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(double[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(double[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -238,6 +240,10 @@
             });
 
             checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -333,6 +339,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -414,6 +424,10 @@
                 });
 
                 checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -486,6 +500,10 @@
                 });
 
                 checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -561,6 +579,10 @@
                     });
 
                     checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                     });
 
@@ -698,12 +720,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value");
+                }
+
                 // Compare set and get
                 {
-                    double o = (double) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet double");
+                    double o = (double) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet double");
                     double x = (double) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet double value");
+                    assertEquals(x, VALUE_2, "getAndSet double value");
                 }
 
             }
@@ -831,12 +860,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease double");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile double");
+                    double x = (double) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile double value");
+                }
+
                 // Compare set and get
                 {
-                    double o = (double) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet double");
+                    double o = (double) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet double");
                     double x = (double) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet double value");
+                    assertEquals(x, VALUE_2, "getAndSet double value");
                 }
 
             }
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsFloat.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsFloat
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsFloat
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsFloat
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(float[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(float[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(float[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(float[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -238,6 +240,10 @@
             });
 
             checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -333,6 +339,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -414,6 +424,10 @@
                 });
 
                 checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -486,6 +500,10 @@
                 });
 
                 checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -561,6 +579,10 @@
                     });
 
                     checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                     });
 
@@ -698,12 +720,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value");
+                }
+
                 // Compare set and get
                 {
-                    float o = (float) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet float");
+                    float o = (float) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet float");
                     float x = (float) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet float value");
+                    assertEquals(x, VALUE_2, "getAndSet float value");
                 }
 
             }
@@ -831,12 +860,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease float");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile float");
+                    float x = (float) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile float value");
+                }
+
                 // Compare set and get
                 {
-                    float o = (float) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet float");
+                    float o = (float) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet float");
                     float x = (float) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet float value");
+                    assertEquals(x, VALUE_2, "getAndSet float value");
                 }
 
             }
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsInt.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsInt
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsInt
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsInt
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(int[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(int[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(int[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(int[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -231,6 +233,10 @@
             });
 
             checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -319,6 +325,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -407,6 +417,10 @@
                 });
 
                 checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -486,6 +500,10 @@
                 });
 
                 checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -568,6 +586,10 @@
                     });
 
                     checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                     });
 
@@ -712,12 +734,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value");
+                }
+
                 // Compare set and get
                 {
-                    int o = (int) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet int");
+                    int o = (int) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet int");
                     int x = (int) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet int value");
+                    assertEquals(x, VALUE_2, "getAndSet int value");
                 }
 
                 vh.set(array, i, VALUE_1);
@@ -854,12 +883,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease int");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile int");
+                    int x = (int) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile int value");
+                }
+
                 // Compare set and get
                 {
-                    int o = (int) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet int");
+                    int o = (int) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet int");
                     int x = (int) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet int value");
+                    assertEquals(x, VALUE_2, "getAndSet int value");
                 }
 
                 vh.set(array, i, VALUE_1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsLong.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsLong
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsLong
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsLong
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(long[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(long[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(long[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(long[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -231,6 +233,10 @@
             });
 
             checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -319,6 +325,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -407,6 +417,10 @@
                 });
 
                 checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -486,6 +500,10 @@
                 });
 
                 checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -568,6 +586,10 @@
                     });
 
                     checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                     });
 
@@ -712,12 +734,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value");
+                }
+
                 // Compare set and get
                 {
-                    long o = (long) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet long");
+                    long o = (long) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet long");
                     long x = (long) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet long value");
+                    assertEquals(x, VALUE_2, "getAndSet long value");
                 }
 
                 vh.set(array, i, VALUE_1);
@@ -854,12 +883,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease long");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile long");
+                    long x = (long) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile long value");
+                }
+
                 // Compare set and get
                 {
-                    long o = (long) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet long");
+                    long o = (long) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet long");
                     long x = (long) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet long value");
+                    assertEquals(x, VALUE_2, "getAndSet long value");
                 }
 
                 vh.set(array, i, VALUE_1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestByteArrayAsShort.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAsShort
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAsShort
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAsShort
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle(short[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle(short[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle(short[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle(short[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -91,9 +93,9 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
-        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
 
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_ADD));
@@ -203,6 +205,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
         });
 
@@ -264,6 +270,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -305,6 +315,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessInt.java	Wed Jul 05 21:39:33 2017 +0200
@@ -228,12 +228,19 @@
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2, 1);
+            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+        }
+
         // Compare set and get
         {
-            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1);
-            assertEquals(o, 2, "getAndSet int");
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2);
+            assertEquals(o, 1, "getAndSet int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, 1, "getAndSet int value");
+            assertEquals(x, 2, "getAndSet int value");
         }
 
         hs.get(TestAccessMode.SET).invokeExact(recv, 1);
@@ -356,18 +363,25 @@
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1, 2);
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1, 2);
             assertEquals(r, true, "weakCompareAndSetRelease int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2, "weakCompareAndSetRelease int");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2, 1);
+            assertEquals(r, true, "weakCompareAndSetVolatile int");
+            int x = (int) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+        }
+
         // Compare set and get
         {
-            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1);
-            assertEquals(o, 2, "getAndSet int");
+            int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2);
+            assertEquals(o, 1, "getAndSet int");
             int x = (int) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, 1, "getAndSet int value");
+            assertEquals(x, 2, "getAndSet int value");
         }
 
         hs.get(TestAccessMode.SET).invokeExact(1);
@@ -499,12 +513,19 @@
                 assertEquals(x, 2, "weakCompareAndSetRelease int");
             }
 
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2, 1);
+                assertEquals(r, true, "weakCompareAndSetVolatile int");
+                int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1, "weakCompareAndSetVolatile int value");
+            }
+
             // Compare set and get
             {
-                int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1);
-                assertEquals(o, 2, "getAndSet int");
+                int o = (int) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2);
+                assertEquals(o, 1, "getAndSet int");
                 int x = (int) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, 1, "getAndSet int value");
+                assertEquals(x, 2, "getAndSet int value");
             }
 
             hs.get(TestAccessMode.SET).invokeExact(array, i, 1);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessLong.java	Wed Jul 05 21:39:33 2017 +0200
@@ -228,12 +228,19 @@
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, 2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+        }
+
         // Compare set and get
         {
-            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 1L);
-            assertEquals(o, 2L, "getAndSet long");
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, 2L);
+            assertEquals(o, 1L, "getAndSet long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, 1L, "getAndSet long value");
+            assertEquals(x, 2L, "getAndSet long value");
         }
 
         hs.get(TestAccessMode.SET).invokeExact(recv, 1L);
@@ -356,18 +363,25 @@
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( 1L, 2L);
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact(1L, 2L);
             assertEquals(r, true, "weakCompareAndSetRelease long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, 2L, "weakCompareAndSetRelease long");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(2L, 1L);
+            assertEquals(r, true, "weakCompareAndSetVolatile long");
+            long x = (long) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+        }
+
         // Compare set and get
         {
-            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact( 1L);
-            assertEquals(o, 2L, "getAndSet long");
+            long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(2L);
+            assertEquals(o, 1L, "getAndSet long");
             long x = (long) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, 1L, "getAndSet long value");
+            assertEquals(x, 2L, "getAndSet long value");
         }
 
         hs.get(TestAccessMode.SET).invokeExact(1L);
@@ -499,12 +513,19 @@
                 assertEquals(x, 2L, "weakCompareAndSetRelease long");
             }
 
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, 2L, 1L);
+                assertEquals(r, true, "weakCompareAndSetVolatile long");
+                long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, 1L, "weakCompareAndSetVolatile long value");
+            }
+
             // Compare set and get
             {
-                long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 1L);
-                assertEquals(o, 2L, "getAndSet long");
+                long o = (long) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, 2L);
+                assertEquals(o, 1L, "getAndSet long");
                 long x = (long) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, 1L, "getAndSet long value");
+                assertEquals(x, 2L, "getAndSet long value");
             }
 
             hs.get(TestAccessMode.SET).invokeExact(array, i, 1L);
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodHandleAccessString.java	Wed Jul 05 21:39:33 2017 +0200
@@ -228,12 +228,19 @@
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, "bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+        }
+
         // Compare set and get
         {
-            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "foo");
-            assertEquals(o, "bar", "getAndSet String");
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, "bar");
+            assertEquals(o, "foo", "getAndSet String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, "foo", "getAndSet String value");
+            assertEquals(x, "bar", "getAndSet String value");
         }
 
     }
@@ -352,18 +359,25 @@
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( "foo", "bar");
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact("foo", "bar");
             assertEquals(r, true, "weakCompareAndSetRelease String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, "bar", "weakCompareAndSetRelease String");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact("bar", "foo");
+            assertEquals(r, true, "weakCompareAndSetVolatile String");
+            String x = (String) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+        }
+
         // Compare set and get
         {
-            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact( "foo");
-            assertEquals(o, "bar", "getAndSet String");
+            String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact("bar");
+            assertEquals(o, "foo", "getAndSet String");
             String x = (String) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, "foo", "getAndSet String value");
+            assertEquals(x, "bar", "getAndSet String value");
         }
 
     }
@@ -491,12 +505,19 @@
                 assertEquals(x, "bar", "weakCompareAndSetRelease String");
             }
 
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, "bar", "foo");
+                assertEquals(r, true, "weakCompareAndSetVolatile String");
+                String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, "foo", "weakCompareAndSetVolatile String value");
+            }
+
             // Compare set and get
             {
-                String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "foo");
-                assertEquals(o, "bar", "getAndSet String");
+                String o = (String) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, "bar");
+                assertEquals(o, "foo", "getAndSet String");
                 String x = (String) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, "foo", "getAndSet String value");
+                assertEquals(x, "bar", "getAndSet String value");
             }
 
         }
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeInt.java	Wed Jul 05 21:39:33 2017 +0200
@@ -374,6 +374,32 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1, 1, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
@@ -972,6 +998,23 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(1, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(1, 1, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkWMTE(() -> { // expected reference class
@@ -1566,6 +1609,35 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 0, 1, 1);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1, 1);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 0, 1, 1);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1, 1);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, 1, 1, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeLong.java	Wed Jul 05 21:39:33 2017 +0200
@@ -374,6 +374,32 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(recv, 1L, 1L, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
@@ -972,6 +998,23 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(1L, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(1L, 1L, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkWMTE(() -> { // expected reference class
@@ -1566,6 +1609,35 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 0, 1L, 1L);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, 1L);
+        });
+        checkWMTE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 0, 1L, 1L);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, Void.class, 1L, 1L);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, 1L, 1L, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/VarHandleTestMethodTypeString.java	Wed Jul 05 21:39:33 2017 +0200
@@ -374,6 +374,32 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(recv, "foo", "foo", Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
@@ -878,6 +904,23 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile("foo", Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile("foo", "foo", Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkCCE(() -> { // expected reference class
@@ -1407,6 +1450,35 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, "foo", "foo");
+        });
+        checkCCE(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, "foo");
+        });
+        checkCCE(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 0, "foo", "foo");
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, Void.class, "foo", "foo");
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, "foo", "foo", Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestAccess.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -105,6 +105,7 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -114,6 +115,7 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -297,6 +299,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
         });
 
@@ -383,6 +389,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
         });
 
@@ -514,12 +524,19 @@
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
+        {
+            boolean r = vh.weakCompareAndSetVolatile(recv, $value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            $type$ x = ($type$) vh.get(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+        }
+
         // Compare set and get
         {
-            $type$ o = ($type$) vh.getAndSet(recv, $value1$);
-            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ o = ($type$) vh.getAndSet(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) vh.get(recv);
-            assertEquals(x, $value1$, "getAndSet $type$ value");
+            assertEquals(x, $value2$, "getAndSet $type$ value");
         }
 #end[CAS]
 
@@ -559,6 +576,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(recv, $value1$, $value2$);
         });
 
@@ -684,18 +705,25 @@
         }
 
         {
-            boolean r = (boolean) vh.weakCompareAndSetRelease( $value1$, $value2$);
+            boolean r = (boolean) vh.weakCompareAndSetRelease($value1$, $value2$);
             assertEquals(r, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) vh.get();
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
+        {
+            boolean r = (boolean) vh.weakCompareAndSetVolatile($value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            $type$ x = ($type$) vh.get();
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+        }
+
         // Compare set and get
         {
-            $type$ o = ($type$) vh.getAndSet( $value1$);
-            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ o = ($type$) vh.getAndSet( $value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) vh.get();
-            assertEquals(x, $value1$, "getAndSet $type$ value");
+            assertEquals(x, $value2$, "getAndSet $type$ value");
         }
 #end[CAS]
 
@@ -735,6 +763,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile($value1$, $value2$);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire($value1$, $value2$);
         });
 
@@ -869,12 +901,19 @@
                 assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
             }
 
+            {
+                boolean r = vh.weakCompareAndSetVolatile(array, i, $value2$, $value1$);
+                assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                $type$ x = ($type$) vh.get(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+            }
+
             // Compare set and get
             {
-                $type$ o = ($type$) vh.getAndSet(array, i, $value1$);
-                assertEquals(o, $value2$, "getAndSet $type$");
+                $type$ o = ($type$) vh.getAndSet(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSet $type$");
                 $type$ x = ($type$) vh.get(array, i);
-                assertEquals(x, $value1$, "getAndSet $type$ value");
+                assertEquals(x, $value2$, "getAndSet $type$ value");
             }
 #end[CAS]
 
@@ -918,6 +957,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, i, $value1$, $value2$);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, i, $value1$, $value2$);
         });
 
@@ -997,6 +1040,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, $value1$, $value2$);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, $value1$, $value2$);
             });
 
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestByteArrayView.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154556
  * @run testng/othervm -Diters=20000 -XX:TieredStopAtLevel=1 VarHandleTestByteArrayAs$Type$
  * @run testng/othervm -Diters=20000                         VarHandleTestByteArrayAs$Type$
  * @run testng/othervm -Diters=20000 -XX:-TieredCompilation  VarHandleTestByteArrayAs$Type$
@@ -57,15 +58,16 @@
         // Combinations of VarHandle byte[] or ByteBuffer
         vhss = new ArrayList<>();
         for (MemoryMode endianess : Arrays.asList(MemoryMode.BIG_ENDIAN, MemoryMode.LITTLE_ENDIAN)) {
+
+            ByteOrder bo = endianess == MemoryMode.BIG_ENDIAN
+                    ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN;
             VarHandleSource aeh = new VarHandleSource(
-                    MethodHandles.byteArrayViewVarHandle($type$[].class,
-                                                         endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteArrayViewVarHandle($type$[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(aeh);
 
             VarHandleSource bbh = new VarHandleSource(
-                    MethodHandles.byteBufferViewVarHandle($type$[].class,
-                                                          endianess == MemoryMode.BIG_ENDIAN),
+                    MethodHandles.byteBufferViewVarHandle($type$[].class, bo),
                     endianess, MemoryMode.READ_WRITE);
             vhss.add(bbh);
         }
@@ -92,6 +94,7 @@
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertTrue(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -101,6 +104,7 @@
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.COMPARE_AND_EXCHANGE_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET));
+        assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_VOLATILE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_ACQUIRE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.WEAK_COMPARE_AND_SET_RELEASE));
         assertFalse(vh.isAccessModeSupported(VarHandle.AccessMode.GET_AND_SET));
@@ -219,6 +223,10 @@
         });
 
         checkUOE(() -> {
+            boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+        });
+
+        checkUOE(() -> {
             boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
         });
 
@@ -289,6 +297,10 @@
             });
 
             checkROBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkROBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -320,6 +332,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -373,6 +389,10 @@
             });
 
             checkUOE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkUOE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -459,6 +479,10 @@
             });
 
             checkIOOBE(() -> {
+                boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+            });
+
+            checkIOOBE(() -> {
                 boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
             });
 
@@ -551,6 +575,10 @@
                 });
 
                 checkIOOBE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkIOOBE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -634,6 +662,10 @@
                 });
 
                 checkISE(() -> {
+                    boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                });
+
+                checkISE(() -> {
                     boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                 });
 
@@ -720,6 +752,10 @@
                     });
 
                     checkISE(() -> {
+                        boolean r = vh.weakCompareAndSetVolatile(array, ci, VALUE_1, VALUE_2);
+                    });
+
+                    checkISE(() -> {
                         boolean r = vh.weakCompareAndSetAcquire(array, ci, VALUE_1, VALUE_2);
                     });
 
@@ -868,12 +904,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value");
+                }
+
                 // Compare set and get
                 {
-                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet $type$");
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet $type$");
                     $type$ x = ($type$) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet $type$ value");
+                    assertEquals(x, VALUE_2, "getAndSet $type$ value");
                 }
 #end[CAS]
 
@@ -1014,12 +1057,19 @@
                     assertEquals(x, VALUE_2, "weakCompareAndSetRelease $type$");
                 }
 
+                {
+                    boolean r = vh.weakCompareAndSetVolatile(array, i, VALUE_2, VALUE_1);
+                    assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                    $type$ x = ($type$) vh.get(array, i);
+                    assertEquals(x, VALUE_1, "weakCompareAndSetVolatile $type$ value");
+                }
+
                 // Compare set and get
                 {
-                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_1);
-                    assertEquals(o, VALUE_2, "getAndSet $type$");
+                    $type$ o = ($type$) vh.getAndSet(array, i, VALUE_2);
+                    assertEquals(o, VALUE_1, "getAndSet $type$");
                     $type$ x = ($type$) vh.get(array, i);
-                    assertEquals(x, VALUE_1, "getAndSet $type$ value");
+                    assertEquals(x, VALUE_2, "getAndSet $type$ value");
                 }
 #end[CAS]
 
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodHandleAccess.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -229,12 +229,19 @@
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(recv, $value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+        }
+
         // Compare set and get
         {
-            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value1$);
-            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(recv, $value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(recv);
-            assertEquals(x, $value1$, "getAndSet $type$ value");
+            assertEquals(x, $value2$, "getAndSet $type$ value");
         }
 #end[CAS]
 
@@ -387,18 +394,25 @@
         }
 
         {
-            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact( $value1$, $value2$);
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_RELEASE).invokeExact($value1$, $value2$);
             assertEquals(r, true, "weakCompareAndSetRelease $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
             assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
         }
 
+        {
+            boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact($value2$, $value1$);
+            assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+            $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
+            assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+        }
+
         // Compare set and get
         {
-            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact( $value1$);
-            assertEquals(o, $value2$, "getAndSet $type$");
+            $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact($value2$);
+            assertEquals(o, $value1$, "getAndSet $type$");
             $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact();
-            assertEquals(x, $value1$, "getAndSet $type$ value");
+            assertEquals(x, $value2$, "getAndSet $type$ value");
         }
 #end[CAS]
 
@@ -560,12 +574,19 @@
                 assertEquals(x, $value2$, "weakCompareAndSetRelease $type$");
             }
 
+            {
+                boolean r = (boolean) hs.get(TestAccessMode.WEAK_COMPARE_AND_SET_VOLATILE).invokeExact(array, i, $value2$, $value1$);
+                assertEquals(r, true, "weakCompareAndSetVolatile $type$");
+                $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
+                assertEquals(x, $value1$, "weakCompareAndSetVolatile $type$ value");
+            }
+
             // Compare set and get
             {
-                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value1$);
-                assertEquals(o, $value2$, "getAndSet $type$");
+                $type$ o = ($type$) hs.get(TestAccessMode.GET_AND_SET).invokeExact(array, i, $value2$);
+                assertEquals(o, $value1$, "getAndSet $type$");
                 $type$ x = ($type$) hs.get(TestAccessMode.GET).invokeExact(array, i);
-                assertEquals(x, $value1$, "getAndSet $type$ value");
+                assertEquals(x, $value2$, "getAndSet $type$ value");
             }
 #end[CAS]
 
--- a/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/lang/invoke/VarHandles/X-VarHandleTestMethodType.java.template	Wed Jul 05 21:39:33 2017 +0200
@@ -375,6 +375,32 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(recv, $value1$, $value1$, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
@@ -981,6 +1007,23 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile($value1$, Void.class);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile($value1$, $value1$, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         check{#if[String]?CCE:WMTE}(() -> { // expected reference class
@@ -1583,6 +1626,35 @@
         });
 
 
+        // WeakCompareAndSetVolatile
+        // Incorrect argument types
+        checkNPE(() -> { // null receiver
+            boolean r = vh.weakCompareAndSetVolatile(null, 0, $value1$, $value1$);
+        });
+        checkCCE(() -> { // receiver reference class
+            boolean r = vh.weakCompareAndSetVolatile(Void.class, 0, $value1$, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // expected reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, Void.class, $value1$);
+        });
+        check{#if[String]?CCE:WMTE}(() -> { // actual reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, Void.class);
+        });
+        checkWMTE(() -> { // receiver primitive class
+            boolean r = vh.weakCompareAndSetVolatile(0, 0, $value1$, $value1$);
+        });
+        checkWMTE(() -> { // index reference class
+            boolean r = vh.weakCompareAndSetVolatile(array, Void.class, $value1$, $value1$);
+        });
+        // Incorrect arity
+        checkWMTE(() -> { // 0
+            boolean r = vh.weakCompareAndSetVolatile();
+        });
+        checkWMTE(() -> { // >
+            boolean r = vh.weakCompareAndSetVolatile(array, 0, $value1$, $value1$, Void.class);
+        });
+
+
         // WeakCompareAndSetAcquire
         // Incorrect argument types
         checkNPE(() -> { // null receiver
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/invoke/java.base/java/util/concurrent/LookupTester.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.concurrent;
+
+import java.lang.invoke.MethodHandles;
+
+public class LookupTester {
+    public static MethodHandles.Lookup getLookup() {
+        return MethodHandles.lookup();
+    }
+
+
+    public static MethodHandles.Lookup getLookupIn() {
+        return MethodHandles.lookup().in(ConcurrentHashMap.class);
+    }
+}
--- a/jdk/test/java/net/SocketOption/OptionsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/SocketOption/OptionsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,11 +23,13 @@
 
 /*
  * @test
- * @bug 8036979 8072384
+ * @bug 8036979 8072384 8044773
  * @run main/othervm -Xcheck:jni OptionsTest
  * @run main/othervm -Xcheck:jni -Djava.net.preferIPv4Stack=true OptionsTest
+ * @run main/othervm -Djdk.launcher.limitmods=java.base OptionsTest
  */
 
+import java.lang.reflect.Method;
 import java.net.*;
 import java.util.*;
 
@@ -43,7 +45,7 @@
         }
         Object option;
         Object testValue;
-    };
+    }
 
     // The tests set the option using the new API, read back the set value
     // which could be diferent, and then use the legacy get API to check
@@ -223,8 +225,7 @@
             } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
                 return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
             } else if (option.equals(StandardSocketOptions.IP_TOS)) {
-                return Integer.valueOf(jdk.net.Sockets.getOption(
-                    socket, StandardSocketOptions.IP_TOS));
+                return getServerSocketTrafficClass(socket);
             } else {
                 throw new RuntimeException("unexecpted socket option");
             }
@@ -281,4 +282,20 @@
         doDgSocketTests();
         doMcSocketTests();
     }
+
+    // Reflectively access jdk.net.Sockets.getOption so that the test can run
+    // without the jdk.net module.
+    static Object getServerSocketTrafficClass(ServerSocket ss) throws Exception {
+        try {
+            Class<?> c = Class.forName("jdk.net.Sockets");
+            Method m = c.getDeclaredMethod("getOption", ServerSocket.class, SocketOption.class);
+            return m.invoke(null, ss, StandardSocketOptions.IP_TOS);
+        } catch (ClassNotFoundException e) {
+            // Ok, jdk.net module not present, just fall back
+            System.out.println("jdk.net module not present, falling back.");
+            return Integer.valueOf(ss.getOption(StandardSocketOptions.IP_TOS));
+        } catch (ReflectiveOperationException e) {
+            throw new AssertionError(e);
+        }
+    }
 }
--- a/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/SocketOption/UnsupportedOptionsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,34 +21,48 @@
  * questions.
  */
 
-import jdk.net.ExtendedSocketOptions;
-
 import java.io.IOException;
+import java.lang.reflect.Field;
 import java.net.*;
+import java.util.ArrayList;
+import java.util.List;
 
 /*
  * @test
- * @bug 8143554
- * @run main UnsupportedOptionsTest
+ * @bug 8143554 8044773
  * @summary Test checks that UnsupportedOperationException for unsupported
  * SOCKET_OPTIONS is thrown by both getOption() and setOption() methods.
+ * @run main UnsupportedOptionsTest
+ * @run main/othervm -Djdk.launcher.limitmods=java.base UnsupportedOptionsTest
  */
+
 public class UnsupportedOptionsTest {
 
-    private static final SocketOption[] SOCKET_OPTIONS = {
-            StandardSocketOptions.IP_MULTICAST_IF,
-            StandardSocketOptions.IP_MULTICAST_LOOP,
-            StandardSocketOptions.IP_MULTICAST_TTL,
-            StandardSocketOptions.IP_TOS,
-            StandardSocketOptions.SO_BROADCAST,
-            StandardSocketOptions.SO_KEEPALIVE,
-            StandardSocketOptions.SO_LINGER,
-            StandardSocketOptions.SO_RCVBUF,
-            StandardSocketOptions.SO_REUSEADDR,
-            StandardSocketOptions.SO_SNDBUF,
-            StandardSocketOptions.TCP_NODELAY,
-            ExtendedSocketOptions.SO_FLOW_SLA
-    };
+    private static final List<SocketOption<?>> socketOptions = new ArrayList<>();
+
+    static {
+        socketOptions.add(StandardSocketOptions.IP_MULTICAST_IF);
+        socketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP);
+        socketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL);
+        socketOptions.add(StandardSocketOptions.IP_TOS);
+        socketOptions.add(StandardSocketOptions.SO_BROADCAST);
+        socketOptions.add(StandardSocketOptions.SO_KEEPALIVE);
+        socketOptions.add(StandardSocketOptions.SO_LINGER);
+        socketOptions.add(StandardSocketOptions.SO_RCVBUF);
+        socketOptions.add(StandardSocketOptions.SO_REUSEADDR);
+        socketOptions.add(StandardSocketOptions.SO_SNDBUF);
+        socketOptions.add(StandardSocketOptions.TCP_NODELAY);
+
+        try {
+            Class<?> c = Class.forName("jdk.net.ExtendedSocketOptions");
+            Field field = c.getField("SO_FLOW_SLA");
+            socketOptions.add((SocketOption<?>)field.get(null));
+        } catch (ClassNotFoundException e) {
+            // ignore, jdk.net module not present
+        } catch (ReflectiveOperationException e) {
+            throw new AssertionError(e);
+        }
+    }
 
     public static void main(String[] args) throws IOException {
         Socket s = new Socket();
@@ -56,7 +70,7 @@
         DatagramSocket ds = new DatagramSocket();
         MulticastSocket ms = new MulticastSocket();
 
-        for (SocketOption option : SOCKET_OPTIONS) {
+        for (SocketOption option : socketOptions) {
             if (!s.supportedOptions().contains(option)) {
                 testUnsupportedSocketOption(s, option);
             }
--- a/jdk/test/java/net/httpclient/APIErrors.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/APIErrors.java	Wed Jul 05 21:39:33 2017 +0200
@@ -26,6 +26,7 @@
  * @bug 8087112
  * @library /lib/testlibrary/
  * @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @build TestKit
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
  * @run main/othervm APIErrors
@@ -73,26 +74,6 @@
         }
     }
 
-    static void reject(Runnable r, Class<? extends Exception> extype) {
-        try {
-            r.run();
-            throw new RuntimeException("Expected: " + extype);
-        } catch (Throwable t) {
-            if (!extype.isAssignableFrom(t.getClass())) {
-                throw new RuntimeException("Wrong exception type: " + extype + " / "
-                    +t.getClass());
-            }
-        }
-    }
-
-    static void accept(Runnable r) {
-        try {
-            r.run();
-        } catch (Throwable t) {
-            throw new RuntimeException("Unexpected exception: " + t);
-        }
-    }
-
     static void checkNonNull(Supplier<?> r) {
         if (r.get() == null)
             throw new RuntimeException("Unexpected null return:");
@@ -108,12 +89,14 @@
         System.out.println("Test 1");
         HttpClient.Builder cb = HttpClient.create();
         InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000);
-        reject(() -> { cb.priority(-1);}, IllegalArgumentException.class);
-        reject(() -> { cb.priority(500);}, IllegalArgumentException.class);
-        accept(() -> { cb.priority(1);});
-        accept(() -> { cb.priority(255);});
-
-        accept(() -> {clients.add(cb.build()); clients.add(cb.build());});
+        TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(-1));
+        TestKit.assertThrows(IllegalArgumentException.class, () -> cb.priority(500));
+        TestKit.assertNotThrows(() -> cb.priority(1));
+        TestKit.assertNotThrows(() -> cb.priority(255));
+        TestKit.assertNotThrows(() -> {
+            clients.add(cb.build());
+            clients.add(cb.build());
+        });
     }
 
     static void test2() throws Exception {
@@ -139,7 +122,7 @@
 
     static void test3() throws Exception {
         System.out.println("Test 3");
-        reject(()-> {
+        TestKit.assertThrows(IllegalStateException.class, ()-> {
             try {
                 HttpRequest r1 = request();
                 HttpResponse resp = r1.response();
@@ -147,9 +130,9 @@
             } catch (IOException |InterruptedException e) {
                 throw new RuntimeException(e);
             }
-        }, IllegalStateException.class);
+        });
 
-        reject(()-> {
+        TestKit.assertThrows(IllegalStateException.class, ()-> {
             try {
                 HttpRequest r1 = request();
                 HttpResponse resp = r1.response();
@@ -157,8 +140,8 @@
             } catch (IOException |InterruptedException | ExecutionException e) {
                 throw new RuntimeException(e);
             }
-        }, IllegalStateException.class);
-        reject(()-> {
+        });
+        TestKit.assertThrows(IllegalStateException.class, ()-> {
             try {
                 HttpRequest r1 = request();
                 HttpResponse resp1 = r1.responseAsync().get();
@@ -166,7 +149,7 @@
             } catch (IOException |InterruptedException | ExecutionException e) {
                 throw new RuntimeException(e);
             }
-        }, IllegalStateException.class);
+        });
     }
 
     static class Auth extends java.net.Authenticator {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/EchoHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import 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 java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import jdk.testlibrary.SimpleSSLContext;
+import static java.net.http.HttpRequest.*;
+import static java.net.http.HttpResponse.*;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class EchoHandler implements HttpHandler {
+    public EchoHandler() {}
+
+    @Override
+    public void handle(HttpExchange t)
+            throws IOException {
+        try {
+            System.err.println("EchoHandler received request to " + t.getRequestURI());
+            InputStream is = t.getRequestBody();
+            Headers map = t.getRequestHeaders();
+            Headers map1 = t.getResponseHeaders();
+            map1.add("X-Hello", "world");
+            map1.add("X-Bye", "universe");
+            String fixedrequest = map.getFirst("XFixed");
+            File outfile = File.createTempFile("foo", "bar");
+            FileOutputStream fos = new FileOutputStream(outfile);
+            int count = (int) is.transferTo(fos);
+            is.close();
+            fos.close();
+            InputStream is1 = new FileInputStream(outfile);
+            OutputStream os = null;
+            // return the number of bytes received (no echo)
+            String summary = map.getFirst("XSummary");
+            if (fixedrequest != null && summary == null) {
+                t.sendResponseHeaders(200, count);
+                os = t.getResponseBody();
+                is1.transferTo(os);
+            } else {
+                t.sendResponseHeaders(200, 0);
+                os = t.getResponseBody();
+                is1.transferTo(os);
+
+                if (summary != null) {
+                    String s = Integer.toString(count);
+                    os.write(s.getBytes());
+                }
+            }
+            outfile.delete();
+            os.close();
+            is1.close();
+        } catch (Throwable e) {
+            e.printStackTrace();
+            throw new IOException(e);
+        }
+    }
+}
--- a/jdk/test/java/net/httpclient/LightWeightHttpServer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -22,10 +22,10 @@
  */
 
 /**
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
- * @compile ../../../com/sun/net/httpserver/LogFilter.java
- * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
+ * library /lib/testlibrary/ /
+ * build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
+ * compile ../../../com/sun/net/httpserver/LogFilter.java
+ * compile ../../../com/sun/net/httpserver/FileServerHandler.java
  */
 import com.sun.net.httpserver.Headers;
 import com.sun.net.httpserver.HttpContext;
--- a/jdk/test/java/net/httpclient/ManyRequests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/ManyRequests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,18 +24,17 @@
 /**
  * @test
  * @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext
+ * @library /lib/testlibrary/ /
+ * @build jdk.testlibrary.SimpleSSLContext EchoHandler
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
- * @run main/othervm ManyRequests
+ * @run main/othervm/timeout=40 -Djava.net.http.HttpClient.log=ssl ManyRequests
  * @summary Send a large number of requests asynchronously
  */
 
 //package javaapplication16;
 
-import com.sun.net.httpserver.HttpsConfigurator;
-import com.sun.net.httpserver.HttpsServer;
+import com.sun.net.httpserver.*;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.net.http.HttpClient;
@@ -47,18 +46,25 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Random;
+import java.util.logging.*;
 import java.util.concurrent.CompletableFuture;
-import javax.net.ssl.SSLContext;
+import javax.net.ssl.*;
 import jdk.testlibrary.SimpleSSLContext;
 
 public class ManyRequests {
 
+    volatile static int counter = 0;
+
     public static void main(String[] args) throws Exception {
+        Logger logger = Logger.getLogger("com.sun.net.httpserver");
+        logger.setLevel(Level.ALL);
+        logger.info("TEST");
+
         SSLContext ctx = new SimpleSSLContext().get();
 
         InetSocketAddress addr = new InetSocketAddress(0);
         HttpsServer server = HttpsServer.create(addr, 0);
-        server.setHttpsConfigurator(new HttpsConfigurator(ctx));
+        server.setHttpsConfigurator(new Configurator(ctx));
 
         HttpClient client = HttpClient.create()
                                       .sslContext(ctx)
@@ -72,7 +78,8 @@
         }
     }
 
-    static final int REQUESTS = 1000;
+    //static final int REQUESTS = 1000;
+    static final int REQUESTS = 20;
 
     static void test(HttpsServer server, HttpClient client) throws Exception {
         int port = server.getAddress().getPort();
@@ -102,6 +109,9 @@
                                resp.bodyAsync(HttpResponse.ignoreBody());
                                String s = "Expected 200, got: " + resp.statusCode();
                                return completedWithIOException(s);
+                           } else {
+                               counter++;
+                               System.out.println("Result from " + counter);
                            }
                            return resp.bodyAsync(HttpResponse.asByteArray())
                                       .thenApply((b) -> new Pair<>(resp, b));
@@ -114,14 +124,18 @@
 
                       });
         }
+
         // wait for them all to complete and throw exception in case of error
-        CompletableFuture.allOf(results).join();
+        //try {
+            CompletableFuture.allOf(results).join();
+        //} catch (Exception  e) {
+            //e.printStackTrace();
+            //throw e;
+        //}
     }
 
     static <T> CompletableFuture<T> completedWithIOException(String message) {
-        CompletableFuture<T> cf = new CompletableFuture<>();
-        cf.completeExceptionally(new IOException(message));
-        return cf;
+        return CompletableFuture.failedFuture(new IOException(message));
     }
 
     static final class Pair<T,U> {
@@ -192,3 +206,14 @@
         throw new RuntimeException(sb.toString());
     }
 }
+
+class Configurator extends HttpsConfigurator {
+    public Configurator(SSLContext ctx) {
+        super(ctx);
+    }
+
+    public void configure (HttpsParameters params) {
+        params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+    }
+}
+
--- a/jdk/test/java/net/httpclient/RequestBodyTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/RequestBodyTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,10 +23,11 @@
 
 /**
  * @test @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @library /lib/testlibrary/ /
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
+ * @build LightWeightHttpServer
+ * @build jdk.testlibrary.SimpleSSLContext ProxyServer
  * @run main/othervm RequestBodyTest
  */
 
--- a/jdk/test/java/net/httpclient/SmokeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/SmokeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,15 +24,13 @@
 /**
  * @test
  * @bug 8087112
- * @library /lib/testlibrary/
- * @build jdk.testlibrary.SimpleSSLContext ProxyServer
+ * @library /lib/testlibrary/ /
+ * @build jdk.testlibrary.SimpleSSLContext ProxyServer EchoHandler
  * @compile ../../../com/sun/net/httpserver/LogFilter.java
  * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
  * @run main/othervm SmokeTest
  */
 
-//package javaapplication16;
-
 import com.sun.net.httpserver.*;
 import java.net.*;
 import java.net.http.*;
@@ -69,6 +67,7 @@
  */
 public class SmokeTest {
     static SSLContext ctx;
+    static SSLParameters sslparams;
     static HttpServer s1 ;
     static HttpsServer s2;
     static ExecutorService executor;
@@ -107,6 +106,7 @@
 
         client = HttpClient.create()
                            .sslContext(ctx)
+                           .sslParameters(sslparams)
                            .followRedirects(HttpClient.Redirect.ALWAYS)
                            .executorService(Executors.newCachedThreadPool())
                            .build();
@@ -285,6 +285,7 @@
         HttpClient cl = HttpClient.create()
                                   .proxy(ProxySelector.of(proxyAddr))
                                   .sslContext(ctx)
+                                  .sslParameters(sslparams)
                                   .build();
 
         CompletableFuture<String> fut = cl.request(uri)
@@ -672,7 +673,8 @@
         s1.setExecutor(executor);
         s2.setExecutor(executor);
         ctx = new SimpleSSLContext().get();
-        s2.setHttpsConfigurator(new HttpsConfigurator(ctx));
+        sslparams = ctx.getSupportedSSLParameters();
+        s2.setHttpsConfigurator(new Configurator(ctx));
         s1.start();
         s2.start();
 
@@ -689,6 +691,16 @@
     }
 }
 
+class Configurator extends HttpsConfigurator {
+    public Configurator(SSLContext ctx) {
+        super(ctx);
+    }
+
+    public void configure (HttpsParameters params) {
+        params.setSSLParameters (getSSLContext().getSupportedSSLParameters());
+    }
+}
+
 class UploadServer extends Thread {
     int statusCode;
     ServerSocket ss;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/TestKit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.regex.Pattern;
+
+import static java.util.Objects.requireNonNull;
+
+//
+// A set of testing utility functions
+//
+public final class TestKit {
+
+    private TestKit() { }
+
+    public static void assertNotThrows(ThrowingProcedure code) {
+        requireNonNull(code, "code");
+        assertNotThrows(() -> {
+            code.run();
+            return null;
+        });
+    }
+
+    public static <V> V assertNotThrows(ThrowingFunction<V> code) {
+        requireNonNull(code, "code");
+        try {
+            return code.run();
+        } catch (Throwable t) {
+            throw new RuntimeException("Expected to run normally, but threw "
+                    + t.getClass().getCanonicalName(), t);
+        }
+    }
+
+    public static <T extends Throwable> T assertThrows(Class<? extends T> clazz,
+                                                       ThrowingProcedure code) {
+        requireNonNull(clazz, "clazz");
+        requireNonNull(code, "code");
+        try {
+            code.run();
+        } catch (Throwable t) {
+            if (clazz.isInstance(t)) {
+                return clazz.cast(t);
+            }
+            throw new RuntimeException("Expected to catch an exception of type "
+                    + clazz.getCanonicalName() + ", but caught "
+                    + t.getClass().getCanonicalName(), t);
+
+        }
+        throw new RuntimeException("Expected to catch an exception of type "
+                + clazz.getCanonicalName() + ", but caught nothing");
+    }
+
+    public interface ThrowingProcedure {
+        void run() throws Throwable;
+    }
+
+    public interface ThrowingFunction<V> {
+        V run() throws Throwable;
+    }
+
+    // The rationale behind asking for a regex is to not pollute variable names
+    // space in the scope of assertion: if it's something as simple as checking
+    // a message, we can do it inside
+    public static <T extends Throwable> T assertThrows(Class<? extends T> clazz,
+                                                       String messageRegex,
+                                                       ThrowingProcedure code) {
+        requireNonNull(messageRegex, "messagePattern");
+        T t = assertThrows(clazz, code);
+        String m = t.getMessage();
+        if (m == null) {
+            throw new RuntimeException(String.format(
+                    "Expected exception message to match the regex '%s', " +
+                            "but the message was null", messageRegex), t);
+        }
+        if (!Pattern.matches(messageRegex, m)) {
+            throw new RuntimeException(String.format(
+                    "Expected exception message to match the regex '%s', " +
+                            "actual message: %s", messageRegex, m), t);
+        }
+        return t;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/TestKitTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.IllegalFormatException;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+/*
+ * @test
+ * @compile TestKit.java
+ * @run testng TestKitTest
+ */
+public final class TestKitTest {
+
+    public static void main(String[] args) {
+        testAssertNotThrows();
+        testAssertThrows();
+    }
+
+    private static void testAssertNotThrows() {
+        Integer integer = TestKit.assertNotThrows(
+                () -> TestKit.assertNotThrows(() -> 1)
+        );
+        assertEquals(integer, Integer.valueOf(1));
+
+        RuntimeException re = TestKit.assertThrows(
+                RuntimeException.class,
+                () -> TestKit.assertNotThrows(() -> { throw new IOException(); })
+        );
+        assertEquals(re.getMessage(),
+                "Expected to run normally, but threw "
+                        + "java.io.IOException");
+
+        TestKit.assertNotThrows(
+                () -> TestKit.assertNotThrows(() -> { })
+        );
+
+        re = TestKit.assertThrows(
+                RuntimeException.class,
+                () ->  TestKit.assertNotThrows((TestKit.ThrowingProcedure) () -> { throw new IOException(); })
+        );
+        assertEquals(re.getMessage(),
+                "Expected to run normally, but threw "
+                        + "java.io.IOException");
+    }
+
+    private static void testAssertThrows() {
+        NullPointerException npe = TestKit.assertThrows(
+                NullPointerException.class,
+                () -> TestKit.assertThrows(null, null)
+        );
+        assertNotNull(npe);
+        assertTrue(Set.of("clazz", "code").contains(npe.getMessage()), npe.getMessage());
+
+        npe = TestKit.assertThrows(
+                NullPointerException.class,
+                () -> TestKit.assertThrows(IOException.class, null)
+        );
+        assertNotNull(npe);
+        assertEquals(npe.getMessage(), "code");
+
+        npe = TestKit.assertThrows(
+                NullPointerException.class,
+                () -> TestKit.assertThrows(null, () -> { })
+        );
+        assertEquals(npe.getMessage(), "clazz");
+
+        npe = TestKit.assertThrows(
+                NullPointerException.class,
+                () -> { throw new NullPointerException(); }
+        );
+        assertNotNull(npe);
+        assertNull(npe.getMessage());
+        assertEquals(npe.getClass(), NullPointerException.class);
+
+        RuntimeException re = TestKit.assertThrows(
+                RuntimeException.class,
+                () -> TestKit.assertThrows(NullPointerException.class, () -> { })
+        );
+        assertEquals(re.getClass(), RuntimeException.class);
+        assertEquals(re.getMessage(),
+                "Expected to catch an exception of type "
+                        + "java.lang.NullPointerException, but caught nothing");
+
+        re = TestKit.assertThrows(
+                RuntimeException.class,
+                () -> { throw new NullPointerException(); }
+        );
+        assertNotNull(re);
+        assertNull(re.getMessage());
+        assertEquals(re.getClass(), NullPointerException.class);
+
+        re = TestKit.assertThrows(
+                RuntimeException.class,
+                () -> TestKit.assertThrows(
+                        IllegalFormatException.class,
+                        () -> { throw new IndexOutOfBoundsException(); }
+                ));
+        assertNotNull(re);
+        assertEquals(re.getClass(), RuntimeException.class);
+        assertEquals(re.getMessage(),
+                "Expected to catch an exception of type java.util.IllegalFormatException"
+                        + ", but caught java.lang.IndexOutOfBoundsException");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/BasicTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,222 @@
+/*
+ * 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 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @modules java.httpclient
+ * @compile/module=java.httpclient java/net/http/BodyOutputStream.java
+ * @compile/module=java.httpclient java/net/http/BodyInputStream.java
+ * @compile/module=java.httpclient java/net/http/EchoHandler.java
+ * @compile/module=java.httpclient java/net/http/Http2Handler.java
+ * @compile/module=java.httpclient java/net/http/Http2TestExchange.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServer.java
+ * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java
+ * @compile/module=java.httpclient java/net/http/TestUtil.java
+ * @run testng/othervm -Djava.net.http.HttpClient.log=ssl,requests,responses,errors BasicTest
+ */
+
+import java.io.*;
+import java.net.*;
+import java.net.http.*;
+import static java.net.http.HttpClient.Version.HTTP_2;
+import javax.net.ssl.*;
+import java.nio.file.*;
+import java.util.concurrent.*;
+import jdk.testlibrary.SimpleSSLContext;
+
+
+import org.testng.annotations.Test;
+import org.testng.annotations.Parameters;
+
+@Test
+public class BasicTest {
+    static int httpPort, httpsPort;
+    static Http2TestServer httpServer, httpsServer;
+    static HttpClient client = null;
+    static ExecutorService exec;
+    static SSLContext sslContext;
+
+    static String httpURIString, httpsURIString;
+
+    static void initialize() throws Exception {
+        try {
+            SimpleSSLContext sslct = new SimpleSSLContext();
+            sslContext = sslct.get();
+            client = getClient();
+            exec = client.executorService();
+            httpServer = new Http2TestServer(false, 0, new EchoHandler(),
+                    exec, sslContext);
+            httpPort = httpServer.getAddress().getPort();
+
+            httpsServer = new Http2TestServer(true, 0, new EchoHandler(),
+                    exec, sslContext);
+
+            httpsPort = httpsServer.getAddress().getPort();
+            httpURIString = "http://127.0.0.1:" + Integer.toString(httpPort) +
+                    "/foo/";
+            httpsURIString = "https://127.0.0.1:" + Integer.toString(httpsPort) +
+                    "/bar/";
+
+            httpServer.start();
+            httpsServer.start();
+        } catch (Throwable e) {
+            System.err.println("Throwing now");
+            e.printStackTrace();
+            throw e;
+        }
+    }
+
+    @Test(timeOut=30000)
+    public static void test() throws Exception {
+        try {
+            initialize();
+            simpleTest(false);
+            simpleTest(true);
+            streamTest(false);
+            streamTest(true);
+            Thread.sleep(1000 * 4);
+        } finally {
+            httpServer.stop();
+            httpsServer.stop();
+            exec.shutdownNow();
+        }
+    }
+
+    static HttpClient getClient() {
+        if (client == null) {
+            client = HttpClient.create()
+                .sslContext(sslContext)
+                .version(HTTP_2)
+                .build();
+        }
+        return client;
+    }
+
+    static URI getURI(boolean secure) {
+        if (secure)
+            return URI.create(httpsURIString);
+        else
+            return URI.create(httpURIString);
+    }
+
+    static void checkStatus(int expected, int found) throws Exception {
+        if (expected != found) {
+            System.err.printf ("Test failed: wrong status code %d/%d\n",
+                expected, found);
+            throw new RuntimeException("Test failed");
+        }
+    }
+
+    static void checkStrings(String expected, String found) throws Exception {
+        if (!expected.equals(found)) {
+            System.err.printf ("Test failed: wrong string %s/%s\n",
+                expected, found);
+            throw new RuntimeException("Test failed");
+        }
+    }
+
+    static Void compareFiles(Path path1, Path path2) {
+        return java.net.http.TestUtil.compareFiles(path1, path2);
+    }
+
+    static Path tempFile() {
+        return java.net.http.TestUtil.tempFile();
+    }
+
+    static final String SIMPLE_STRING = "Hello world Goodbye world";
+
+    static final int LOOPS = 13;
+    static final int FILESIZE = 64 * 1024;
+
+    static void streamTest(boolean secure) throws Exception {
+        URI uri = getURI(secure);
+        System.err.printf("streamTest %b to %s\n" , secure, uri);
+
+        HttpClient client = getClient();
+        Path src = java.net.http.TestUtil.getAFile(FILESIZE * 4);
+        HttpRequest req = client.request(uri)
+                .body(HttpRequest.fromFile(src))
+                .POST();
+
+        CompletableFuture<InputStream> response = req.responseAsync()
+                .thenCompose(resp -> {
+                    if (resp.statusCode() != 200)
+                        throw new RuntimeException();
+                    return resp.bodyAsync(HttpResponse.asInputStream());
+                });
+        InputStream is = response.join();
+        File dest = File.createTempFile("foo","bar");
+        dest.deleteOnExit();
+        FileOutputStream os = new FileOutputStream(dest);
+        is.transferTo(os);
+        is.close();
+        os.close();
+        int count = 0;
+        compareFiles(src, dest.toPath());
+        System.err.println("DONE");
+    }
+
+
+    static void simpleTest(boolean secure) throws Exception {
+        URI uri = getURI(secure);
+        System.err.println("Request to " + uri);
+
+        // Do a simple warmup request
+
+        HttpClient client = getClient();
+        HttpRequest req = client.request(uri)
+                .body(HttpRequest.fromString(SIMPLE_STRING))
+                .POST();
+        HttpResponse response = req.response();
+        HttpHeaders h = response.headers();
+
+        checkStatus(200, response.statusCode());
+
+        String responseBody = response.body(HttpResponse.asString());
+        checkStrings(SIMPLE_STRING, responseBody);
+
+        checkStrings(h.firstValue("x-hello").get(), "world");
+        checkStrings(h.firstValue("x-bye").get(), "universe");
+
+        // Do loops asynchronously
+
+        CompletableFuture[] responses = new CompletableFuture[LOOPS];
+        final Path source = java.net.http.TestUtil.getAFile(FILESIZE);
+        for (int i = 0; i < LOOPS; i++) {
+            responses[i] = client.request(uri)
+                .body(HttpRequest.fromFile(source))
+                .version(HTTP_2)
+                .POST()
+                .responseAsync()
+                .thenCompose(r -> r.bodyAsync(HttpResponse.asFile(tempFile())))
+                .thenApply(path -> compareFiles(path, source));
+            Thread.sleep(100);
+        }
+        CompletableFuture.allOf(responses).join();
+        System.err.println("DONE");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/ServerPush.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8087112
+ * @library /lib/testlibrary
+ * @build jdk.testlibrary.SimpleSSLContext
+ * @modules java.httpclient
+ * @compile/module=java.httpclient java/net/http/BodyOutputStream.java
+ * @compile/module=java.httpclient java/net/http/BodyInputStream.java
+ * @compile/module=java.httpclient java/net/http/PushHandler.java
+ * @compile/module=java.httpclient java/net/http/Http2Handler.java
+ * @compile/module=java.httpclient java/net/http/Http2TestExchange.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServerConnection.java
+ * @compile/module=java.httpclient java/net/http/Http2TestServer.java
+ * @compile/module=java.httpclient java/net/http/OutgoingPushPromise.java
+ * @compile/module=java.httpclient java/net/http/TestUtil.java
+ * @run testng/othervm -Djava.net.http.HttpClient.log=requests,responses ServerPush
+ */
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.http.*;
+import java.util.*;
+import java.util.concurrent.*;
+import org.testng.annotations.Test;
+
+public class ServerPush {
+
+    static ExecutorService e = Executors.newCachedThreadPool();
+
+    static final int LOOPS = 13;
+    static final int FILE_SIZE = 32 * 1024;
+
+    static Path tempFile;
+
+    @Test(timeOut=30000)
+    public static void test() throws Exception {
+        Http2TestServer server = null;
+        Path dir = null;
+        try {
+            server = new Http2TestServer(false, 0,
+                                         new PushHandler(FILE_SIZE, LOOPS));
+            tempFile = TestUtil.getAFile(FILE_SIZE);
+
+            System.err.println("Server listening on port " + server.getAddress().getPort());
+            server.start();
+            int port = server.getAddress().getPort();
+            dir = Files.createTempDirectory("serverPush");
+
+            URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo");
+            HttpRequest request = HttpRequest.create(uri)
+                    .version(HttpClient.Version.HTTP_2)
+                    .GET();
+
+            CompletableFuture<Map<URI,Path>> cf =
+            request.multiResponseAsync(HttpResponse.multiFile(dir));
+            Map<URI,Path> results = cf.get();
+
+            //HttpResponse resp = request.response();
+            System.err.println(results.size());
+            Set<URI> uris = results.keySet();
+            for (URI u : uris) {
+                Path result = results.get(u);
+                System.err.printf("%s -> %s\n", u.toString(), result.toString());
+                TestUtil.compareFiles(result, tempFile);
+            }
+            System.out.println("TEST OK");
+        } finally {
+            e.shutdownNow();
+            server.stop();
+            Files.walkFileTree(dir, new SimpleFileVisitor<Path>() {
+                public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+                    dir.toFile().delete();
+                    return FileVisitResult.CONTINUE;
+                }
+                public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
+                    path.toFile().delete();
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/TEST.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,1 @@
+bootclasspath.dirs = /java/net/httpclient
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyInputStream.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,107 @@
+package java.net.http;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+/**
+ * InputStream reads frames off stream q and supplies read demand from any
+ * DataFrames it finds. Window updates are sent back on the connections send
+ * q.
+ */
+class BodyInputStream extends InputStream {
+
+    final Queue<Http2Frame> q;
+    final int streamid;
+    boolean closed;
+    boolean eof;
+    final Http2TestServerConnection conn;
+
+    @SuppressWarnings({"rawtypes","unchecked"})
+    BodyInputStream(Queue q, int streamid, Http2TestServerConnection conn) {
+        this.q = q;
+        this.streamid = streamid;
+        this.conn = conn;
+    }
+
+    DataFrame df;
+    ByteBuffer[] buffers;
+    ByteBuffer buffer;
+    int nextIndex = -1;
+
+    private DataFrame getData() throws IOException {
+        if (eof) {
+            return null;
+        }
+        Http2Frame frame;
+        do {
+            frame = q.take();
+            if (frame.type() == ResetFrame.TYPE) {
+                conn.handleStreamReset((ResetFrame) frame); // throws IOException
+            }
+            // ignoring others for now Wupdates handled elsewhere
+            if (frame.type() != DataFrame.TYPE) {
+                System.out.println("Ignoring " + frame.toString() + " CHECK THIS");
+            }
+        } while (frame.type() != DataFrame.TYPE);
+        df = (DataFrame) frame;
+        int len = df.getDataLength();
+        eof = frame.getFlag(DataFrame.END_STREAM);
+        // acknowledge
+        conn.sendWindowUpdates(len, streamid);
+        return (DataFrame) frame;
+    }
+
+    // null return means EOF
+    private ByteBuffer getBuffer() throws IOException {
+        if (buffer == null || !buffer.hasRemaining()) {
+            if (nextIndex == -1 || nextIndex == buffers.length) {
+                DataFrame df = getData();
+                if (df == null) {
+                    return null;
+                }
+                int len = df.getDataLength();
+                if ((len == 0) && eof) {
+                    return null;
+                }
+                buffers = df.getData();
+                nextIndex = 0;
+            }
+            buffer = buffers[nextIndex++];
+        }
+        return buffer;
+    }
+
+    @Override
+    public int read(byte[] buf, int offset, int length) throws IOException {
+        if (closed) {
+            throw new IOException("closed");
+        }
+        ByteBuffer b = getBuffer();
+        if (b == null) {
+            return -1;
+        }
+        int remaining = b.remaining();
+        if (remaining < length) {
+            length = remaining;
+        }
+        b.get(buf, offset, length);
+        return length;
+    }
+
+    byte[] one = new byte[1];
+
+    @Override
+    public int read() throws IOException {
+        int c = read(one, 0, 1);
+        if (c == -1) {
+            return -1;
+        }
+        return one[0];
+    }
+
+    @Override
+    public void close() {
+        // TODO reset this stream
+        closed = true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/BodyOutputStream.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,106 @@
+package java.net.http;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+/**
+ * OutputStream. Incoming window updates handled by the main connection
+ * reader thread.
+ */
+@SuppressWarnings({"rawtypes","unchecked"})
+class BodyOutputStream extends OutputStream {
+    final static byte[] EMPTY_BARRAY = new byte[0];
+
+    final int streamid;
+    int window;
+    boolean closed;
+    boolean goodToGo = false; // not allowed to send until headers sent
+    final Http2TestServerConnection conn;
+    final Queue outputQ;
+
+    BodyOutputStream(int streamid, int initialWindow, Http2TestServerConnection conn) {
+        this.window = initialWindow;
+        this.streamid = streamid;
+        this.conn = conn;
+        this.outputQ = conn.outputQ;
+        conn.registerStreamWindowUpdater(streamid, this::updateWindow);
+    }
+
+    // called from connection reader thread as all incoming window
+    // updates are handled there.
+    synchronized void updateWindow(int update) {
+        window += update;
+        notifyAll();
+    }
+
+    void waitForWindow(int demand) throws InterruptedException {
+        // first wait for the connection window
+        conn.obtainConnectionWindow(demand);
+        // now wait for the stream window
+        synchronized (this) {
+            while (demand > 0) {
+                int n = Math.min(demand, window);
+                demand -= n;
+                window -= n;
+                if (demand > 0) {
+                    wait();
+                }
+            }
+        }
+    }
+
+    void goodToGo() {
+        goodToGo = true;
+    }
+
+    @Override
+    public void write(byte[] buf, int offset, int len) throws IOException {
+        if (closed) {
+            throw new IOException("closed");
+        }
+
+        if (!goodToGo) {
+            throw new IllegalStateException("sendResponseHeaders must be called first");
+        }
+        try {
+            waitForWindow(len);
+            send(buf, offset, len, 0);
+        } catch (InterruptedException ex) {
+            throw new IOException(ex);
+        }
+    }
+
+    private void send(byte[] buf, int offset, int len, int flags) throws IOException {
+        ByteBuffer buffer = ByteBuffer.allocate(len);
+        buffer.put(buf, offset, len);
+        buffer.flip();
+        DataFrame df = new DataFrame();
+        assert streamid != 0;
+        df.streamid(streamid);
+        df.setFlags(flags);
+        df.setData(buffer);
+        outputQ.put(df);
+    }
+
+    byte[] one = new byte[1];
+
+    @Override
+    public void write(int b) throws IOException {
+        one[0] = (byte) b;
+        write(one, 0, 1);
+    }
+
+    @Override
+    public void close() {
+        if (closed) {
+            return;
+        }
+        closed = true;
+        try {
+            send(EMPTY_BARRAY, 0, 0, DataFrame.END_STREAM);
+        } catch (IOException ex) {
+            System.err.println("TestServer: OutputStream.close exception: " + ex);
+            ex.printStackTrace();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/EchoHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.io.*;
+import java.net.*;
+
+public class EchoHandler implements Http2Handler {
+    public EchoHandler() {}
+
+    @Override
+    public void handle(Http2TestExchange t)
+            throws IOException {
+        try {
+            System.err.println("EchoHandler received request to " + t.getRequestURI());
+            InputStream is = t.getRequestBody();
+            HttpHeadersImpl map = t.getRequestHeaders();
+            HttpHeadersImpl map1 = t.getResponseHeaders();
+            map1.addHeader("X-Hello", "world");
+            map1.addHeader("X-Bye", "universe");
+            String fixedrequest = map.firstValue("XFixed").orElse(null);
+            File outfile = File.createTempFile("foo", "bar");
+            FileOutputStream fos = new FileOutputStream(outfile);
+            int count = (int) is.transferTo(fos);
+            System.err.printf("EchoHandler read %d bytes\n", count);
+            is.close();
+            fos.close();
+            InputStream is1 = new FileInputStream(outfile);
+            OutputStream os = null;
+            // return the number of bytes received (no echo)
+            String summary = map.firstValue("XSummary").orElse(null);
+            if (fixedrequest != null && summary == null) {
+                t.sendResponseHeaders(200, count);
+                os = t.getResponseBody();
+                is1.transferTo(os);
+            } else {
+                t.sendResponseHeaders(200, 0);
+                os = t.getResponseBody();
+                int count1 = (int)is1.transferTo(os);
+                System.err.printf("EchoHandler wrote %d bytes\n", count1);
+
+                if (summary != null) {
+                    String s = Integer.toString(count);
+                    os.write(s.getBytes());
+                }
+            }
+            outfile.delete();
+            os.close();
+            is1.close();
+        } catch (Throwable e) {
+            e.printStackTrace();
+            throw new IOException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2Handler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,18 @@
+package java.net.http;
+
+import java.io.IOException;
+
+/**
+ * A handler which is invoked to process HTTP exchanges. Each
+ * HTTP exchange is handled by one of these handlers.
+ */
+public interface Http2Handler {
+    /**
+     * Handle the given request and generate an appropriate response.
+     * @param exchange the exchange containing the request from the
+     *      client and used to send the response
+     * @throws NullPointerException if exchange is <code>null</code>
+     */
+    public abstract void handle (Http2TestExchange exchange) throws IOException;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestExchange.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,126 @@
+package java.net.http;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.InetSocketAddress;
+
+public class Http2TestExchange {
+
+    final HttpHeadersImpl reqheaders;
+    final HttpHeadersImpl rspheaders;
+    final URI uri;
+    final String method;
+    final InputStream is;
+    final BodyOutputStream os;
+    final int streamid;
+    final boolean pushAllowed;
+    final Http2TestServerConnection conn;
+    final Http2TestServer server;
+
+    int responseCode = -1;
+    long responseLength;
+
+    Http2TestExchange(int streamid, String method, HttpHeadersImpl reqheaders,
+            HttpHeadersImpl rspheaders, URI uri, InputStream is,
+            BodyOutputStream os, Http2TestServerConnection conn, boolean pushAllowed) {
+        this.reqheaders = reqheaders;
+        this.rspheaders = rspheaders;
+        this.uri = uri;
+        this.method = method;
+        this.is = is;
+        this.streamid = streamid;
+        this.os = os;
+        this.pushAllowed = pushAllowed;
+        this.conn = conn;
+        this.server = conn.server;
+    }
+
+    public HttpHeadersImpl getRequestHeaders() {
+        return reqheaders;
+    }
+
+    public HttpHeadersImpl getResponseHeaders() {
+        return rspheaders;
+    }
+
+    public URI getRequestURI() {
+        return uri;
+    }
+
+    public String getRequestMethod() {
+        return method;
+    }
+
+    public void close() {
+        try {
+            is.close();
+            os.close();
+        } catch (IOException e) {
+            System.err.println("TestServer: HttpExchange.close exception: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    public InputStream getRequestBody() {
+        return is;
+    }
+
+    public OutputStream getResponseBody() {
+        return os;
+    }
+
+    public void sendResponseHeaders(int rCode, long responseLength) throws IOException {
+        this.responseLength = responseLength;
+        if (responseLength > 0 || responseLength < 0) {
+                long clen = responseLength > 0 ? responseLength : 0;
+            rspheaders.setHeader("Content-length", Long.toString(clen));
+        }
+
+        rspheaders.setHeader(":status", Integer.toString(rCode));
+
+        Http2TestServerConnection.ResponseHeaders response
+                = new Http2TestServerConnection.ResponseHeaders(rspheaders);
+        response.streamid(streamid);
+        response.setFlag(HeaderFrame.END_HEADERS);
+        conn.outputQ.put(response);
+        os.goodToGo();
+        System.err.println("Sent response headers " + rCode);
+    }
+
+    public InetSocketAddress getRemoteAddress() {
+        return (InetSocketAddress) conn.socket.getRemoteSocketAddress();
+    }
+
+    public int getResponseCode() {
+        return responseCode;
+    }
+
+    public InetSocketAddress getLocalAddress() {
+        return server.getAddress();
+    }
+
+    public String getProtocol() {
+        return "HTTP/2";
+    }
+
+    public boolean serverPushAllowed() {
+        return pushAllowed;
+    }
+
+    public void serverPush(URI uri, HttpHeadersImpl headers, InputStream content) {
+        OutgoingPushPromise pp = new OutgoingPushPromise(
+                streamid, uri, headers, content);
+        headers.setHeader(":method", "GET");
+        headers.setHeader(":scheme", uri.getScheme());
+        headers.setHeader(":authority", uri.getAuthority());
+        headers.setHeader(":path", uri.getPath());
+        try {
+            conn.outputQ.put(pp);
+            // writeLoop will spin up thread to read the InputStream
+        } catch (IOException ex) {
+            System.err.println("TestServer: pushPromise exception: " + ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.net.*;
+import java.util.HashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import javax.net.ServerSocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+
+/**
+ * Waits for incoming TCP connections from a client and establishes
+ * a HTTP2 connection. Two threads are created per connection. One for reading
+ * and one for writing. Incoming requests are dispatched to the supplied
+ * Http2Handler on additional threads. All threads
+ * obtained from the supplied ExecutorService.
+ */
+public class Http2TestServer {
+    final ServerSocket server;
+    boolean secure;
+    SettingsFrame serverSettings, clientSettings;
+    final ExecutorService exec;
+    volatile boolean stopping = false;
+    final Http2Handler handler;
+    final SSLContext sslContext;
+    final HashMap<InetSocketAddress,Http2TestServerConnection> connections;
+
+    private static ThreadFactory defaultThreadFac =
+        (Runnable r) -> {
+            Thread t = new Thread(r);
+            t.setName("Test-server-pool");
+            return t;
+        };
+
+
+    private static ExecutorService getDefaultExecutor() {
+        return Executors.newCachedThreadPool(defaultThreadFac);
+    }
+
+    public Http2TestServer(boolean secure, int port, Http2Handler handler) throws Exception {
+        this(secure, port, handler, getDefaultExecutor(), null);
+    }
+
+    public InetSocketAddress getAddress() {
+        return (InetSocketAddress)server.getLocalSocketAddress();
+    }
+
+    /**
+     * Create a Http2Server listening on the given port. Currently needs
+     * to know in advance whether incoming connections are plain TCP "h2c"
+     * or TLS "h2"/
+     *
+     * @param secure https or http
+     * @param port listen port
+     * @param handler the handler which receives incoming requests
+     * @param exec executor service (cached thread pool is used if null)
+     * @param context the SSLContext used when secure is true
+     * @throws Exception
+     */
+    public Http2TestServer(boolean secure, int port, Http2Handler handler,
+            ExecutorService exec, SSLContext context) throws Exception {
+        if (secure) {
+            server = initSecure(port);
+        } else {
+            server = initPlaintext(port);
+        }
+        this.secure = secure;
+        this.exec = exec == null ? getDefaultExecutor() : exec;
+        this.handler = handler;
+        this.sslContext = context;
+        this.connections = new HashMap<>();
+    }
+
+    final ServerSocket initPlaintext(int port) throws Exception {
+        return new ServerSocket(port);
+    }
+
+    public void stop() {
+        // TODO: clean shutdown GoAway
+        stopping = true;
+        for (Http2TestServerConnection connection : connections.values()) {
+            connection.close();
+        }
+        try {
+            server.close();
+        } catch (IOException e) {}
+        exec.shutdownNow();
+    }
+
+
+    final ServerSocket initSecure(int port) throws Exception {
+        ServerSocketFactory fac;
+        if (sslContext != null) {
+            fac = sslContext.getServerSocketFactory();
+        } else {
+            fac = SSLServerSocketFactory.getDefault();
+        }
+        SSLServerSocket se = (SSLServerSocket) fac.createServerSocket(port);
+        SSLParameters sslp = se.getSSLParameters();
+        sslp.setApplicationProtocols(new String[]{"h2"});
+        se.setSSLParameters(sslp);
+        se.setEnabledCipherSuites(se.getSupportedCipherSuites());
+        se.setEnabledProtocols(se.getSupportedProtocols());
+        // other initialisation here
+        return se;
+    }
+
+    /**
+     * Start thread which waits for incoming connections.
+     *
+     * @throws Exception
+     */
+    public void start() {
+        exec.submit(() -> {
+            try {
+                while (!stopping) {
+                    Socket socket = server.accept();
+                    InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
+                    Http2TestServerConnection c = new Http2TestServerConnection(this, socket);
+                    connections.put(addr, c);
+                    c.run();
+                }
+            } catch (Throwable e) {
+                if (!stopping) {
+                    System.err.println("TestServer: start exception: " + e);
+                    e.printStackTrace();
+                }
+            }
+        });
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/Http2TestServerConnection.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import static java.net.http.SettingsFrame.HEADER_TABLE_SIZE;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import sun.net.httpclient.hpack.Decoder;
+import sun.net.httpclient.hpack.DecodingCallback;
+import sun.net.httpclient.hpack.Encoder;
+
+/**
+ * Represents one HTTP2 connection, either plaintext upgraded from HTTP/1.1
+ * or HTTPS opened using "h2" ALPN.
+ */
+public class Http2TestServerConnection {
+    final Http2TestServer server;
+    @SuppressWarnings({"rawtypes","unchecked"})
+    final Map<Integer, Queue> streams; // input q per stream
+    final Queue<Http2Frame> outputQ;
+    int nextstream;
+    final Socket socket;
+    final InputStream is;
+    final OutputStream os;
+    Encoder hpackOut;
+    Decoder hpackIn;
+    SettingsFrame clientSettings, serverSettings;
+    final ExecutorService exec;
+    final boolean secure;
+    final Http2Handler handler;
+    volatile boolean stopping;
+    int nextPushStreamId = 2;
+
+    final static ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0);
+    final static byte[] EMPTY_BARRAY = new byte[0];
+
+    final static byte[] clientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n".getBytes();
+
+    Http2TestServerConnection(Http2TestServer server, Socket socket) throws IOException {
+        System.err.println("New connection from " + socket);
+        this.server = server;
+        this.streams = Collections.synchronizedMap(new HashMap<>());
+        this.outputQ = new Queue<>();
+        this.socket = socket;
+        this.clientSettings = server.clientSettings;
+        this.serverSettings = server.serverSettings;
+        this.exec = server.exec;
+        this.secure = server.secure;
+        this.handler = server.handler;
+        is = new BufferedInputStream(socket.getInputStream());
+        os = new BufferedOutputStream(socket.getOutputStream());
+    }
+
+    void close() {
+        streams.forEach((i, q) -> {
+            q.close();
+        });
+        stopping = true;
+        try {
+            socket.close();
+            // TODO: put a reset on each stream
+        } catch (IOException e) {
+        }
+    }
+
+    private void readPreface() throws IOException {
+        int len = clientPreface.length;
+        byte[] bytes = new byte[len];
+        is.readNBytes(bytes, 0, len);
+        if (Arrays.compare(clientPreface, bytes) != 0) {
+            throw new IOException("Invalid preface: " + new String(bytes, 0, len));
+        }
+    }
+
+    String doUpgrade() throws IOException {
+        String upgrade = readHttp1Request();
+        String h2c = getHeader(upgrade, "Upgrade");
+        if (h2c == null || !h2c.equals("h2c")) {
+            throw new IOException("Bad upgrade 1 " + h2c);
+        }
+
+        sendHttp1Response(101, "Switching Protocols", "Connection", "Upgrade",
+                "Upgrade", "h2c");
+
+        sendSettingsFrame();
+        readPreface();
+
+        String clientSettingsString = getHeader(upgrade, "HTTP2-Settings");
+        clientSettings = getSettingsFromString(clientSettingsString);
+
+        return upgrade;
+    }
+
+    /**
+     * Client settings payload provided in base64 HTTP1 header. Decode it
+     * and add a header so we can interpret it.
+     *
+     * @param s
+     * @return
+     * @throws IOException
+     */
+    private SettingsFrame getSettingsFromString(String s) throws IOException {
+        Base64.Decoder decoder = Base64.getUrlDecoder();
+        byte[] payload = decoder.decode(s);
+        ByteBuffer bb1 = ByteBuffer.wrap(payload);
+        // simulate header of Settings Frame
+        ByteBuffer bb0 = ByteBuffer.wrap(
+                new byte[] {0, 0, (byte)payload.length, 4, 0, 0, 0, 0, 0});
+        ByteBufferConsumer bbc = new ByteBufferConsumer(
+                new LinkedList<ByteBuffer>(List.of(bb0, bb1)),
+                this::getBuffer);
+        Http2Frame frame = Http2Frame.readIncoming(bbc);
+        if (!(frame instanceof SettingsFrame))
+            throw new IOException("Expected SettingsFrame");
+        return (SettingsFrame)frame;
+    }
+
+    void run() throws Exception {
+        String upgrade = null;
+        if (!secure) {
+            upgrade = doUpgrade();
+        } else {
+            readPreface();
+            sendSettingsFrame(true);
+            clientSettings = (SettingsFrame) readFrame();
+            nextstream = 1;
+        }
+
+        hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE));
+        hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE));
+
+        exec.submit(() -> {
+            readLoop();
+        });
+        exec.submit(() -> {
+            writeLoop();
+        });
+        if (!secure) {
+            createPrimordialStream(upgrade);
+            nextstream = 3;
+        }
+    }
+
+    static class BufferPool implements BufferHandler {
+
+        public void setMinBufferSize(int size) {
+        }
+
+        public ByteBuffer getBuffer(int size) {
+            if (size == -1)
+                size = 32 * 1024;
+            return ByteBuffer.allocate(size);
+        }
+
+        public void returnBuffer(ByteBuffer buffer) {
+        }
+    }
+
+    static BufferPool bufferpool = new BufferPool();
+
+    private void writeFrame(Http2Frame frame) throws IOException {
+        ByteBufferGenerator bg = new ByteBufferGenerator(bufferpool);
+        frame.computeLength();
+        System.err.println("Writing frame " + frame.toString());
+        frame.writeOutgoing(bg);
+        ByteBuffer[] bufs = bg.getBufferArray();
+        int c = 0;
+        for (ByteBuffer buf : bufs) {
+            byte[] ba = buf.array();
+            int start = buf.arrayOffset() + buf.position();
+            c += buf.remaining();
+            os.write(ba, start, buf.remaining());
+        }
+        os.flush();
+        System.err.printf("wrote %d bytes\n", c);
+    }
+
+    void handleStreamReset(ResetFrame resetFrame) throws IOException {
+        // TODO: cleanup
+        throw new IOException("Stream reset");
+    }
+
+    private void handleCommonFrame(Http2Frame f) throws IOException {
+        if (f instanceof SettingsFrame) {
+            serverSettings = (SettingsFrame) f;
+            if (serverSettings.getFlag(SettingsFrame.ACK)) // ignore
+            {
+                return;
+            }
+            // otherwise acknowledge it
+            SettingsFrame frame = new SettingsFrame();
+            frame.setFlag(SettingsFrame.ACK);
+            frame.streamid(0);
+            outputQ.put(frame);
+            return;
+        }
+        System.err.println("Received ---> " + f.toString());
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    void sendWindowUpdates(int len, int streamid) throws IOException {
+        if (len == 0)
+            return;
+        WindowUpdateFrame wup = new WindowUpdateFrame();
+        wup.streamid(streamid);
+        wup.setUpdate(len);
+        outputQ.put(wup);
+        wup = new WindowUpdateFrame();
+        wup.streamid(0);
+        wup.setUpdate(len);
+        outputQ.put(wup);
+    }
+
+    HttpHeadersImpl decodeHeaders(List<HeaderFrame> frames) {
+        HttpHeadersImpl headers = new HttpHeadersImpl();
+
+        DecodingCallback cb = (name, value) -> {
+            headers.addHeader(name.toString(), value.toString());
+        };
+
+        for (HeaderFrame frame : frames) {
+            ByteBuffer[] buffers = frame.getHeaderBlock();
+            for (ByteBuffer buffer : buffers) {
+                hpackIn.decode(buffer, false, cb);
+            }
+        }
+        hpackIn.decode(EMPTY_BUFFER, true, cb);
+        return headers;
+    }
+
+    String getRequestLine(String request) {
+        int eol = request.indexOf(CRLF);
+        return request.substring(0, eol);
+    }
+
+    // First stream (1) comes from a plaintext HTTP/1.1 request
+    @SuppressWarnings({"rawtypes","unchecked"})
+    void createPrimordialStream(String request) throws IOException {
+        HttpHeadersImpl headers = new HttpHeadersImpl();
+        String requestLine = getRequestLine(request);
+        String[] tokens = requestLine.split(" ");
+        if (!tokens[2].equals("HTTP/1.1")) {
+            throw new IOException("bad request line");
+        }
+        URI uri = null;
+        try {
+            uri = new URI(tokens[1]);
+        } catch (URISyntaxException e) {
+            throw new IOException(e);
+        }
+        String host = getHeader(request, "Host");
+        if (host == null) {
+            throw new IOException("missing Host");
+        }
+
+        headers.setHeader(":method", tokens[0]);
+        headers.setHeader(":scheme", "http"); // always in this case
+        headers.setHeader(":authority", host);
+        headers.setHeader(":path", uri.getPath());
+        Queue q = new Queue();
+        String body = getRequestBody(request);
+        headers.setHeader("Content-length", Integer.toString(body.length()));
+
+        addRequestBodyToQueue(body, q);
+        streams.put(1, q);
+        exec.submit(() -> {
+            handleRequest(headers, q, 1);
+        });
+    }
+
+    // all other streams created here
+    @SuppressWarnings({"rawtypes","unchecked"})
+    void createStream(HeaderFrame frame) throws IOException {
+        List<HeaderFrame> frames = new LinkedList<>();
+        frames.add(frame);
+        int streamid = frame.streamid();
+        if (streamid != nextstream) {
+            throw new IOException("unexpected stream id");
+        }
+        nextstream += 2;
+
+        while (!frame.getFlag(HeaderFrame.END_HEADERS)) {
+            Http2Frame f = readFrame();
+            if (!(f instanceof HeaderFrame)) {
+                handleCommonFrame(f); // should only be error frames
+            } else {
+                frame = (HeaderFrame) f;
+                frames.add(frame);
+            }
+        }
+        HttpHeadersImpl headers = decodeHeaders(frames);
+        Queue q = new Queue();
+        streams.put(streamid, q);
+        exec.submit(() -> {
+            handleRequest(headers, q, streamid);
+        });
+    }
+
+    // runs in own thread. Handles request from start to finish. Incoming frames
+    // for this stream/request delivered on Q
+
+    @SuppressWarnings({"rawtypes","unchecked"})
+    void handleRequest(HttpHeadersImpl headers, Queue queue, int streamid) {
+        String method = headers.firstValue(":method").orElse("");
+        System.out.println("method = " + method);
+        String path = headers.firstValue(":path").orElse("");
+        System.out.println("path = " + path);
+        String scheme = headers.firstValue(":scheme").orElse("");
+        System.out.println("scheme = " + scheme);
+        String authority = headers.firstValue(":authority").orElse("");
+        System.out.println("authority = " + authority);
+        HttpHeadersImpl rspheaders = new HttpHeadersImpl();
+        int winsize = clientSettings.getParameter(
+                        SettingsFrame.INITIAL_WINDOW_SIZE);
+        System.err.println ("Stream window size = " + winsize);
+        try (
+            BodyInputStream bis = new BodyInputStream(queue, streamid, this);
+            BodyOutputStream bos = new BodyOutputStream(streamid, winsize, this);
+        )
+        {
+            String us = scheme + "://" + authority + path;
+            URI uri = new URI(us);
+            boolean pushAllowed = clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1;
+            Http2TestExchange exchange = new Http2TestExchange(streamid, method,
+                    headers, rspheaders, uri, bis, bos, this, pushAllowed);
+
+            // give to user
+            handler.handle(exchange);
+
+            // everything happens in the exchange from here. Hopefully will
+            // return though.
+        } catch (Throwable e) {
+            System.err.println("TestServer: handleRequest exception: " + e);
+            e.printStackTrace();
+        }
+    }
+
+    // Runs in own thread
+
+    @SuppressWarnings({"rawtypes","unchecked"})
+    void readLoop() {
+        try {
+            while (!stopping) {
+                Http2Frame frame = readFrame();
+                int stream = frame.streamid();
+                if (stream == 0) {
+                    if (frame.type() == WindowUpdateFrame.TYPE) {
+                        WindowUpdateFrame wup = (WindowUpdateFrame) frame;
+                        updateConnectionWindow(wup.getUpdate());
+                    } else {
+                        // other common frame types
+                        handleCommonFrame(frame);
+                    }
+                } else {
+                    Queue q = streams.get(stream);
+                    if (frame.type() == HeadersFrame.TYPE) {
+                        if (q != null) {
+                            System.err.println("HEADERS frame for existing stream! Error.");
+                            // TODO: close connection
+                            continue;
+                        } else {
+                            createStream((HeadersFrame) frame);
+                        }
+                    } else {
+                        if (q == null) {
+                            System.err.printf("Non Headers frame received with"+
+                                " non existing stream (%d) ", frame.streamid());
+                            System.err.println(frame);
+                            continue;
+                        }
+                        if (frame.type() == WindowUpdateFrame.TYPE) {
+                            WindowUpdateFrame wup = (WindowUpdateFrame) frame;
+                            synchronized (updaters) {
+                                Consumer<Integer> r = updaters.get(stream);
+                                r.accept(wup.getUpdate());
+                            }
+                        } else {
+                            q.put(frame);
+                        }
+                    }
+                }
+            }
+        } catch (Throwable e) {
+            close();
+            if (!stopping) {
+                System.err.println("Http server reader thread shutdown");
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // set streamid outside plus other specific fields
+    void encodeHeaders(HttpHeadersImpl headers, HeaderFrame out) {
+        List<ByteBuffer> buffers = new LinkedList<>();
+
+        ByteBuffer buf = getBuffer();
+        boolean encoded;
+        for (Map.Entry<String, List<String>> entry : headers.map().entrySet()) {
+            List<String> values = entry.getValue();
+            String key = entry.getKey().toLowerCase();
+            for (String value : values) {
+                do {
+                    hpackOut.header(key, value);
+                    encoded = hpackOut.encode(buf);
+                    if (!encoded) {
+                        buf.flip();
+                        buffers.add(buf);
+                        buf = getBuffer();
+                    }
+                } while (!encoded);
+            }
+        }
+        buf.flip();
+        buffers.add(buf);
+        out.setFlags(HeaderFrame.END_HEADERS);
+        out.setHeaderBlock(buffers.toArray(bbarray));
+    }
+
+    static void closeIgnore(Closeable c) {
+        try {
+            c.close();
+        } catch (IOException e) {}
+    }
+
+    // Runs in own thread
+    void writeLoop() {
+        try {
+            while (!stopping) {
+                Http2Frame frame = outputQ.take();
+                if (frame instanceof ResponseHeaders) {
+                    ResponseHeaders rh = (ResponseHeaders)frame;
+                    HeadersFrame hf = new HeadersFrame();
+                    encodeHeaders(rh.headers, hf);
+                    hf.streamid(rh.streamid());
+                    writeFrame(hf);
+                } else if (frame instanceof OutgoingPushPromise) {
+                    handlePush((OutgoingPushPromise)frame);
+                } else
+                    writeFrame(frame);
+            }
+            System.err.println("Connection writer stopping");
+        } catch (Throwable e) {
+            e.printStackTrace();
+            /*close();
+            if (!stopping) {
+                e.printStackTrace();
+                System.err.println("TestServer: writeLoop exception: " + e);
+            }*/
+        }
+    }
+
+    private void handlePush(OutgoingPushPromise op) throws IOException {
+        PushPromiseFrame pp = new PushPromiseFrame();
+        encodeHeaders(op.headers, pp);
+        int promisedStreamid = nextPushStreamId;
+        nextPushStreamId += 2;
+        pp.streamid(op.parentStream);
+        pp.setPromisedStream(promisedStreamid);
+        writeFrame(pp);
+        final InputStream ii = op.is;
+        final BodyOutputStream oo = new BodyOutputStream(
+                promisedStreamid,
+                clientSettings.getParameter(
+                        SettingsFrame.INITIAL_WINDOW_SIZE), this);
+        oo.goodToGo();
+        exec.submit(() -> {
+            try {
+                ResponseHeaders oh = getPushResponse(promisedStreamid);
+                outputQ.put(oh);
+                ii.transferTo(oo);
+            } catch (Throwable ex) {
+                System.err.printf("TestServer: pushing response error: %s\n",
+                        ex.toString());
+            } finally {
+                closeIgnore(ii);
+                closeIgnore(oo);
+            }
+        });
+
+    }
+
+    // returns a minimal response with status 200
+    // that is the response to the push promise just sent
+    private ResponseHeaders getPushResponse(int streamid) {
+        HttpHeadersImpl h = new HttpHeadersImpl();
+        h.addHeader(":status", "200");
+        ResponseHeaders oh = new ResponseHeaders(h);
+        oh.streamid(streamid);
+        return oh;
+    }
+
+    private ByteBuffer getBuffer() {
+        return ByteBuffer.allocate(8 * 1024);
+    }
+
+    private Http2Frame readFrame() throws IOException {
+        byte[] buf = new byte[9];
+        if (is.readNBytes(buf, 0, 9) != 9)
+            throw new IOException("readFrame: connection closed");
+        int len = 0;
+        for (int i = 0; i < 3; i++) {
+            int n = buf[i] & 0xff;
+            //System.err.println("n = " + n);
+            len = (len << 8) + n;
+        }
+        byte[] rest = new byte[len];
+        int n = is.readNBytes(rest, 0, len);
+        if (n != len)
+            throw new IOException("Error reading frame");
+        ByteBufferConsumer bc = new ByteBufferConsumer(
+                new LinkedList<ByteBuffer>(List.of(ByteBuffer.wrap(buf), ByteBuffer.wrap(rest))),
+                this::getBuffer);
+        return Http2Frame.readIncoming(bc);
+    }
+
+    void sendSettingsFrame() throws IOException {
+        sendSettingsFrame(false);
+    }
+
+    void sendSettingsFrame(boolean now) throws IOException {
+        if (serverSettings == null) {
+            serverSettings = SettingsFrame.getDefaultSettings();
+        }
+        if (now) {
+            writeFrame(serverSettings);
+        } else {
+            outputQ.put(serverSettings);
+        }
+    }
+
+    String readUntil(String end) throws IOException {
+        int number = end.length();
+        int found = 0;
+        StringBuilder sb = new StringBuilder();
+        while (found < number) {
+            char expected = end.charAt(found);
+            int c = is.read();
+            if (c == -1) {
+                throw new IOException("Connection closed");
+            }
+            char c0 = (char) c;
+            sb.append(c0);
+            if (c0 != expected) {
+                found = 0;
+                continue;
+            }
+            found++;
+        }
+        return sb.toString();
+    }
+
+    private int getContentLength(String headers) {
+        return getIntHeader(headers, "Content-length");
+    }
+
+    private int getIntHeader(String headers, String name) {
+        String val = getHeader(headers, name);
+        if (val == null) {
+            return -1;
+        }
+        return Integer.parseInt(val);
+    }
+
+    private String getHeader(String headers, String name) {
+        String headers1 = headers.toLowerCase(); // not efficient
+        name = CRLF + name.toLowerCase();
+        int start = headers1.indexOf(name);
+        if (start == -1) {
+            return null;
+        }
+        start += 2;
+        int end = headers1.indexOf(CRLF, start);
+        String line = headers.substring(start, end);
+        start = line.indexOf(':');
+        if (start == -1) {
+            return null;
+        }
+        return line.substring(start + 1).trim();
+    }
+
+    final static String CRLF = "\r\n";
+
+    String readHttp1Request() throws IOException {
+        String headers = readUntil(CRLF + CRLF);
+        int clen = getContentLength(headers);
+        // read the content. There shouldn't be content but ..
+        byte[] buf = new byte[clen];
+        is.readNBytes(buf, 0, clen);
+        String body = new String(buf, "US-ASCII");
+        return headers + body;
+    }
+
+    void sendHttp1Response(int code, String msg, String... headers) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        sb.append("HTTP/1.1 ")
+                .append(code)
+                .append(' ')
+                .append(msg)
+                .append(CRLF);
+        int numheaders = headers.length;
+        for (int i = 0; i < numheaders; i += 2) {
+            sb.append(headers[i])
+                    .append(": ")
+                    .append(headers[i + 1])
+                    .append(CRLF);
+        }
+        sb.append(CRLF);
+        String s = sb.toString();
+        os.write(s.getBytes("US-ASCII"));
+        os.flush();
+    }
+
+    private void unexpectedFrame(Http2Frame frame) {
+        System.err.println("OOPS. Unexpected");
+        assert false;
+    }
+
+    final static ByteBuffer[] bbarray = new ByteBuffer[0];
+
+    // wrapper around a BlockingQueue that throws an exception when it's closed
+    // Each stream has one of these
+
+    String getRequestBody(String request) {
+        int bodystart = request.indexOf(CRLF+CRLF);
+        String body;
+        if (bodystart == -1)
+            body = "";
+        else
+            body = request.substring(bodystart+4);
+        return body;
+    }
+
+    @SuppressWarnings({"rawtypes","unchecked"})
+    void addRequestBodyToQueue(String body, Queue q) throws IOException {
+        ByteBuffer buf = ByteBuffer.wrap(body.getBytes(StandardCharsets.US_ASCII));
+        DataFrame df = new DataFrame();
+        df.streamid(1); // only used for primordial stream
+        df.setData(buf);
+        df.computeLength();
+        df.setFlag(DataFrame.END_STREAM);
+        q.put(df);
+    }
+
+    // window updates done in main reader thread because they may
+    // be used to unblock BodyOutputStreams waiting for WUPs
+
+    HashMap<Integer,Consumer<Integer>> updaters = new HashMap<>();
+
+    void registerStreamWindowUpdater(int streamid, Consumer<Integer> r) {
+        synchronized(updaters) {
+            updaters.put(streamid, r);
+        }
+    }
+
+    int sendWindow = 64 * 1024 - 1; // connection level send window
+
+    /**
+     * BodyOutputStreams call this to get the connection window first.
+     *
+     * @param amount
+     */
+    synchronized void obtainConnectionWindow(int amount) throws InterruptedException {
+       while (amount > 0) {
+           int n = Math.min(amount, sendWindow);
+           amount -= n;
+           sendWindow -= n;
+           if (amount > 0)
+               wait();
+       }
+    }
+
+    synchronized void updateConnectionWindow(int amount) {
+        sendWindow += amount;
+        notifyAll();
+    }
+
+    // simplified output headers class. really just a type safe container
+    // for the hashmap.
+
+    static class ResponseHeaders extends Http2Frame {
+        HttpHeadersImpl headers;
+
+        ResponseHeaders(HttpHeadersImpl headers) {
+            this.headers = headers;
+        }
+
+        @Override
+        void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+            throw new UnsupportedOperationException("Not supported ever!");
+        }
+
+        @Override
+        void computeLength() {
+            throw new UnsupportedOperationException("Not supported ever!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/OutgoingPushPromise.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,31 @@
+package java.net.http;
+
+import java.io.*;
+import java.net.*;
+
+// will be converted to a PushPromiseFrame in the writeLoop
+// a thread is then created to produce the DataFrames from the InputStream
+class OutgoingPushPromise extends Http2Frame {
+    final HttpHeadersImpl headers;
+    final URI uri;
+    final InputStream is;
+    final int parentStream; // not the pushed streamid
+
+    OutgoingPushPromise(int parentStream, URI uri, HttpHeadersImpl headers, InputStream is) {
+        this.uri = uri;
+        this.headers = headers;
+        this.is = is;
+        this.parentStream = parentStream;
+    }
+
+    @Override
+    void readIncomingImpl(ByteBufferConsumer bc) throws IOException {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+    @Override
+    void computeLength() {
+        throw new UnsupportedOperationException("Not supported yet.");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/PushHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.nio.file.attribute.*;
+import java.net.http.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class PushHandler implements Http2Handler {
+
+    final Path tempFile;
+    final int loops;
+
+    public PushHandler(int file_size, int loops) throws Exception {
+        tempFile = TestUtil.getAFile(file_size);
+        this.loops = loops;
+    }
+
+    int invocation = 0;
+
+    public void handle(Http2TestExchange ee) {
+        try {
+            System.err.println ("Server: handle " + ee);
+            invocation++;
+
+            if (ee.serverPushAllowed()) {
+                for (int i=0; i<loops; i++) {
+                    InputStream is = new FileInputStream(tempFile.toFile());
+                    URI u = new URI ("http://www.foo.com/" + Integer.toString(i));
+                    HttpHeadersImpl h = new HttpHeadersImpl();
+                    h.addHeader("X-foo", "bar");
+                    ee.serverPush(u, h, is);
+                }
+                System.err.println ("Server: sent all pushes");
+            }
+            ee.sendResponseHeaders(200, 0);
+            OutputStream os = ee.getResponseBody();
+            InputStream iis = new FileInputStream(tempFile.toFile());
+            iis.transferTo(os);
+            os.close();
+            iis.close();
+        } catch (Exception ex) {
+            System.err.println ("Server: exception " + ex);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/httpclient/http2/java.httpclient/java/net/http/TestUtil.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.io.*;
+import java.net.*;
+import java.nio.file.*;
+import java.util.concurrent.*;
+import java.util.Arrays;
+
+public class TestUtil {
+
+    final static String fileContent = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // repeated
+
+    public static Path getAFile(int size) throws IOException {
+        Path p = tempFile();
+        BufferedWriter writer = Files.newBufferedWriter(p);
+        int len = fileContent.length();
+        int iterations = size / len;
+        int remainder = size - (iterations * len);
+        for (int i=0; i<iterations; i++)
+            writer.write(fileContent, 0, len);
+        writer.write(fileContent, 0, remainder);
+        writer.close();
+        return p;
+    }
+
+    public static Path tempFile() {
+        try {
+            Path p = Files.createTempFile("foo", "test");
+            p.toFile().deleteOnExit();
+            return p;
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    public static Void compareFiles(Path path1, Path path2) {
+        try {
+            if (Files.size(path1) != Files.size(path2))
+                throw new RuntimeException("File sizes do not match");
+            compareContents(path1, path2);
+            return null;
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    static void compareContents(Path path1, Path path2) {
+        try {
+            byte[] b1 = Files.readAllBytes(path1);
+            byte[] b2 = Files.readAllBytes(path2);
+            if (!Arrays.equals(b1, b2))
+                throw new RuntimeException ("Files do not match");
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+}
--- a/jdk/test/java/net/httpclient/security/15.policy	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/net/httpclient/security/15.policy	Wed Jul 05 21:39:33 2017 +0200
@@ -16,7 +16,7 @@
     permission java.net.URLPermission "socket://127.0.0.1:27301", "CONNECT";
 
     // Test checks for this explicitly
-    permission java.net.RuntimePermission "foobar"; 
+    permission java.net.RuntimePermission "foobar";
 };
 
 
--- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -22,8 +22,10 @@
  */
 
 /* @test
- * @bug 4640544
+ * @bug 4640544 8044773
  * @summary Unit test for setOption/getOption/options methods
+ * @run main SocketOptionTests
+ * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
  */
 
 import java.nio.*;
--- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -22,9 +22,11 @@
  */
 
 /* @test
- * @bug 4640544
+ * @bug 4640544 8044773
  * @summary Unit test for ServerSocketChannel setOption/getOption/options
  *          methods.
+ * @run main SocketOptionTests
+ * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
  */
 
 import java.nio.*;
--- a/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/nio/channels/SocketChannel/SocketOptionTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -22,9 +22,11 @@
  */
 
 /* @test
- * @bug 4640544
+ * @bug 4640544 8044773
  * @summary Unit test to check SocketChannel setOption/getOption/options
  *          methods.
+ * @run main SocketOptionTests
+ * @run main/othervm -Djdk.launcher.limitmods=java.base SocketOptionTests
  */
 
 import java.nio.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/WatchService/DeleteInterference.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016, Red Hat, Inc. and/or its affiliates.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/**
+ * @test
+ * @bug 8153925
+ * @summary Tests potential interference between a thread creating and closing
+ *     a WatchService with another thread that is deleting and re-creating the
+ *     directory at around the same time. This scenario tickled a timing bug
+ *     in the Windows implementation.
+ */
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.WatchService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import static java.nio.file.StandardWatchEventKinds.*;
+
+public class DeleteInterference {
+
+    private static final int ITERATIONS_COUNT = 1024;
+
+    /**
+     * Execute two tasks in a thread pool. One task loops on creating and
+     * closing a WatchService, the other task deletes and re-creates the
+     * directory.
+     */
+    public static void main(String[] args) throws Exception {
+        Path dir = Files.createTempDirectory("work");
+        ExecutorService pool = Executors.newCachedThreadPool();
+        try {
+            Future<?> task1 = pool.submit(() -> openAndCloseWatcher(dir));
+            Future<?> task2 = pool.submit(() -> deleteAndRecreateDirectory(dir));
+            task1.get();
+            task2.get();
+        } finally {
+            pool.shutdown();
+            deleteFileTree(dir);
+        }
+    }
+
+    private static void openAndCloseWatcher(Path dir) {
+        FileSystem fs = FileSystems.getDefault();
+        for (int i = 0; i < ITERATIONS_COUNT; i++) {
+            try (WatchService watcher = fs.newWatchService()) {
+                dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+            } catch (IOException ioe) {
+                // ignore
+            }
+        }
+    }
+
+    private static void deleteAndRecreateDirectory(Path dir) {
+        for (int i = 0; i < ITERATIONS_COUNT; i++) {
+            try {
+                deleteFileTree(dir);
+                Path subdir = Files.createDirectories(dir.resolve("subdir"));
+                Files.createFile(subdir.resolve("test"));
+            } catch (IOException ioe) {
+                // ignore
+            }
+        }
+    }
+
+    private static void deleteFileTree(Path file) {
+        try {
+            if (Files.isDirectory(file)) {
+                try (DirectoryStream<Path> stream = Files.newDirectoryStream(file)) {
+                    for (Path pa : stream) {
+                        deleteFileTree(pa);
+                    }
+                }
+            }
+            Files.delete(file);
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/rmi/TEST.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,1 @@
+modules = java.rmi
--- a/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/rmi/reliability/benchmark/bench/serial/Main.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
  * @summary The Serialization benchmark test. This java class is used to run the
  *          test under JTREG.
  * @library ../../
+ * @modules java.desktop
  * @build bench.BenchInfo bench.HtmlReporter bench.Util bench.Benchmark
  * @build bench.Reporter bench.XmlReporter bench.ConfigFormatException
  * @build bench.Harness bench.TextReporter
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Arrays/AsList.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 8155600
+ * @summary Tests for Arrays.asList()
+ * @run testng AsList
+ */
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.stream.IntStream;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.DataProvider;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
+public class AsList {
+    /*
+     * Iterator contract test
+     */
+    @Test(dataProvider = "Arrays")
+    public void testIterator(Object[] array) {
+        Iterator<Object> itr = Arrays.asList(array).iterator();
+        for (int i = 0; i < array.length; i++) {
+            assertTrue(itr.hasNext());
+            assertTrue(itr.hasNext()); // must be idempotent
+            assertSame(array[i], itr.next());
+            try {
+                itr.remove();
+                fail("Remove must throw");
+            } catch (UnsupportedOperationException ex) {
+                // expected
+            }
+        }
+        assertFalse(itr.hasNext());
+        for (int i = 0; i < 3; i++) {
+            assertFalse(itr.hasNext());
+            try {
+                itr.next();
+                fail("Next succeed when there's no data left");
+            } catch (NoSuchElementException ex) {
+                // expected
+            }
+        }
+    }
+
+    @DataProvider(name = "Arrays")
+    public static Object[][] arrays() {
+        Object[][] arrays = {
+            { new Object[] { } },
+            { new Object[] { 1 } },
+            { new Object[] { null } },
+            { new Object[] { null, 1 } },
+            { new Object[] { 1, null } },
+            { new Object[] { null, null } },
+            { new Object[] { null, 1, 2 } },
+            { new Object[] { 1, null, 2 } },
+            { new Object[] { 1, 2, null } },
+            { new Object[] { null, null, null } },
+            { new Object[] { 1, 2, 3, null, 4 } },
+            { new Object[] { "a", "a", "a", "a" } },
+            { IntStream.range(0, 100).boxed().toArray() }
+        };
+
+        return arrays;
+    }
+}
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -27,11 +27,18 @@
 
 import java.util.Arrays;
 import java.util.Random;
+import java.util.Spliterator;
 import java.util.stream.DoubleStream;
 import java.util.stream.LongStream;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
+/**
+ * @test
+ * @bug 8153293
+ */
 @Test
 public class DoublePrimitiveOpsTests {
 
@@ -42,6 +49,13 @@
         assertEquals(sum, 1.0 + 2.0 + 3.0 + 4.0 + 5.0);
     }
 
+    public void testFlags() {
+        assertTrue(LongStream.range(1, 10).asDoubleStream().boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(DoubleStream.of(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+    }
+
     public void testToArray() {
         {
             double[] array =  LongStream.range(1, 10).asDoubleStream().map(i -> i * 2).toArray();
@@ -72,6 +86,22 @@
         }
     }
 
+    public void testSortDistinct() {
+        {
+            double[] range = LongStream.range(0, 10).asDoubleStream().toArray();
+
+            assertEquals(LongStream.range(0, 10).asDoubleStream().sorted().distinct().toArray(), range);
+            assertEquals(LongStream.range(0, 10).asDoubleStream().parallel().sorted().distinct().toArray(), range);
+
+            double[] data = {5, 3, 1, 1, 5, Double.NaN, 3, 9, Double.POSITIVE_INFINITY,
+                             Double.NEGATIVE_INFINITY, 2, 9, 1, 0, 8, Double.NaN, -0.0};
+            double[] expected = {Double.NEGATIVE_INFINITY, -0.0, 0, 1, 2, 3, 5, 8, 9,
+                                 Double.POSITIVE_INFINITY, Double.NaN};
+            assertEquals(DoubleStream.of(data).sorted().distinct().toArray(), expected);
+            assertEquals(DoubleStream.of(data).parallel().sorted().distinct().toArray(), expected);
+        }
+    }
+
     public void testSortSort() {
         Random r = new Random();
 
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,13 +28,21 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Random;
+import java.util.Spliterator;
+import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.IntConsumer;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
+/**
+ * @test
+ * @bug 8153293
+ */
 @Test
 public class IntPrimitiveOpsTests {
 
@@ -85,6 +93,29 @@
         assertEquals(sum, 15);
     }
 
+    public void testFlags() {
+        assertTrue(IntStream.range(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+        assertFalse(IntStream.of(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(IntStream.of(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.DISTINCT));
+
+        assertTrue(IntStream.range(1, 10).asLongStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+        assertFalse(IntStream.of(1, 10).asLongStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(IntStream.of(1, 10).asLongStream().spliterator()
+                      .hasCharacteristics(Spliterator.DISTINCT));
+
+        assertTrue(IntStream.range(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+        assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(IntStream.of(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.DISTINCT));
+    }
+
     public void testToArray() {
         {
             int[] array =  IntStream.range(1, 10).map(i -> i * 2).toArray();
@@ -115,6 +146,35 @@
         }
     }
 
+    public void testSortDistinct() {
+        {
+            int[] range = IntStream.range(0, 10).toArray();
+
+            assertEquals(IntStream.range(0, 10).sorted().distinct().toArray(), range);
+            assertEquals(IntStream.range(0, 10).parallel().sorted().distinct().toArray(), range);
+
+            int[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8};
+            int[] expected = {0, 1, 2, 3, 5, 8, 9};
+            assertEquals(IntStream.of(data).sorted().distinct().toArray(), expected);
+            assertEquals(IntStream.of(data).parallel().sorted().distinct().toArray(), expected);
+        }
+
+        {
+            int[] input = new Random().ints(100, -10, 10).map(x -> x+Integer.MAX_VALUE).toArray();
+            TreeSet<Long> longs = new TreeSet<>();
+            for(int i : input) longs.add((long)i);
+            long[] expectedLongs = longs.stream().mapToLong(Long::longValue).toArray();
+            assertEquals(IntStream.of(input).sorted().asLongStream().sorted().distinct().toArray(),
+                         expectedLongs);
+
+            TreeSet<Double> doubles = new TreeSet<>();
+            for(int i : input) doubles.add((double)i);
+            double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray();
+            assertEquals(IntStream.of(input).sorted().distinct().asDoubleStream()
+                         .sorted().distinct().toArray(), expectedDoubles);
+        }
+    }
+
     public void testSortSort() {
         Random r = new Random();
 
--- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,13 +28,21 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Random;
+import java.util.Spliterator;
+import java.util.TreeSet;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.LongConsumer;
 import java.util.stream.Collectors;
 import java.util.stream.LongStream;
 
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
 
+/**
+ * @test
+ * @bug 8153293
+ */
 @Test
 public class LongPrimitiveOpsTests {
 
@@ -85,6 +93,22 @@
         assertEquals(sum, 15);
     }
 
+    public void testFlags() {
+        assertTrue(LongStream.range(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED | Spliterator.DISTINCT));
+        assertFalse(LongStream.of(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(LongStream.of(1, 10).boxed().spliterator()
+                      .hasCharacteristics(Spliterator.DISTINCT));
+
+        assertTrue(LongStream.range(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+        assertFalse(LongStream.range(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.DISTINCT));
+        assertFalse(LongStream.of(1, 10).asDoubleStream().spliterator()
+                      .hasCharacteristics(Spliterator.SORTED));
+    }
+
     public void testToArray() {
         {
             long[] array =  LongStream.range(1, 10).map(i -> i * 2).toArray();
@@ -115,6 +139,30 @@
         }
     }
 
+    public void testSortDistinct() {
+        {
+            long[] range = LongStream.range(0, 10).toArray();
+
+            assertEquals(LongStream.range(0, 10).sorted().distinct().toArray(), range);
+            assertEquals(LongStream.range(0, 10).parallel().sorted().distinct().toArray(), range);
+
+            long[] data = {5, 3, 1, 1, 5, 3, 9, 2, 9, 1, 0, 8};
+            long[] expected = {0, 1, 2, 3, 5, 8, 9};
+            assertEquals(LongStream.of(data).sorted().distinct().toArray(), expected);
+            assertEquals(LongStream.of(data).parallel().sorted().distinct().toArray(), expected);
+        }
+
+        {
+            long[] input = new Random().longs(100, -10, 10).map(x -> x+Long.MAX_VALUE).toArray();
+
+            TreeSet<Double> doubles = new TreeSet<>();
+            for(long i : input) doubles.add((double)i);
+            double[] expectedDoubles = doubles.stream().mapToDouble(Double::doubleValue).toArray();
+            assertEquals(LongStream.of(input).sorted().distinct().asDoubleStream()
+                         .sorted().distinct().toArray(), expectedDoubles);
+        }
+    }
+
     public void testSortSort() {
         Random r = new Random();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/ClientProperty/UIClientPropertyKeyTest/UIClientPropertyKeyTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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.EventQueue;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.UIClientPropertyKey;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+
+import static javax.swing.UIManager.getInstalledLookAndFeels;
+
+/**
+ * @test
+ * @bug 8141544
+ */
+public final class UIClientPropertyKeyTest {
+
+    private static Object key = new UIClientPropertyKey() {
+    };
+
+    public static void main(final String[] args) throws Exception {
+        EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSetUI);
+        EventQueue.invokeAndWait(UIClientPropertyKeyTest::testSerialization);
+    }
+
+    /**
+     * UIClientPropertyKey should be removed after deserialization.
+     */
+    private static void testSerialization() {
+        JComponent comp = new JButton();
+        comp.putClientProperty("key1", "value1");
+        comp.putClientProperty(key, "value2");
+
+        comp = serializeDeserialize(comp);
+
+        validate(comp);
+    }
+
+    /**
+     * UIClientPropertyKey should be removed on updateUI().
+     */
+    private static void testSetUI() {
+        JComponent comp = new JButton();
+        comp.putClientProperty("key1", "value1");
+        for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) {
+            comp.putClientProperty(key, "value2");
+            setLookAndFeel(laf);
+            SwingUtilities.updateComponentTreeUI(comp);
+            validate(comp);
+        }
+    }
+
+    private static void validate(JComponent comp) {
+        Object value = comp.getClientProperty("key1");
+        if (!value.equals("value1")) {
+            throw new RuntimeException("Incorrect value: " + value);
+        }
+        value = comp.getClientProperty(key);
+        if (value != null) {
+            throw new RuntimeException("Incorrect value: " + value);
+        }
+    }
+
+    private static void setLookAndFeel(final UIManager.LookAndFeelInfo laf) {
+        try {
+            UIManager.setLookAndFeel(laf.getClassName());
+            System.out.println("LookAndFeel: " + laf.getClassName());
+        } catch (ClassNotFoundException | InstantiationException |
+                UnsupportedLookAndFeelException | IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static JComponent serializeDeserialize(JComponent comp) {
+        try {
+            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+            ObjectOutputStream out = new ObjectOutputStream(byteOut);
+            out.writeObject(comp);
+            out.close();
+            return (JComponent) new ObjectInputStream(new ByteArrayInputStream(
+                    byteOut.toByteArray())).readObject();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JButton/PressedButtonRightClickTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import java.awt.AWTException;
+import java.awt.BorderLayout;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.SwingUtilities;
+
+/*
+ * @test
+ * @bug  8049069
+ * @summary Tests whether right mouse click releases a pressed JButton
+ */
+
+public class PressedButtonRightClickTest {
+
+    private static Robot testRobot;
+    private static JFrame myFrame;
+    private static JButton myButton;
+
+    public static void main(String[] args) throws Throwable {
+
+        SwingUtilities.invokeAndWait(new Runnable() {
+
+            @Override
+            public void run() {
+                constructTestUI();
+            }
+        });
+
+        try {
+            testRobot = new Robot();
+        } catch (AWTException ex) {
+            throw new RuntimeException("Exception in Robot creation");
+        }
+
+        testRobot.waitForIdle();
+
+        // Method performing auto test operation
+        test();
+
+        disposeTestUI();
+    }
+
+    private static void test() {
+        Point loc = myFrame.getLocationOnScreen();
+
+        testRobot.mouseMove((loc.x + 100), (loc.y + 100));
+
+        // Press the left mouse button
+        testRobot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+        myButton.setText("Left button pressed");
+        testRobot.delay(1000);
+
+        // Press the right mouse button
+        testRobot.mousePress(InputEvent.BUTTON3_DOWN_MASK);
+        myButton.setText("Left button pressed + Right button pressed");
+        testRobot.delay(1000);
+
+        // Release the right mouse button
+        testRobot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK);
+        myButton.setText("Right button released");
+        testRobot.delay(1000);
+
+        // Test whether the button is still pressed
+        if (myButton.getModel().isPressed() == false) {
+            disposeTestUI();
+            throw new RuntimeException("Test Failed!");
+        }
+    }
+
+    private static void disposeTestUI() {
+        myFrame.setVisible(false);
+        myFrame.dispose();
+    }
+
+    public static void constructTestUI() {
+        myFrame = new JFrame();
+        myFrame.setLayout(new BorderLayout());
+        myButton = new JButton("Whatever");
+        myFrame.add(myButton, BorderLayout.CENTER);
+        myFrame.setSize(400, 300);
+        myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        myFrame.setVisible(true);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/JEditorPane/5076514/bug5076514.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* @test
+   @bug 5076514 8025430
+   @summary Tests if SecurityManager.checkPermission()
+                  used for clipboard access with permission 'accessClipboard'
+   @run main bug5076514
+*/
+
+import java.security.Permission;
+import javax.swing.JEditorPane;
+
+public class bug5076514 {
+    private final static String ACCESS_CLIPBOARD = "accessClipboard";
+    private static boolean isCheckPermissionCalled = false;
+
+    public static void main(String[] args) {
+        System.setSecurityManager(new MySecurityManager());
+        JEditorPane editor = new JEditorPane();
+        editor.copy();
+        if (!isCheckPermissionCalled) {
+            throw new RuntimeException("JEditorPane's clipboard operations "
+                    + "didn't call SecurityManager.checkPermission() with "
+                    + "permission 'accessClipboard' when there is a security"
+                    + " manager installed");
+        }
+    }
+
+    private static class MySecurityManager extends SecurityManager {
+        @Override
+        public void checkPermission(Permission perm) {
+            if (ACCESS_CLIPBOARD.equals(perm.getName())) {
+                isCheckPermissionCalled = true;
+            }
+        }
+    }
+}
--- a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,7 +30,6 @@
  * @run main ShellFolderQueriesTest
  */
 
-import sun.awt.OSInfo;
 
 import javax.swing.filechooser.FileSystemView;
 import java.io.File;
@@ -50,7 +49,8 @@
     static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save";
 
     public static void main(String[] args) throws Exception {
-        if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) {
+        if(System.getProperty("os.name").toLowerCase().contains("windows")) {
+            System.out.println("Windows detected: will run shortcut test");
             testGet();
             testLink();
         } else {
--- a/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/javax/swing/LookAndFeel/6439354/TitledBorderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 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
@@ -23,7 +23,7 @@
 
  /*
  * @test
- * @bug 6439354
+ * @bug 8153056 8152647 6439354
  * @summary Verify TitleBorder appearance Color/Visibility for WLAF
  * @requires (os.family == "windows")
  * @run main/manual TitledBorderTest
@@ -33,6 +33,7 @@
 import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.concurrent.CountDownLatch;
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 import javax.swing.JFrame;
@@ -41,7 +42,26 @@
 import javax.swing.SwingUtilities;
 import javax.swing.UIManager;
 
-public class TitledBorderTest implements ActionListener {
+public class TitledBorderTest {
+
+    public static void main(String args[]) throws Exception {
+        final CountDownLatch latch = new CountDownLatch(1);
+
+        TitledBorder test = new TitledBorder(latch);
+        Thread T1 = new Thread(test);
+        T1.start();
+
+        // wait for latch to complete
+        latch.await();
+
+        if (test.testResult == false) {
+            throw new RuntimeException("User Clicked Fail!"
+                    + " TitledBorder Not Valid");
+        }
+    }
+}
+
+class TitledBorder implements Runnable {
 
     private static GridBagLayout layout;
     private static JPanel mainControlPanel;
@@ -50,88 +70,98 @@
     private static JButton passButton;
     private static JButton failButton;
     private static JFrame mainFrame;
+    private final CountDownLatch latch;
+    public boolean testResult = false;
 
-    public static void main(String[] args) throws Exception {
-        TitledBorderTest titledBorderTest = new TitledBorderTest();
+    public TitledBorder(CountDownLatch latch) throws Exception {
+        this.latch = latch;
     }
 
-    public TitledBorderTest() throws Exception {
-        createUI();
+    @Override
+    public void run() {
+
+        try {
+            createUI();
+        } catch (Exception ex) {
+            if (mainFrame != null) {
+                mainFrame.dispose();
+            }
+            latch.countDown();
+            throw new RuntimeException("createUI Failed: " + ex.getMessage());
+        }
+
     }
 
     public final void createUI() throws Exception {
 
         UIManager.setLookAndFeel("com.sun.java.swing.plaf."
                 + "windows.WindowsLookAndFeel");
-
-        SwingUtilities.invokeAndWait(() -> {
-
-            mainFrame = new JFrame("Window LAF TitledBorder Test");
-            layout = new GridBagLayout();
-            mainControlPanel = new JPanel(layout);
-            resultButtonPanel = new JPanel(layout);
+        SwingUtilities.invokeAndWait(new Runnable() {
+            @Override
+            public void run() {
+                mainFrame = new JFrame("Window LAF TitledBorder Test");
+                layout = new GridBagLayout();
+                mainControlPanel = new JPanel(layout);
+                resultButtonPanel = new JPanel(layout);
 
-            GridBagConstraints gbc = new GridBagConstraints();
-            String instructions
-                    = "INSTRUCTIONS:"
-                    + "\n set Windows Theme to HighContrast#1."
-                    + "\n (ControlPanel->Personalization->High Contrast#1)"
-                    + "\n If Titled Border(Border Line) is visible then test"
-                    + " passes else failed.";
+                GridBagConstraints gbc = new GridBagConstraints();
+                String instructions
+                        = "INSTRUCTIONS:"
+                        + "\n set Windows Theme to HighContrast#1."
+                        + "\n (ControlPanel->Personalization->High Contrast#1)"
+                        + "\n If Titled Border(Border Line) is visible then test"
+                        + " passes else failed.";
 
-            instructionTextArea = new JTextArea();
-            instructionTextArea.setText(instructions);
-            instructionTextArea.setEnabled(false);
-            instructionTextArea.setDisabledTextColor(Color.black);
-            instructionTextArea.setBackground(Color.white);
+                instructionTextArea = new JTextArea();
+                instructionTextArea.setText(instructions);
+                instructionTextArea.setEnabled(false);
+                instructionTextArea.setDisabledTextColor(Color.black);
+                instructionTextArea.setBackground(Color.white);
 
-            gbc.gridx = 0;
-            gbc.gridy = 0;
-            gbc.fill = GridBagConstraints.HORIZONTAL;
-            mainControlPanel.add(instructionTextArea, gbc);
+                gbc.gridx = 0;
+                gbc.gridy = 0;
+                gbc.fill = GridBagConstraints.HORIZONTAL;
+                mainControlPanel.add(instructionTextArea, gbc);
 
-            mainControlPanel.setBorder(BorderFactory.
-                    createTitledBorder("Titled Border"));
+                mainControlPanel.setBorder(BorderFactory.
+                        createTitledBorder("Titled Border"));
 
-            passButton = new JButton("Pass");
-            passButton.setActionCommand("Pass");
-            passButton.addActionListener(TitledBorderTest.this);
-            failButton = new JButton("Fail");
-            failButton.setActionCommand("Fail");
-            failButton.addActionListener(TitledBorderTest.this);
-            gbc.gridx = 0;
-            gbc.gridy = 0;
-            resultButtonPanel.add(passButton, gbc);
-            gbc.gridx = 1;
-            gbc.gridy = 0;
-            resultButtonPanel.add(failButton, gbc);
+                passButton = new JButton("Pass");
+                passButton.setActionCommand("Pass");
+                passButton.addActionListener((ActionEvent e) -> {
+                    System.out.println("Pass Button pressed!");
+                    testResult = true;
+                    mainFrame.dispose();
+                    latch.countDown();
 
-            gbc.gridx = 0;
-            gbc.gridy = 1;
-            mainControlPanel.add(resultButtonPanel, gbc);
+                });
+                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;
+                        mainFrame.dispose();
+                        latch.countDown();
+                    }
+                });
+                gbc.gridx = 0;
+                gbc.gridy = 0;
+                resultButtonPanel.add(passButton, gbc);
+                gbc.gridx = 1;
+                gbc.gridy = 0;
+                resultButtonPanel.add(failButton, gbc);
 
-            mainFrame.add(mainControlPanel);
-            mainFrame.pack();
-            mainFrame.setVisible(true);
+                gbc.gridx = 0;
+                gbc.gridy = 1;
+                mainControlPanel.add(resultButtonPanel, gbc);
+
+                mainFrame.add(mainControlPanel);
+                mainFrame.pack();
+                mainFrame.setVisible(true);
+            }
         });
+
     }
-
-    @Override
-    public void actionPerformed(ActionEvent evt) {
-        if (evt.getSource() instanceof JButton) {
-            JButton btn = (JButton) evt.getSource();
-            cleanUp();
-            switch (btn.getActionCommand()) {
-                case "Pass":
-                    break;
-                case "Fail":
-                    throw new AssertionError("User Clicked Fail!");
-            }
-        }
-    }
-
-    private static void cleanUp() {
-        mainFrame.dispose();
-    }
-
 }
--- a/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/javax/swing/undo/UndoManager/AbstractDocumentUndoConcurrentTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -104,8 +104,12 @@
                     e.printStackTrace();
                 }
                 for (int i = 0; i < 1000; i++) {
-                    undoManager.undoOrRedo();
-                    undoManager.undo();
+                    if(undoManager.canUndoOrRedo()) {
+                        undoManager.undoOrRedo();
+                    }
+                    if(undoManager.canUndo()) {
+                        undoManager.undo();
+                    }
                 }
                 System.out.println("t3 done");
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/net/SocketFlow/SocketFlowBasic.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 8765432
+ * @summary Basic test for SocketFlow API
+ * @run testng SocketFlowBasic
+ */
+
+import jdk.net.SocketFlow;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import static jdk.net.SocketFlow.*;
+import static org.testng.Assert.*;
+
+public class SocketFlowBasic {
+
+    @DataProvider
+    public Object[][] validPriorities() {
+        return new Object[][] { {HIGH_PRIORITY}, {NORMAL_PRIORITY} };
+    }
+
+    @Test(dataProvider = "validPriorities")
+    public void priority(long validPriority) {
+        SocketFlow flow = SocketFlow.create();
+        flow.bandwidth(validPriority);
+        long bandwidth = flow.bandwidth();
+        assertTrue(bandwidth == validPriority, "Expected " + validPriority + ", got" + bandwidth);
+    }
+
+    @DataProvider
+    public Object[][] invalidPriorities() {
+        return new Object[][] { {HIGH_PRIORITY+10}, {NORMAL_PRIORITY-10000} };
+    }
+
+    @Test(dataProvider = "invalidPriorities", expectedExceptions = IllegalArgumentException.class)
+    public void priority(int invalidPriority) {
+        SocketFlow flow = SocketFlow.create();
+        flow.priority(invalidPriority);
+    }
+
+    @DataProvider
+    public Object[][] positiveBandwidth() {
+        return new Object[][] { {0}, {100}, {Integer.MAX_VALUE}, {Long.MAX_VALUE} };
+    }
+
+    @Test(dataProvider = "positiveBandwidth")
+    public void bandwidth(long posBandwidth) {
+        SocketFlow flow = SocketFlow.create();
+        flow.bandwidth(posBandwidth);
+        long bandwidth = flow.bandwidth();
+        assertTrue(bandwidth == posBandwidth, "Expected " + posBandwidth + ", got" + bandwidth);
+    }
+
+
+    @DataProvider
+    public Object[][] negativeBandwidth() {
+        return new Object[][] { {-1}, {-100}, {Integer.MIN_VALUE}, {Long.MIN_VALUE} };
+    }
+
+    @Test(dataProvider = "negativeBandwidth", expectedExceptions = IllegalArgumentException.class)
+    public void invalidBandwidth(long negBandwidth) {
+        SocketFlow flow = SocketFlow.create();
+        flow.bandwidth(negBandwidth);
+    }
+
+    @Test
+    public void status() {
+        SocketFlow flow = SocketFlow.create();
+        assertTrue(flow.status() == Status.NO_STATUS);
+    }
+}
--- a/jdk/test/jdk/net/Sockets/Test.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/jdk/net/Sockets/Test.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,8 +23,9 @@
 
 /*
  * @test
- * @bug 8032808
- * @run main/othervm -Xcheck:jni Test
+ * @bug 8032808 8044773
+ * @modules jdk.net
+ * @run main/othervm -Xcheck:jni Test success
  * @run main/othervm/policy=policy.fail -Xcheck:jni Test fail
  * @run main/othervm/policy=policy.success -Xcheck:jni Test success
  */
@@ -35,15 +36,13 @@
 import java.util.concurrent.*;
 import java.util.Set;
 import jdk.net.*;
+import static java.lang.System.out;
 
 public class Test {
 
-    static boolean security;
-    static boolean success;
+    interface Runner { void run() throws Exception; }
 
-    interface Runner {
-        public void run() throws Exception;
-    }
+    static boolean expectSuccess;
 
     public static void main(String[] args) throws Exception {
 
@@ -52,95 +51,107 @@
 
         Sockets.supportedOptions(Socket.class);
 
-        security = System.getSecurityManager() != null;
-        success = security && args[0].equals("success");
+        expectSuccess = args[0].equals("success");
 
         // Main thing is to check for JNI problems
         // Doesn't matter if current system does not support the option
         // and currently setting the option with the loopback interface
         // doesn't work either
 
-        System.out.println ("Security Manager enabled: " + security);
-        if (security) {
-            System.out.println ("Success expected: " + success);
-        }
+        boolean sm = System.getSecurityManager() != null;
+        out.println("Security Manager enabled: " + sm);
+        out.println("Success expected: " + expectSuccess);
 
-        final SocketFlow flowIn = SocketFlow.create()
-            .bandwidth(1000)
-            .priority(SocketFlow.HIGH_PRIORITY);
+        SocketFlow flowIn = SocketFlow.create()
+                                      .bandwidth(1000)
+                                      .priority(SocketFlow.HIGH_PRIORITY);
 
-        ServerSocket ss = new ServerSocket(0);
-        int tcp_port = ss.getLocalPort();
-        final InetAddress loop = InetAddress.getByName("127.0.0.1");
-        final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
+        try (ServerSocket ss = new ServerSocket(0);
+             DatagramSocket dg = new DatagramSocket(0)) {
 
-        DatagramSocket dg = new DatagramSocket(0);
-        final int udp_port = dg.getLocalPort();
+            int tcp_port = ss.getLocalPort();
+            final InetAddress loop = InetAddress.getByName("127.0.0.1");
+            final InetSocketAddress loopad = new InetSocketAddress(loop, tcp_port);
+
+            final int udp_port = dg.getLocalPort();
 
-        // If option not available, end test
-        Set<SocketOption<?>> options = dg.supportedOptions();
-        if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
-            System.out.println("SO_FLOW_SLA not supported");
-            return;
-        }
+            // If option not available, end test
+            Set<SocketOption<?>> options = dg.supportedOptions();
+            if (!options.contains(ExtendedSocketOptions.SO_FLOW_SLA)) {
+                System.out.println("SO_FLOW_SLA not supported");
+                return;
+            }
 
-        final Socket s = new Socket("127.0.0.1", tcp_port);
-        final SocketChannel sc = SocketChannel.open();
-        sc.connect (new InetSocketAddress("127.0.0.1", tcp_port));
+            final Socket s = new Socket("127.0.0.1", tcp_port);
+            final SocketChannel sc = SocketChannel.open();
+            sc.connect(new InetSocketAddress("127.0.0.1", tcp_port));
 
-        doTest(()->{
-            Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
-        doTest(()->{
-            Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
-        });
-        doTest(()->{
-            sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
-        doTest(()->{
-            sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA);
-        });
-        doTest(()->{
-            DatagramSocket dg1 = new DatagramSocket(0);
-            dg1.connect(loop, udp_port);
-            Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
-        doTest(()->{
-            DatagramChannel dg2 = DatagramChannel.open();
-            dg2.bind(new InetSocketAddress(loop, 0));
-            dg2.connect(new InetSocketAddress(loop, udp_port));
-            dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
-        doTest(()->{
-            MulticastSocket mc1 = new MulticastSocket(0);
-            mc1.connect(loop, udp_port);
-            Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
-        doTest(()->{
-            AsynchronousSocketChannel asc = AsynchronousSocketChannel.open();
-            Future<Void> f = asc.connect(loopad);
-            f.get();
-            asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
-        });
+            doTest("Sockets.setOption Socket", () -> {
+                out.println(flowIn);
+                Sockets.setOption(s, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                out.println(flowIn);
+            });
+            doTest("Sockets.getOption Socket",() -> {
+                Sockets.getOption(s, ExtendedSocketOptions.SO_FLOW_SLA);
+                out.println(flowIn);
+            });
+            doTest("Sockets.setOption SocketChannel",() ->
+                sc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn)
+            );
+            doTest("Sockets.getOption SocketChannel",() ->
+                sc.getOption(ExtendedSocketOptions.SO_FLOW_SLA)
+            );
+            doTest("Sockets.setOption DatagramSocket",() -> {
+                try (DatagramSocket dg1 = new DatagramSocket(0)) {
+                    dg1.connect(loop, udp_port);
+                    Sockets.setOption(dg1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                }
+            });
+            doTest("Sockets.setOption DatagramSocket 2", () -> {
+                try (DatagramChannel dg2 = DatagramChannel.open()) {
+                    dg2.bind(new InetSocketAddress(loop, 0));
+                    dg2.connect(new InetSocketAddress(loop, udp_port));
+                    dg2.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                }
+            });
+            doTest("Sockets.setOption MulticastSocket", () -> {
+                try (MulticastSocket mc1 = new MulticastSocket(0)) {
+                    mc1.connect(loop, udp_port);
+                    Sockets.setOption(mc1, ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                }
+            });
+            doTest("Sockets.setOption AsynchronousSocketChannel", () -> {
+                try (AsynchronousSocketChannel asc = AsynchronousSocketChannel.open()) {
+                    Future<Void> f = asc.connect(loopad);
+                    f.get();
+                    asc.setOption(ExtendedSocketOptions.SO_FLOW_SLA, flowIn);
+                }
+            });
+        }
     }
 
-    static void doTest(Runner func) throws Exception {
+    static void doTest(String message, Runner func) throws Exception {
+        out.println(message);
         try {
             func.run();
-            if (security && !success) {
-                throw new RuntimeException("Test failed");
+            if (expectSuccess) {
+                out.println("Completed as expected");
+            } else {
+                throw new RuntimeException("Operation succeeded, but expected SecurityException");
             }
         } catch (SecurityException e) {
-            if (success) {
-                throw new RuntimeException("Test failed");
+            if (expectSuccess) {
+                throw new RuntimeException("Unexpected SecurityException", e);
+            } else {
+                out.println("Caught expected: " + e);
             }
         } catch (UnsupportedOperationException e) {
-            System.out.println (e);
+            System.out.println(e);
         } catch (IOException e) {
             // Probably a permission error, but we're not
             // going to check unless a specific permission exception
             // is defined.
-            System.out.println (e);
+            System.out.println(e);
         }
     }
 }
--- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,8 @@
  * questions.
  */
 
+import com.sun.swingset3.demos.button.ButtonDemo;
+import org.jtregext.GuiTestListener;
 import java.awt.Point;
 import java.awt.Robot;
 import java.awt.event.InputEvent;
@@ -32,6 +34,7 @@
 import static org.jemmy2ext.JemmyExt.*;
 import org.testng.annotations.Test;
 import static com.sun.swingset3.demos.button.ButtonDemo.*;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -41,31 +44,30 @@
  *          image is different from initial button image.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.button.ButtonDemo
  * @run testng ButtonDemoScreenshotTest
  */
+@Listeners(GuiTestListener.class)
 public class ButtonDemoScreenshotTest {
 
     private static final int BUTTON_COUNT = 6; // TODO: Decide about "open browser" buttons (value was 8 originally)
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            Robot rob = new Robot();
+        Robot rob = new Robot();
 
-            new ClassReference(com.sun.swingset3.demos.button.ButtonDemo.class.getCanonicalName()).startApplication();
+        new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
-            waitImageIsStill(rob, mainFrame);
+        JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
+        waitImageIsStill(rob, mainFrame);
 
-            // Check all the buttons
-            for (int i = 0; i < BUTTON_COUNT; i++) {
-                checkButton(mainFrame, i, rob);
-            }
-        });
+        // Check all the buttons
+        for (int i = 0; i < BUTTON_COUNT; i++) {
+            checkButton(mainFrame, i, rob);
+        }
     }
 
     public void checkButton(JFrameOperator jfo, int i, Robot rob) {
--- a/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ButtonDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.JHyperlink;
 import com.sun.swingset3.demos.button.ButtonDemo;
 import java.util.concurrent.ArrayBlockingQueue;
@@ -38,7 +39,7 @@
 import static com.sun.swingset3.demos.button.ButtonDemo.*;
 import org.jemmy2ext.JemmyExt;
 import org.jemmy2ext.JemmyExt.MultiThreadedTryCatch;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -48,12 +49,13 @@
  *          on buttons before and after click.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.button.ButtonDemo
  * @run testng ButtonDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ButtonDemoTest {
 
     private static final String[] BUTTON_TEXT_AFTER = {
@@ -92,34 +94,30 @@
     @Test
     public void test() throws Exception {
 
-        captureDebugInfoOnFail(() -> {
-
-            new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication();
+        new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
-            mainFrame.setComparator(EXACT_STRING_COMPARATOR);
-
-            // Check all the buttons
-            for (int i = 0; i < BUTTON_TOOLTIP.length; i++) {
-                String tooltip = BUTTON_TOOLTIP[i];
-
-                JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip));
+        JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
+        mainFrame.setComparator(EXACT_STRING_COMPARATOR);
 
-                assertEquals(BUTTON_TEXT_BEFORE[i], button.getText());
+        // Check all the buttons
+        for (int i = 0; i < BUTTON_TOOLTIP.length; i++) {
+            String tooltip = BUTTON_TOOLTIP[i];
+
+            JButtonOperator button = new JButtonOperator(mainFrame, new ByToolTipChooser(tooltip));
 
-                // Two buttons are hyperlinks, we don't want to click them
-                if (!button.getSource().getClass().equals(JHyperlink.class)) {
-                    checkButton(button);
-                }
+            assertEquals(BUTTON_TEXT_BEFORE[i], button.getText());
 
-                if (BUTTON_TEXT_AFTER.length > i) {
-                    assertEquals(BUTTON_TEXT_AFTER[i], button.getText());
-                } else {
-                    assertEquals(BUTTON_TEXT_BEFORE[i], button.getText());
-                }
+            // Two buttons are hyperlinks, we don't want to click them
+            if (!button.getSource().getClass().equals(JHyperlink.class)) {
+                checkButton(button);
             }
 
-        });
+            if (BUTTON_TEXT_AFTER.length > i) {
+                assertEquals(BUTTON_TEXT_AFTER[i], button.getText());
+            } else {
+                assertEquals(BUTTON_TEXT_BEFORE[i], button.getText());
+            }
+        }
     }
 
     private void checkButton(JButtonOperator button) throws Exception {
--- a/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ComboBoxDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.combobox.ComboBoxDemo;
 import static org.testng.AssertJUnit.*;
 import org.testng.annotations.Test;
@@ -28,7 +29,7 @@
 import org.netbeans.jemmy.operators.JComboBoxOperator;
 import org.netbeans.jemmy.operators.JFrameOperator;
 import static com.sun.swingset3.demos.combobox.ComboBoxDemo.*;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -37,12 +38,13 @@
  *          each value of each ComboBox.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.combobox.ComboBoxDemo
  * @run testng ComboBoxDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ComboBoxDemoTest {
 
     private static enum ComboBoxInfo {
@@ -61,14 +63,13 @@
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication();
+
+        new ClassReference(ComboBoxDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
-            for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) {
-                comboBoxChecker(frame, comboBoxInfo);
-            }
-        });
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        for (ComboBoxInfo comboBoxInfo : ComboBoxInfo.values()) {
+            comboBoxChecker(frame, comboBoxInfo);
+        }
     }
 
     private void comboBoxChecker(JFrameOperator jfo, ComboBoxInfo comboBoxInfo) {
--- a/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ListDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.list.ListDemo;
 import static com.sun.swingset3.demos.list.ListDemo.DEMO_TITLE;
 import static org.testng.AssertJUnit.*;
@@ -30,7 +31,7 @@
 import org.netbeans.jemmy.operators.JCheckBoxOperator;
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JListOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -40,64 +41,64 @@
  *          list.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.list.ListDemo
  * @run testng ListDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ListDemoTest {
 
     private static final int CHECKBOX_COUNT = 50;
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(ListDemo.class.getCanonicalName()).startApplication();
+
+        new ClassReference(ListDemo.class.getCanonicalName()).startApplication();
+
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        JListOperator listOp = new JListOperator(frame);
+
+        // Check *NO* Prefix and Suffixes Marked
+        for (int i = 0; i < CHECKBOX_COUNT; i++) {
+            JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+            checkBox.changeSelection(false);
+        }
+        System.out.println("######## Number of Items = " + listOp.getModel().getSize());
+        assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize());
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
-            JListOperator listOp = new JListOperator(frame);
+        // Check *ALL* Prefix and Suffixes Marked
+        for (int i = 0; i < CHECKBOX_COUNT; i++) {
+            JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+            checkBox.changeSelection(true);
+        }
+        System.out.println("######## Number of Items = " + listOp.getModel().getSize());
+        assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize());
 
-            // Check *NO* Prefix and Suffixes Marked
-            for (int i = 0; i < CHECKBOX_COUNT; i++) {
-                JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+        // Check *ALL* Prefix and *NO* Suffixes Marked
+        for (int i = 0; i < CHECKBOX_COUNT; i++) {
+            JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+            if (i < CHECKBOX_COUNT / 2) {
+                checkBox.changeSelection(true);
+            } else {
                 checkBox.changeSelection(false);
             }
-            System.out.println("######## Number of Items = " + listOp.getModel().getSize());
-            assertEquals("Select None number of items is correct", 0, listOp.getModel().getSize());
+        }
+        System.out.println("######## Number of Items = " + listOp.getModel().getSize());
+        assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize());
 
-            // Check *ALL* Prefix and Suffixes Marked
-            for (int i = 0; i < CHECKBOX_COUNT; i++) {
-                JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+        // Check *NO* Prefix and *ALL* Suffixes Marked
+        for (int i = 0; i < CHECKBOX_COUNT; i++) {
+            JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
+            if (i < CHECKBOX_COUNT / 2) {
+                checkBox.changeSelection(false);
+            } else {
                 checkBox.changeSelection(true);
             }
-            System.out.println("######## Number of Items = " + listOp.getModel().getSize());
-            assertEquals("Select All number of items is correct", CHECKBOX_COUNT / 2 * CHECKBOX_COUNT / 2, listOp.getModel().getSize());
-
-            // Check *ALL* Prefix and *NO* Suffixes Marked
-            for (int i = 0; i < CHECKBOX_COUNT; i++) {
-                JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
-                if (i < CHECKBOX_COUNT / 2) {
-                    checkBox.changeSelection(true);
-                } else {
-                    checkBox.changeSelection(false);
-                }
-            }
-            System.out.println("######## Number of Items = " + listOp.getModel().getSize());
-            assertEquals("Select All Prefixes and NO Suffixes number of items is correct", 0, listOp.getModel().getSize());
-
-            // Check *NO* Prefix and *ALL* Suffixes Marked
-            for (int i = 0; i < CHECKBOX_COUNT; i++) {
-                JCheckBoxOperator checkBox = getJCheckBoxOperator(frame, i);
-                if (i < CHECKBOX_COUNT / 2) {
-                    checkBox.changeSelection(false);
-                } else {
-                    checkBox.changeSelection(true);
-                }
-            }
-            System.out.println("######## Number of Items = " + listOp.getModel().getSize());
-            assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize());
-        });
+        }
+        System.out.println("######## Number of Items = " + listOp.getModel().getSize());
+        assertEquals("Select NO Prefixes and All Suffixes number of items is correct", 0, listOp.getModel().getSize());
     }
 
     private JCheckBoxOperator getJCheckBoxOperator(JFrameOperator frame, int index) {
--- a/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/OptionPaneDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,10 +21,10 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.optionpane.OptionPaneDemo;
 import static com.sun.swingset3.demos.optionpane.OptionPaneDemo.*;
 import javax.swing.UIManager;
-import static org.jemmy2ext.JemmyExt.*;
 import static org.testng.AssertJUnit.*;
 import org.testng.annotations.Test;
 import org.netbeans.jemmy.ClassReference;
@@ -34,6 +34,7 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JLabelOperator;
 import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.testng.annotations.Listeners;
 
 
 /*
@@ -43,12 +44,13 @@
  *          and choosing different options in them.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.optionpane.OptionPaneDemo
  * @run testng OptionPaneDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class OptionPaneDemoTest {
 
     public static final String SOME_TEXT_TO_TYPE = "I am some text";
@@ -59,21 +61,20 @@
     public static final String TEXT_TO_TYPE = "Hooray! I'm a textField";
     public static final String NO = "No";
     public static final String YES = "Yes";
-    public static final String SELECT_AN__OPTION = UIManager.getString("OptionPane.titleText");
+    public static final String SELECT_AN_OPTION = UIManager.getString("OptionPane.titleText");
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        new ClassReference(OptionPaneDemo.class.getCanonicalName()).startApplication();
+
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
 
-            showInputDialog(frame);
-            showWarningDialog(frame);
-            showMessageDialog(frame);
-            showComponentDialog(frame);
-            showConfirmationDialog(frame);
-        });
+        showInputDialog(frame);
+        showWarningDialog(frame);
+        showMessageDialog(frame);
+        showComponentDialog(frame);
+        showConfirmationDialog(frame);
     }
 
     public void showInputDialog(JFrameOperator jfo) throws Exception {
@@ -286,7 +287,7 @@
         {
             new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock();
 
-            JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION);
+            JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION);
             new JButtonOperator(jdo, YES).pushNoBlock();
 
             JDialogOperator jdo1 = new JDialogOperator(MESSAGE);
@@ -306,7 +307,7 @@
         {
             new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock();
 
-            JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION);
+            JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION);
             new JButtonOperator(jdo, NO).pushNoBlock();
 
             JDialogOperator jdo1 = new JDialogOperator(MESSAGE);
@@ -326,7 +327,7 @@
         {
             new JButtonOperator(jfo, CONFIRM_BUTTON).pushNoBlock();
 
-            JDialogOperator jdo = new JDialogOperator(SELECT_AN__OPTION);
+            JDialogOperator jdo = new JDialogOperator(SELECT_AN_OPTION);
 
             assertTrue("Show Confirmation Dialog Cancel Option", jdo.isShowing());
 
--- a/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ProgressBarDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.progressbar.ProgressBarDemo;
 import static com.sun.swingset3.demos.progressbar.ProgressBarDemo.*;
 import java.awt.Component;
@@ -31,7 +32,7 @@
 import org.netbeans.jemmy.operators.JButtonOperator;
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JProgressBarOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -40,31 +41,31 @@
  *          buttons and checking the progress bar and the buttons state.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.progressbar.ProgressBarDemo
  * @run testng ProgressBarDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ProgressBarDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        new ClassReference(ProgressBarDemo.class.getCanonicalName()).startApplication();
+
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
 
-            JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON);
-            JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON);
-            JProgressBarOperator jpbo = new JProgressBarOperator(frame);
+        JButtonOperator startButton = new JButtonOperator(frame, START_BUTTON);
+        JButtonOperator stopButton = new JButtonOperator(frame, STOP_BUTTON);
+        JProgressBarOperator jpbo = new JProgressBarOperator(frame);
 
-            // Check that progress completes and corect enable/disable of start/stop buttons
-            checkCompleteProgress(frame, startButton, stopButton, jpbo);
+        // Check that progress completes and corect enable/disable of start/stop buttons
+        checkCompleteProgress(frame, startButton, stopButton, jpbo);
 
-            // Check progess bar progression and start/stop button disabled/enabled states
-            checkStartStop(frame, startButton, stopButton, jpbo);
-        });
+        // Check progess bar progression and start/stop button disabled/enabled states
+        checkStartStop(frame, startButton, stopButton, jpbo);
     }
 
     // Check that progress completes and corect enable/disable of start/stop buttons
--- a/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ScrollPaneDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.scrollpane.ScrollPaneDemo;
 import static com.sun.swingset3.demos.scrollpane.ScrollPaneDemo.DEMO_TITLE;
 import static org.testng.AssertJUnit.*;
@@ -28,7 +29,7 @@
 import org.netbeans.jemmy.ClassReference;
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JScrollPaneOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -37,73 +38,73 @@
  *          to left and to right and checking scroll bar values.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.scrollpane.ScrollPaneDemo
  * @run testng ScrollPaneDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ScrollPaneDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(ScrollPaneDemo.class.getName()).startApplication();
+
+        new ClassReference(ScrollPaneDemo.class.getName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
-            JScrollPaneOperator jspo = new JScrollPaneOperator(frame);
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        JScrollPaneOperator jspo = new JScrollPaneOperator(frame);
 
-            // Set initial scrollbar positions
-            int initialVerticalValue = jspo.getVerticalScrollBar().getValue();
-            int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue();
+        // Set initial scrollbar positions
+        int initialVerticalValue = jspo.getVerticalScrollBar().getValue();
+        int initialHorizontalValue = jspo.getHorizontalScrollBar().getValue();
 
-            System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue());
-            System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue());
+        System.out.println("Initial Vertical Value = " + jspo.getVerticalScrollBar().getValue());
+        System.out.println("Initial HoriZontal Value = " + jspo.getHorizontalScrollBar().getValue());
 
-            // Check scroll to Bottom
-            {
-                jspo.scrollToBottom();
-                int currentValue = jspo.getVerticalScrollBar().getValue();
-                System.out.println("Final Value = " + currentValue);
-                assertTrue("Scroll to Bottom of Pane "
-                        + "(initialVerticalValue, actual value: " + initialVerticalValue + " "
-                        + "< currentValue, actual value = " + currentValue + ")",
-                        initialVerticalValue < currentValue);
-            }
+        // Check scroll to Bottom
+        {
+            jspo.scrollToBottom();
+            int currentValue = jspo.getVerticalScrollBar().getValue();
+            System.out.println("Final Value = " + currentValue);
+            assertTrue("Scroll to Bottom of Pane "
+                    + "(initialVerticalValue, actual value: " + initialVerticalValue + " "
+                    + "< currentValue, actual value = " + currentValue + ")",
+                    initialVerticalValue < currentValue);
+        }
 
-            // Check scroll to Top
-            {
-                jspo.scrollToTop();
-                int currentValue = jspo.getVerticalScrollBar().getValue();
-                System.out.println("Top Scroll Final Value = " + currentValue);
-                assertTrue("Scroll to Top of Pane "
-                        + "(initialVerticalValue, actual value: " + initialVerticalValue + " "
-                        + "> currentValue, actual value = " + currentValue + ")",
-                        initialVerticalValue > currentValue);
-            }
+        // Check scroll to Top
+        {
+            jspo.scrollToTop();
+            int currentValue = jspo.getVerticalScrollBar().getValue();
+            System.out.println("Top Scroll Final Value = " + currentValue);
+            assertTrue("Scroll to Top of Pane "
+                    + "(initialVerticalValue, actual value: " + initialVerticalValue + " "
+                    + "> currentValue, actual value = " + currentValue + ")",
+                    initialVerticalValue > currentValue);
+        }
 
-            // Check scroll to Left
-            {
-                jspo.scrollToLeft();
-                int currentValue = jspo.getHorizontalScrollBar().getValue();
-                System.out.println("Scroll to Left Final Value = " + currentValue);
-                assertTrue("Scroll to Left of Pane "
-                        + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " "
-                        + "> currentValue, actual value = " + currentValue + ")",
-                        initialHorizontalValue > currentValue);
-            }
+        // Check scroll to Left
+        {
+            jspo.scrollToLeft();
+            int currentValue = jspo.getHorizontalScrollBar().getValue();
+            System.out.println("Scroll to Left Final Value = " + currentValue);
+            assertTrue("Scroll to Left of Pane "
+                    + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " "
+                    + "> currentValue, actual value = " + currentValue + ")",
+                    initialHorizontalValue > currentValue);
+        }
 
-            // Check scroll to Right
-            {
-                jspo.scrollToRight();
-                int currentValue = jspo.getHorizontalScrollBar().getValue();
-                System.out.println("Scroll to Right Final Value = " + currentValue);
-                assertTrue("Scroll to Right of Pane "
-                        + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " "
-                        + "< currentValue, actual value = " + currentValue + ")",
-                        initialHorizontalValue < currentValue);
-            }
-        });
+        // Check scroll to Right
+        {
+            jspo.scrollToRight();
+            int currentValue = jspo.getHorizontalScrollBar().getValue();
+            System.out.println("Scroll to Right Final Value = " + currentValue);
+            assertTrue("Scroll to Right of Pane "
+                    + "(initialHorizontalValue, actual value: " + initialHorizontalValue + " "
+                    + "< currentValue, actual value = " + currentValue + ")",
+                    initialHorizontalValue < currentValue);
+        }
     }
 
 }
--- a/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/SpinnerDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.spinner.SpinnerDemo;
 import static com.sun.swingset3.demos.spinner.SpinnerDemo.DEMO_TITLE;
 import java.text.DecimalFormat;
@@ -30,7 +31,7 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JSpinnerOperator;
 import org.netbeans.jemmy.operators.JTextFieldOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -39,12 +40,13 @@
  *          the spinner button and checking text field value.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.spinner.SpinnerDemo
  * @run testng SpinnerDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class SpinnerDemoTest {
 
     private static final int SPINNERS_COUNT = 9;
@@ -52,16 +54,14 @@
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication();
+        new ClassReference(SpinnerDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
 
-            // Check changing different spinners
-            for (int i = 0; i < SPINNERS_COUNT; i++) {
-                changeValues(frame, i);
-            }
-        });
+        // Check changing different spinners
+        for (int i = 0; i < SPINNERS_COUNT; i++) {
+            changeValues(frame, i);
+        }
     }
 
     private void changeValues(JFrameOperator jfo, int spinnerIndex) throws Exception {
--- a/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/SplitPaneDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.splitpane.SplitPaneDemo;
 import static com.sun.swingset3.demos.splitpane.SplitPaneDemo.*;
 import java.awt.event.KeyEvent;
@@ -35,6 +36,7 @@
 import org.netbeans.jemmy.operators.JSplitPaneOperator;
 import org.netbeans.jemmy.operators.JTextFieldOperator;
 import static org.jemmy2ext.JemmyExt.*;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -44,39 +46,39 @@
  *          and changing the divider orientation.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.splitpane.SplitPaneDemo
  * @run testng SplitPaneDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class SplitPaneDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        new ClassReference(SplitPaneDemo.class.getCanonicalName()).startApplication();
+
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
 
-            JSplitPaneOperator splitPane = new JSplitPaneOperator(frame);
+        JSplitPaneOperator splitPane = new JSplitPaneOperator(frame);
 
-            // Toggle OneTouch Expandable
-            checkOneTouch(frame, splitPane, true);
-            checkOneTouch(frame, splitPane, false);
+        // Toggle OneTouch Expandable
+        checkOneTouch(frame, splitPane, true);
+        checkOneTouch(frame, splitPane, false);
 
-            // Check changing divider size to minimum and maximum values
-            changeDividerSize(frame, splitPane, 50);
-            changeDividerSize(frame, splitPane, 6);
+        // Check changing divider size to minimum and maximum values
+        changeDividerSize(frame, splitPane, 50);
+        changeDividerSize(frame, splitPane, 6);
 
-            // Check moving the divider
-            checkDividerMoves(frame, splitPane, false);
-            checkDividerMoves(frame, splitPane, true);
+        // Check moving the divider
+        checkDividerMoves(frame, splitPane, false);
+        checkDividerMoves(frame, splitPane, true);
 
-            // Check different minumum Day/Night sizes
-            changeMinimumSizes(frame, splitPane, 100);
-            changeMinimumSizes(frame, splitPane, 0);
-        });
+        // Check different minumum Day/Night sizes
+        changeMinimumSizes(frame, splitPane, 100);
+        changeMinimumSizes(frame, splitPane, 0);
     }
 
     // Check for different day and night minimum size
--- a/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/TabbedPaneDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo;
 import static com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo.*;
 import static org.jemmy2ext.JemmyExt.getLabeledContainerOperator;
@@ -31,7 +32,7 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JRadioButtonOperator;
 import org.netbeans.jemmy.operators.JTabbedPaneOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -40,25 +41,24 @@
  *          positions, opening each tab and verifying the the tab gets selected.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.tabbedpane.TabbedPaneDemo
  * @run testng TabbedPaneDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class TabbedPaneDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication();
+        new ClassReference(TabbedPaneDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
+        JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
 
-            for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) {
-                testTabs(mainFrame, tp);
-            }
-        });
+        for (String tp : new String[]{TOP, LEFT, BOTTOM, RIGHT}) {
+            testTabs(mainFrame, tp);
+        }
     }
 
     public void testTabs(JFrameOperator mainFrame, String tabPlacement) throws Exception {
--- a/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/TextFieldDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.textfield.JHistoryTextField;
 import com.sun.swingset3.demos.textfield.TextFieldDemo;
 import static com.sun.swingset3.demos.textfield.TextFieldDemo.*;
@@ -41,6 +42,7 @@
 import org.netbeans.jemmy.operators.JLabelOperator;
 import org.netbeans.jemmy.operators.JPasswordFieldOperator;
 import org.netbeans.jemmy.operators.JTextFieldOperator;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -49,25 +51,25 @@
  *          checking that app reacts accordingly.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.textfield.TextFieldDemo
  * @run testng TextFieldDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class TextFieldDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        new ClassReference(TextFieldDemo.class.getCanonicalName()).startApplication();
 
-            historyTextField(frame);
-            dateTextField(frame);
-            passwordField(frame);
-        });
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+
+        historyTextField(frame);
+        dateTextField(frame);
+        passwordField(frame);
     }
 
     private void historyTextField(JFrameOperator jfo) throws Exception {
--- a/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/ToggleButtonDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.DemoProperties;
 import com.sun.swingset3.demos.togglebutton.DirectionPanel;
 import com.sun.swingset3.demos.togglebutton.LayoutControlPanel;
@@ -40,7 +41,7 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JRadioButtonOperator;
 import org.netbeans.jemmy.operators.JTabbedPaneOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -53,50 +54,49 @@
  *          selected.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.togglebutton.ToggleButtonDemo
  * @run testng ToggleButtonDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class ToggleButtonDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication();
+        new ClassReference(ToggleButtonDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value());
-            JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame);
+        JFrameOperator mainFrame = new JFrameOperator(ToggleButtonDemo.class.getAnnotation(DemoProperties.class).value());
+        JTabbedPaneOperator tabPane = new JTabbedPaneOperator(mainFrame);
 
-            // Radio Button Toggles
-            testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null);
-            testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null);
-            testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t));
+        // Radio Button Toggles
+        testRadioButtons(getBorderTitledJPanelOperator(mainFrame, TEXT_RADIO_BUTTONS), 3, null);
+        testRadioButtons(getBorderTitledJPanelOperator(mainFrame, IMAGE_RADIO_BUTTONS), 3, null);
+        testRadioButtons(getLabeledContainerOperator(mainFrame, PAD_AMOUNT), 3, (t, i) -> DEFAULT.equals(t));
 
-            // switch to the Check Boxes Tab
-            tabPane.selectPage(CHECK_BOXES);
+        // switch to the Check Boxes Tab
+        tabPane.selectPage(CHECK_BOXES);
 
-            // Check Box Toggles
-            ContainerOperator<?> textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES);
-            testCheckBox(textCheckBoxesJPanel, CHECK1, false);
-            testCheckBox(textCheckBoxesJPanel, CHECK2, false);
-            testCheckBox(textCheckBoxesJPanel, CHECK3, false);
+        // Check Box Toggles
+        ContainerOperator<?> textCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, TEXT_CHECKBOXES);
+        testCheckBox(textCheckBoxesJPanel, CHECK1, false);
+        testCheckBox(textCheckBoxesJPanel, CHECK2, false);
+        testCheckBox(textCheckBoxesJPanel, CHECK3, false);
 
-            ContainerOperator<?> imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES);
-            testCheckBox(imageCheckBoxesJPanel, CHECK1, false);
-            testCheckBox(imageCheckBoxesJPanel, CHECK2, false);
-            testCheckBox(imageCheckBoxesJPanel, CHECK3, false);
+        ContainerOperator<?> imageCheckBoxesJPanel = getBorderTitledJPanelOperator(mainFrame, IMAGE_CHECKBOXES);
+        testCheckBox(imageCheckBoxesJPanel, CHECK1, false);
+        testCheckBox(imageCheckBoxesJPanel, CHECK2, false);
+        testCheckBox(imageCheckBoxesJPanel, CHECK3, false);
 
-            ContainerOperator<?> displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS);
-            testCheckBox(displayOptionsContainer, PAINT_BORDER, false);
-            testCheckBox(displayOptionsContainer, PAINT_FOCUS, true);
-            testCheckBox(displayOptionsContainer, ENABLED, true);
-            testCheckBox(displayOptionsContainer, CONTENT_FILLED, true);
+        ContainerOperator<?> displayOptionsContainer = getLabeledContainerOperator(mainFrame, DISPLAY_OPTIONS);
+        testCheckBox(displayOptionsContainer, PAINT_BORDER, false);
+        testCheckBox(displayOptionsContainer, PAINT_FOCUS, true);
+        testCheckBox(displayOptionsContainer, ENABLED, true);
+        testCheckBox(displayOptionsContainer, CONTENT_FILLED, true);
 
-            // Direction Button Toggles
-            testToggleButtons(mainFrame);
-        });
+        // Direction Button Toggles
+        testToggleButtons(mainFrame);
     }
 
     /**
--- a/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/TreeDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.tree.TreeDemo;
 import static com.sun.swingset3.demos.tree.TreeDemo.DEMO_TITLE;
 import javax.swing.tree.TreePath;
@@ -29,7 +30,7 @@
 import org.netbeans.jemmy.ClassReference;
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JTreeOperator;
-import static org.jemmy2ext.JemmyExt.captureDebugInfoOnFail;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -42,67 +43,67 @@
  *          vertically (as ScrollPane allows it).
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.tree.TreeDemo
  * @run testng TreeDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class TreeDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(TreeDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
+        new ClassReference(TreeDemo.class.getCanonicalName()).startApplication();
+
+        JFrameOperator frame = new JFrameOperator(DEMO_TITLE);
 
-            JTreeOperator tree = new JTreeOperator(frame);
+        JTreeOperator tree = new JTreeOperator(frame);
 
-            assertEquals("Initial number of rows in the tree", 4, tree.getRowCount());
+        assertEquals("Initial number of rows in the tree", 4, tree.getRowCount());
 
-            int initialTreeHeight = tree.getHeight();
+        int initialTreeHeight = tree.getHeight();
 
-            // expand all nodes
-            int expandsCount = 0;
-            for (int i = 0; i < tree.getRowCount(); i++) {
-                TreePath tp = tree.getPathForRow(i);
-                if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) {
-                    tree.expandRow(i);
-                    expandsCount++;
-                }
+        // expand all nodes
+        int expandsCount = 0;
+        for (int i = 0; i < tree.getRowCount(); i++) {
+            TreePath tp = tree.getPathForRow(i);
+            if (tree.getChildCount(tp) > 0 && !tree.isExpanded(tp)) {
+                tree.expandRow(i);
+                expandsCount++;
             }
+        }
 
-            assertEquals("Number of rows expanded", 75, expandsCount);
-            assertEquals("Number of rows in the tree after expanding all of them",
-                    616, tree.getRowCount());
+        assertEquals("Number of rows expanded", 75, expandsCount);
+        assertEquals("Number of rows in the tree after expanding all of them",
+                616, tree.getRowCount());
 
-            int expandedTreeHeight = tree.getHeight();
-            assertTrue("Expanded tree height has increased, current "
-                    + expandedTreeHeight + " > initial " + initialTreeHeight,
-                    expandedTreeHeight > initialTreeHeight);
+        int expandedTreeHeight = tree.getHeight();
+        assertTrue("Expanded tree height has increased, current "
+                + expandedTreeHeight + " > initial " + initialTreeHeight,
+                expandedTreeHeight > initialTreeHeight);
 
-            // collapse all nodes
-            int collapsesCount = 0;
-            for (int i = tree.getRowCount() - 1; i >= 0; i--) {
-                TreePath tp = tree.getPathForRow(i);
-                if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) {
-                    tree.collapseRow(i);
-                    collapsesCount++;
-                }
+        // collapse all nodes
+        int collapsesCount = 0;
+        for (int i = tree.getRowCount() - 1; i >= 0; i--) {
+            TreePath tp = tree.getPathForRow(i);
+            if (tree.getChildCount(tp) > 0 && tree.isExpanded(tp)) {
+                tree.collapseRow(i);
+                collapsesCount++;
             }
+        }
 
-            assertEquals("Number of rows collapsed", 76, collapsesCount);
-            assertEquals("Number of rows in the tree after collapsing all of them",
-                    1, tree.getRowCount());
+        assertEquals("Number of rows collapsed", 76, collapsesCount);
+        assertEquals("Number of rows in the tree after collapsing all of them",
+                1, tree.getRowCount());
 
-            int collapsedTreeHeight = tree.getHeight();
-            assertTrue("Collpased tree height is not longer than initial, "
-                    + "current " + collapsedTreeHeight + " <= initial "
-                    + initialTreeHeight,
-                    collapsedTreeHeight <= initialTreeHeight);
+        int collapsedTreeHeight = tree.getHeight();
+        assertTrue("Collpased tree height is not longer than initial, "
+                + "current " + collapsedTreeHeight + " <= initial "
+                + initialTreeHeight,
+                collapsedTreeHeight <= initialTreeHeight);
 
-        });
     }
 
 }
--- a/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/SwingSet/src/WindowDemoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -21,6 +21,7 @@
  * questions.
  */
 
+import org.jtregext.GuiTestListener;
 import com.sun.swingset3.demos.window.WindowDemo;
 import static com.sun.swingset3.demos.window.WindowDemo.*;
 import static org.jemmy2ext.JemmyExt.*;
@@ -31,6 +32,7 @@
 import org.netbeans.jemmy.operators.JFrameOperator;
 import org.netbeans.jemmy.operators.JLabelOperator;
 import org.netbeans.jemmy.operators.WindowOperator;
+import org.testng.annotations.Listeners;
 
 /*
  * @test
@@ -40,37 +42,37 @@
  *          when the "Show JWindow..." button is clicked.
  *
  * @library /sanity/client/lib/jemmy/src
- * @library /sanity/client/lib/Jemmy2Ext/src
+ * @library /sanity/client/lib/Extensions/src
  * @library /sanity/client/lib/SwingSet3/src
  * @build org.jemmy2ext.JemmyExt
  * @build com.sun.swingset3.demos.window.WindowDemo
  * @run testng WindowDemoTest
  */
+@Listeners(GuiTestListener.class)
 public class WindowDemoTest {
 
     @Test
     public void test() throws Exception {
-        captureDebugInfoOnFail(() -> {
-            new ClassReference(WindowDemo.class.getCanonicalName()).startApplication();
+
+        new ClassReference(WindowDemo.class.getCanonicalName()).startApplication();
 
-            JFrameOperator frame = new JFrameOperator();
+        JFrameOperator frame = new JFrameOperator();
 
-            assertEquals("Only one JWindow is shown", 1, getJWindowCount());
+        assertEquals("Only one JWindow is shown", 1, getJWindowCount());
 
-            WindowOperator window = new WindowOperator(getJWindow());
+        WindowOperator window = new WindowOperator(getJWindow());
 
-            assertTrue("JFrame is showing", frame.isShowing());
-            assertFalse("JFrame is not iconified", isIconified(frame));
-            assertTrue("JWindow is showing", window.isShowing());
+        assertTrue("JFrame is showing", frame.isShowing());
+        assertFalse("JFrame is not iconified", isIconified(frame));
+        assertTrue("JWindow is showing", window.isShowing());
 
-            final String labelText = I_HAVE_NO_SYSTEM_BORDER;
-            JLabelOperator jLabelOperator = new JLabelOperator(window, labelText);
-            assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText());
+        final String labelText = I_HAVE_NO_SYSTEM_BORDER;
+        JLabelOperator jLabelOperator = new JLabelOperator(window, labelText);
+        assertEquals("JWindow contains the label with corresponding text", labelText, jLabelOperator.getText());
 
-            new JButtonOperator(frame, SHOW_J_WINDOW).push();
+        new JButtonOperator(frame, SHOW_J_WINDOW).push();
 
-            assertEquals("Only one JWindow is shown", 1, getJWindowCount());
-        });
+        assertEquals("Only one JWindow is shown", 1, getJWindowCount());
     }
 
 }
--- a/jdk/test/sanity/client/TEST.ROOT.template	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/TEST.ROOT.template	Wed Jul 05 21:39:33 2017 +0200
@@ -12,7 +12,7 @@
 # A "headful" test requires a graphical environment to meaningfully
 # run. Tests that are not headful are "headless." 
 
-keys=screenshots
+keys=2d dnd i18n intermittent randomness headful
 
 # Tests that must run in othervm mode
 othervm.dirs=sanity/client/SwingSet
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.jemmy2ext;
+
+import java.awt.Component;
+import java.awt.EventQueue;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Window;
+import java.awt.image.BufferedImage;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.IntStream;
+import javax.imageio.ImageIO;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JWindow;
+import javax.swing.border.Border;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.TitledBorder;
+import org.netbeans.jemmy.ComponentChooser;
+import org.netbeans.jemmy.DefaultCharBindingMap;
+import org.netbeans.jemmy.QueueTool;
+import org.netbeans.jemmy.TimeoutExpiredException;
+import org.netbeans.jemmy.Waitable;
+import org.netbeans.jemmy.Waiter;
+import org.netbeans.jemmy.drivers.scrolling.JSpinnerDriver;
+import org.netbeans.jemmy.image.StrictImageComparator;
+import org.netbeans.jemmy.operators.ComponentOperator;
+import org.netbeans.jemmy.operators.ContainerOperator;
+import org.netbeans.jemmy.operators.FrameOperator;
+import org.netbeans.jemmy.operators.JButtonOperator;
+import org.netbeans.jemmy.operators.JFrameOperator;
+import org.netbeans.jemmy.operators.JLabelOperator;
+import org.netbeans.jemmy.operators.Operator;
+import org.netbeans.jemmy.util.Dumper;
+import org.netbeans.jemmy.util.PNGEncoder;
+import static org.testng.AssertJUnit.*;
+
+/**
+ * This class solves two tasks: 1. It adds functionality that is missing in
+ * Jemmy 2. It references all the Jemmy API that is needed by tests so that they
+ * can just @build JemmyExt class and do not worry about Jemmy
+ *
+ * @author akouznet
+ */
+public class JemmyExt {
+
+    /**
+     * Statically referencing all the classes that are needed by tests so that
+     * they're compiled by jtreg
+     */
+    static final Class<?>[] DEPENDENCIES = {
+        JSpinnerDriver.class,
+        DefaultCharBindingMap.class
+    };
+
+    public static void assertNotBlack(BufferedImage image) {
+        int w = image.getWidth();
+        int h = image.getHeight();
+        try {
+            assertFalse("All pixels are not black", IntStream.range(0, w).parallel().allMatch(x
+                    -> IntStream.range(0, h).allMatch(y -> (image.getRGB(x, y) & 0xffffff) == 0)
+            ));
+        } catch (Throwable t) {
+            save(image, "allPixelsAreBlack.png");
+            throw t;
+        }
+    }
+
+    public static void waitArmed(JButtonOperator button) {
+        button.waitState(new ComponentChooser() {
+
+            @Override
+            public boolean checkComponent(Component comp) {
+                return isArmed(button);
+            }
+
+            @Override
+            public String getDescription() {
+                return "Button is armed";
+            }
+        });
+    }
+
+    public static boolean isArmed(JButtonOperator button) {
+        return button.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<Boolean>("getModel().isArmed()") {
+
+            @Override
+            public Boolean launch() throws Exception {
+                return ((JButton) button.getSource()).getModel().isArmed();
+            }
+        });
+    }
+
+    public static void waitPressed(JButtonOperator button) {
+        button.waitState(new ComponentChooser() {
+
+            @Override
+            public boolean checkComponent(Component comp) {
+                return isPressed(button);
+            }
+
+            @Override
+            public String getDescription() {
+                return "Button is pressed";
+            }
+        });
+    }
+
+    public static boolean isPressed(JButtonOperator button) {
+        return button.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<Boolean>("getModel().isPressed()") {
+
+            @Override
+            public Boolean launch() throws Exception {
+                return ((JButton) button.getSource()).getModel().isPressed();
+            }
+        });
+    }
+
+    public static void assertEquals(String string, StrictImageComparator comparator, BufferedImage expected, BufferedImage actual) {
+        try {
+            assertTrue(string, comparator.compare(expected, actual));
+        } catch (Error err) {
+            save(expected, "expected.png");
+            save(actual, "actual.png");
+            throw err;
+        }
+    }
+
+    public static void assertNotEquals(String string, StrictImageComparator comparator, BufferedImage notExpected, BufferedImage actual) {
+        try {
+            assertFalse(string, comparator.compare(notExpected, actual));
+        } catch (Error err) {
+            save(notExpected, "notExpected.png");
+            save(actual, "actual.png");
+            throw err;
+        }
+    }
+
+    public static void save(BufferedImage image, String filename) {
+        String filepath = filename;
+        try {
+            filepath = new File(filename).getCanonicalPath();
+            System.out.println("Saving screenshot to " + filepath);
+            BufferedOutputStream file = new BufferedOutputStream(new FileOutputStream(filepath));
+            new PNGEncoder(file, PNGEncoder.COLOR_MODE).encode(image);
+        } catch (IOException ioe) {
+            throw new RuntimeException("Failed to save image to " + filepath, ioe);
+        }
+    }
+
+    public static void waitImageIsStill(Robot rob, ComponentOperator operator) {
+        operator.waitState(new ComponentChooser() {
+
+            private BufferedImage previousImage = null;
+            private int index = 0;
+            private final StrictImageComparator sComparator = new StrictImageComparator();
+
+            @Override
+            public boolean checkComponent(Component comp) {
+                BufferedImage currentImage = capture(rob, operator);
+                save(currentImage, "waitImageIsStill" + index + ".png");
+                index++;
+                boolean compareResult = previousImage == null ? false : sComparator.compare(currentImage, previousImage);
+                previousImage = currentImage;
+                return compareResult;
+            }
+
+            @Override
+            public String getDescription() {
+                return "Image of " + operator + " is still";
+            }
+        });
+    }
+
+    private static class ThrowableHolder {
+
+        volatile Throwable t;
+    }
+
+    public static void waitFor(String description, RunnableWithException r) throws Exception {
+        Waiter<Boolean, ThrowableHolder> waiter = new Waiter<>(new Waitable<Boolean, ThrowableHolder>() {
+
+            @Override
+            public Boolean actionProduced(ThrowableHolder obj) {
+                try {
+                    r.run();
+                    return true;
+                } catch (Throwable t) {
+                    obj.t = t;
+                    return null;
+                }
+            }
+
+            @Override
+            public String getDescription() {
+                return description;
+            }
+        });
+        ThrowableHolder th = new ThrowableHolder();
+        try {
+            waiter.waitAction(th);
+        } catch (TimeoutExpiredException tee) {
+            Throwable t = th.t;
+            if (t != null) {
+                t.addSuppressed(tee);
+                if (t instanceof Exception) {
+                    throw (Exception) t;
+                } else if (t instanceof Error) {
+                    throw (Error) t;
+                } else if (t instanceof RuntimeException) {
+                    throw (RuntimeException) t;
+                } else {
+                    throw new IllegalStateException("Unexpected exception type", t);
+                }
+            }
+        }
+    }
+
+    public static BufferedImage capture(Robot rob, ComponentOperator operator) {
+        Rectangle boundary = new Rectangle(operator.getLocationOnScreen(),
+                operator.getSize());
+        return rob.createScreenCapture(boundary);
+    }
+
+    /**
+     * Dispose all AWT/Swing windows causing event thread to stop
+     */
+    public static void disposeAllWindows() {
+        System.out.println("disposeAllWindows");
+        try {
+            EventQueue.invokeAndWait(() -> {
+                Window[] windows = Window.getWindows();
+                for (Window w : windows) {
+                    w.dispose();
+                }
+            });
+        } catch (InterruptedException | InvocationTargetException ex) {
+            Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, "Failed to dispose all windows", ex);
+        }
+    }
+
+    /**
+     * This is a helper class which allows to catch throwables thrown in other
+     * threads and throw them in the main test thread
+     */
+    public static class MultiThreadedTryCatch {
+
+        private final List<Throwable> throwables
+                = Collections.synchronizedList(new ArrayList<>());
+
+        /**
+         * Throws registered throwables. If the list of the registered
+         * throwables is not empty, it re-throws the first throwable in the list
+         * adding all others into its suppressed list. Can be used in any
+         * thread.
+         *
+         * @throws Exception
+         */
+        public void throwRegistered() throws Exception {
+            Throwable root = null;
+            synchronized (throwables) {
+                if (!throwables.isEmpty()) {
+                    root = throwables.remove(0);
+                    while (!throwables.isEmpty()) {
+                        root.addSuppressed(throwables.remove(0));
+                    }
+                }
+            }
+            if (root != null) {
+                if (root instanceof Error) {
+                    throw (Error) root;
+                } else if (root instanceof Exception) {
+                    throw (Exception) root;
+                } else {
+                    throw new AssertionError("Unexpected exception type: " + root.getClass() + " (" + root + ")");
+                }
+            }
+        }
+
+        /**
+         * Registers a throwable and adds it to the list of throwables. Can be
+         * used in any thread.
+         *
+         * @param t
+         */
+        public void register(Throwable t) {
+            t.printStackTrace();
+            throwables.add(t);
+        }
+
+        /**
+         * Registers a throwable and adds it as the first item of the list of
+         * catched throwables.
+         *
+         * @param t
+         */
+        public void registerRoot(Throwable t) {
+            t.printStackTrace();
+            throwables.add(0, t);
+        }
+    }
+
+    /**
+     * Trying to capture as much information as possible. Currently it includes
+     * full dump and a screenshot of the whole screen.
+     */
+    public static void captureAll() {
+        PNGEncoder.captureScreen("failure.png", PNGEncoder.COLOR_MODE);
+        try {
+            Dumper.dumpAll("dumpAll.xml");
+        } catch (FileNotFoundException ex) {
+            Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        captureWindows();
+    }
+
+    /**
+     * Captures each showing window image using Window.paint() method.
+     */
+    private static void captureWindows() {
+        try {
+            EventQueue.invokeAndWait(() -> {
+                Window[] windows = Window.getWindows();
+                int index = 0;
+                for (Window w : windows) {
+                    if (!w.isShowing()) {
+                        continue;
+                    }
+                    BufferedImage img = new BufferedImage(w.getWidth(), w.getHeight(), BufferedImage.TYPE_INT_ARGB);
+                    Graphics g = img.getGraphics();
+                    w.paint(g);
+                    g.dispose();
+
+                    try {
+                        ImageIO.write(img, "png", new File("window" + index++ + ".png"));
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+        } catch (InterruptedException | InvocationTargetException ex) {
+            Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, null, ex);
+        }
+    }
+
+    public static interface RunnableWithException {
+
+        public void run() throws Exception;
+    }
+
+    public static void waitIsFocused(JFrameOperator jfo) {
+        jfo.waitState(new ComponentChooser() {
+
+            @Override
+            public boolean checkComponent(Component comp) {
+                return jfo.isFocused();
+            }
+
+            @Override
+            public String getDescription() {
+                return "JFrame is focused";
+            }
+        });
+    }
+
+    public static int getJWindowCount() {
+        return new QueueTool().invokeAndWait(new QueueTool.QueueAction<Integer>(null) {
+
+            @Override
+            public Integer launch() throws Exception {
+                Window[] windows = Window.getWindows();
+                int windowCount = 0;
+                for (Window w : windows) {
+                    if (w.getClass().equals(JWindow.class)) {
+                        windowCount++;
+                    }
+                }
+                return windowCount;
+            }
+        });
+    }
+
+    public static JWindow getJWindow() {
+        return getJWindow(0);
+    }
+
+    public static JWindow getJWindow(int index) {
+        return new QueueTool().invokeAndWait(new QueueTool.QueueAction<JWindow>(null) {
+
+            @Override
+            public JWindow launch() throws Exception {
+                Window[] windows = Window.getWindows();
+                int windowIndex = 0;
+                for (Window w : windows) {
+                    if (w.getClass().equals(JWindow.class)) {
+                        if (windowIndex == index) {
+                            return (JWindow) w;
+                        }
+                        windowIndex++;
+                    }
+                }
+                return null;
+            }
+        });
+    }
+
+    public static boolean isIconified(FrameOperator frameOperator) {
+        return frameOperator.getQueueTool().invokeAndWait(new QueueTool.QueueAction<Boolean>("Frame is iconified") {
+
+            @Override
+            public Boolean launch() throws Exception {
+                return (((Frame) frameOperator.getSource()).getState() & Frame.ICONIFIED) != 0;
+            }
+        });
+    }
+
+    public static final Operator.DefaultStringComparator EXACT_STRING_COMPARATOR
+            = new Operator.DefaultStringComparator(true, true);
+
+    /**
+     * Finds a label with the exact labelText and returns the operator for its
+     * parent container.
+     *
+     * @param container
+     * @param labelText
+     * @return
+     */
+    public static ContainerOperator<?> getLabeledContainerOperator(ContainerOperator<?> container, String labelText) {
+
+        container.setComparator(EXACT_STRING_COMPARATOR);
+
+        JLabelOperator jLabelOperator = new JLabelOperator(container, labelText);
+
+        assert labelText.equals(jLabelOperator.getText());
+
+        return new ContainerOperator<>(jLabelOperator.getParent());
+    }
+
+    /**
+     * Finds a JPanel with exact title text.
+     *
+     * @param container
+     * @param titleText
+     * @return
+     */
+    public static ContainerOperator<?> getBorderTitledJPanelOperator(ContainerOperator<?> container, String titleText) {
+        return new ContainerOperator<>(container, new JPanelByBorderTitleFinder(titleText, EXACT_STRING_COMPARATOR));
+    }
+
+    public static final QueueTool QUEUE_TOOL = new QueueTool();
+
+    /**
+     * Allows to find JPanel by the title text in its border.
+     */
+    public static class JPanelByBorderTitleFinder implements ComponentChooser {
+
+        String titleText;
+        Operator.StringComparator comparator;
+
+        /**
+         * @param titleText title text pattern
+         * @param comparator specifies string comparison algorithm.
+         */
+        public JPanelByBorderTitleFinder(String titleText, Operator.StringComparator comparator) {
+            this.titleText = titleText;
+            this.comparator = comparator;
+        }
+
+        /**
+         * @param titleText title text pattern
+         */
+        public JPanelByBorderTitleFinder(String titleText) {
+            this(titleText, Operator.getDefaultStringComparator());
+        }
+
+        @Override
+        public boolean checkComponent(Component comp) {
+            assert EventQueue.isDispatchThread();
+            if (comp instanceof JPanel) {
+                return checkBorder(((JPanel) comp).getBorder());
+            }
+            return false;
+        }
+
+        public boolean checkBorder(Border border) {
+            if (border instanceof TitledBorder) {
+                String title = ((TitledBorder) border).getTitle();
+                return comparator.equals(title, titleText);
+            } else if (border instanceof CompoundBorder) {
+                CompoundBorder compoundBorder = (CompoundBorder) border;
+                return checkBorder(compoundBorder.getInsideBorder()) || checkBorder(compoundBorder.getOutsideBorder());
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public String getDescription() {
+            return ("JPanel with border title text \"" + titleText + "\" with comparator " + comparator);
+        }
+    }
+
+    public static class ByClassSimpleNameChooser implements ComponentChooser {
+
+        private final String className;
+
+        public ByClassSimpleNameChooser(String className) {
+            this.className = className;
+        }
+
+        @Override
+        public boolean checkComponent(Component comp) {
+            return comp.getClass().getSimpleName().equals(className);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Component with the simple class name of " + className;
+        }
+
+    }
+
+    public static class ByClassChooser implements ComponentChooser {
+
+        private final Class<?> clazz;
+
+        public ByClassChooser(Class<?> clazz) {
+            this.clazz = clazz;
+        }
+
+        @Override
+        public boolean checkComponent(Component comp) {
+            return comp.getClass().equals(clazz);
+        }
+
+        @Override
+        public String getDescription() {
+            return "Component with the class of " + clazz;
+        }
+
+    }
+
+    public static class ByToolTipChooser implements ComponentChooser {
+
+        private final String tooltip;
+
+        public ByToolTipChooser(String tooltip) {
+            if (tooltip == null) {
+                throw new NullPointerException("Tooltip cannot be null");
+            }
+            this.tooltip = tooltip;
+        }
+
+        @Override
+        public boolean checkComponent(Component comp) {
+            return (comp instanceof JComponent)
+                    ? tooltip.equals(((JComponent) comp).getToolTipText())
+                    : false;
+        }
+
+        @Override
+        public String getDescription() {
+            return "JComponent with the tooltip '" + tooltip + "'";
+        }
+
+    }
+
+    @SuppressWarnings(value = "unchecked")
+    public static <R, O extends Operator, S extends Component> R getUIValue(O operator, Function<S, R> getter) {
+        return operator.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<R>("getting UI value through the queue using " + getter) {
+
+            @Override
+            public R launch() throws Exception {
+                return getter.apply((S) operator.getSource());
+            }
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sanity/client/lib/Extensions/src/org/jtregext/GuiTestListener.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,72 @@
+package org.jtregext;
+
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import org.jemmy2ext.JemmyExt;
+import static org.jemmy2ext.JemmyExt.captureAll;
+import org.testng.ITestContext;
+import org.testng.ITestListener;
+import org.testng.ITestResult;
+
+// TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed
+public class GuiTestListener implements ITestListener {
+
+    private void afterTest() {
+        JemmyExt.disposeAllWindows();
+    }
+
+    @Override
+    public void onTestStart(ITestResult result) {
+    }
+
+    @Override
+    public void onTestSuccess(ITestResult result) {
+        System.out.println("TEST PASSED");
+        afterTest();
+    }
+
+    @Override
+    public void onTestFailure(ITestResult result) {
+        captureAll();
+        afterTest();
+    }
+
+    @Override
+    public void onTestSkipped(ITestResult result) {
+    }
+
+    @Override
+    public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
+    }
+
+    @Override
+    public void onStart(ITestContext context) {
+    }
+
+    @Override
+    public void onFinish(ITestContext context) {
+    }
+
+}
--- a/jdk/test/sanity/client/lib/Jemmy2Ext/src/org/jemmy2ext/JemmyExt.java	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,614 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.jemmy2ext;
-
-import java.awt.Component;
-import java.awt.EventQueue;
-import java.awt.Frame;
-import java.awt.Graphics;
-import java.awt.Rectangle;
-import java.awt.Robot;
-import java.awt.Window;
-import java.awt.image.BufferedImage;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.IntStream;
-import javax.imageio.ImageIO;
-import javax.swing.JButton;
-import javax.swing.JComponent;
-import javax.swing.JPanel;
-import javax.swing.JWindow;
-import javax.swing.border.Border;
-import javax.swing.border.CompoundBorder;
-import javax.swing.border.TitledBorder;
-import org.netbeans.jemmy.ComponentChooser;
-import org.netbeans.jemmy.DefaultCharBindingMap;
-import org.netbeans.jemmy.QueueTool;
-import org.netbeans.jemmy.TimeoutExpiredException;
-import org.netbeans.jemmy.Waitable;
-import org.netbeans.jemmy.Waiter;
-import org.netbeans.jemmy.drivers.scrolling.JSpinnerDriver;
-import org.netbeans.jemmy.image.StrictImageComparator;
-import org.netbeans.jemmy.operators.ComponentOperator;
-import org.netbeans.jemmy.operators.ContainerOperator;
-import org.netbeans.jemmy.operators.FrameOperator;
-import org.netbeans.jemmy.operators.JButtonOperator;
-import org.netbeans.jemmy.operators.JFrameOperator;
-import org.netbeans.jemmy.operators.JLabelOperator;
-import org.netbeans.jemmy.operators.Operator;
-import org.netbeans.jemmy.util.Dumper;
-import org.netbeans.jemmy.util.PNGEncoder;
-import static org.testng.AssertJUnit.*;
-
-/**
- * This class solves two tasks: 1. It adds functionality that is missing in
- * Jemmy 2. It references all the Jemmy API that is needed by tests so that they
- * can just @build JemmyExt class and do not worry about Jemmy
- *
- * @author akouznet
- */
-public class JemmyExt {
-
-    /**
-     * Statically referencing all the classes that are needed by tests so that
-     * they're compiled by jtreg
-     */
-    static final Class<?>[] DEPENDENCIES = {
-        JSpinnerDriver.class,
-        DefaultCharBindingMap.class
-    };
-
-    public static void assertNotBlack(BufferedImage image) {
-        int w = image.getWidth();
-        int h = image.getHeight();
-        try {
-            assertFalse("All pixels are not black", IntStream.range(0, w).parallel().allMatch(x
-                    -> IntStream.range(0, h).allMatch(y -> (image.getRGB(x, y) & 0xffffff) == 0)
-            ));
-        } catch (Throwable t) {
-            save(image, "allPixelsAreBlack.png");
-            throw t;
-        }
-    }
-
-    public static void waitArmed(JButtonOperator button) {
-        button.waitState(new ComponentChooser() {
-
-            @Override
-            public boolean checkComponent(Component comp) {
-                return isArmed(button);
-            }
-
-            @Override
-            public String getDescription() {
-                return "Button is armed";
-            }
-        });
-    }
-
-    public static boolean isArmed(JButtonOperator button) {
-        return button.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<Boolean>("getModel().isArmed()") {
-
-            @Override
-            public Boolean launch() throws Exception {
-                return ((JButton) button.getSource()).getModel().isArmed();
-            }
-        });
-    }
-
-    public static void waitPressed(JButtonOperator button) {
-        button.waitState(new ComponentChooser() {
-
-            @Override
-            public boolean checkComponent(Component comp) {
-                return isPressed(button);
-            }
-
-            @Override
-            public String getDescription() {
-                return "Button is pressed";
-            }
-        });
-    }
-
-    public static boolean isPressed(JButtonOperator button) {
-        return button.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<Boolean>("getModel().isPressed()") {
-
-            @Override
-            public Boolean launch() throws Exception {
-                return ((JButton) button.getSource()).getModel().isPressed();
-            }
-        });
-    }
-
-    public static void assertEquals(String string, StrictImageComparator comparator, BufferedImage expected, BufferedImage actual) {
-        try {
-            assertTrue(string, comparator.compare(expected, actual));
-        } catch (Error err) {
-            save(expected, "expected.png");
-            save(actual, "actual.png");
-            throw err;
-        }
-    }
-
-    public static void assertNotEquals(String string, StrictImageComparator comparator, BufferedImage notExpected, BufferedImage actual) {
-        try {
-            assertFalse(string, comparator.compare(notExpected, actual));
-        } catch (Error err) {
-            save(notExpected, "notExpected.png");
-            save(actual, "actual.png");
-            throw err;
-        }
-    }
-
-    public static void save(BufferedImage image, String filename) {
-        String filepath = filename;
-        try {
-            filepath = new File(filename).getCanonicalPath();
-            System.out.println("Saving screenshot to " + filepath);
-            BufferedOutputStream file = new BufferedOutputStream(new FileOutputStream(filepath));
-            new PNGEncoder(file, PNGEncoder.COLOR_MODE).encode(image);
-        } catch (IOException ioe) {
-            throw new RuntimeException("Failed to save image to " + filepath, ioe);
-        }
-    }
-
-    public static void waitImageIsStill(Robot rob, ComponentOperator operator) {
-        operator.waitState(new ComponentChooser() {
-
-            private BufferedImage previousImage = null;
-            private int index = 0;
-            private final StrictImageComparator sComparator = new StrictImageComparator();
-
-            @Override
-            public boolean checkComponent(Component comp) {
-                BufferedImage currentImage = capture(rob, operator);
-                save(currentImage, "waitImageIsStill" + index + ".png");
-                index++;
-                boolean compareResult = previousImage == null ? false : sComparator.compare(currentImage, previousImage);
-                previousImage = currentImage;
-                return compareResult;
-            }
-
-            @Override
-            public String getDescription() {
-                return "Image of " + operator + " is still";
-            }
-        });
-    }
-
-    private static class ThrowableHolder {
-
-        volatile Throwable t;
-    }
-
-    public static void waitFor(String description, RunnableWithException r) throws Exception {
-        Waiter<Boolean, ThrowableHolder> waiter = new Waiter<>(new Waitable<Boolean, ThrowableHolder>() {
-
-            @Override
-            public Boolean actionProduced(ThrowableHolder obj) {
-                try {
-                    r.run();
-                    return true;
-                } catch (Throwable t) {
-                    obj.t = t;
-                    return null;
-                }
-            }
-
-            @Override
-            public String getDescription() {
-                return description;
-            }
-        });
-        ThrowableHolder th = new ThrowableHolder();
-        try {
-            waiter.waitAction(th);
-        } catch (TimeoutExpiredException tee) {
-            Throwable t = th.t;
-            if (t != null) {
-                t.addSuppressed(tee);
-                if (t instanceof Exception) {
-                    throw (Exception) t;
-                } else if (t instanceof Error) {
-                    throw (Error) t;
-                } else if (t instanceof RuntimeException) {
-                    throw (RuntimeException) t;
-                } else {
-                    throw new IllegalStateException("Unexpected exception type", t);
-                }
-            }
-        }
-    }
-
-    public static BufferedImage capture(Robot rob, ComponentOperator operator) {
-        Rectangle boundary = new Rectangle(operator.getLocationOnScreen(),
-                operator.getSize());
-        return rob.createScreenCapture(boundary);
-    }
-
-    /**
-     * Wraps the test code so that in case of any failure as much information as
-     * possible is captured
-     *
-     * @param r test code Runnable
-     * @throws Exception whatever exception the test may throw
-     */
-    public static void captureDebugInfoOnFail(RunnableWithException r) throws Exception {
-        // TODO: Remove this once https://bugs.openjdk.java.net/browse/JDK-8151671 is fixed
-        try {
-            r.run();
-            System.out.println("TEST PASSED");
-        } catch (Throwable t) {
-            captureAll();
-            throw t;
-        }
-    }
-
-    /**
-     * This is a helper class which allows to catch throwables thrown in other
-     * threads and throw them in the main test thread
-     */
-    public static class MultiThreadedTryCatch {
-
-        private final List<Throwable> throwables
-                = Collections.synchronizedList(new ArrayList<>());
-
-        /**
-         * Throws registered throwables. If the list of the registered
-         * throwables is not empty, it re-throws the first throwable in the list
-         * adding all others into its suppressed list. Can be used in any
-         * thread.
-         *
-         * @throws Exception
-         */
-        public void throwRegistered() throws Exception {
-            Throwable root = null;
-            synchronized (throwables) {
-                if (!throwables.isEmpty()) {
-                    root = throwables.remove(0);
-                    while (!throwables.isEmpty()) {
-                        root.addSuppressed(throwables.remove(0));
-                    }
-                }
-            }
-            if (root != null) {
-                if (root instanceof Error) {
-                    throw (Error) root;
-                } else if (root instanceof Exception) {
-                    throw (Exception) root;
-                } else {
-                    throw new AssertionError("Unexpected exception type: " + root.getClass() + " (" + root + ")");
-                }
-            }
-        }
-
-        /**
-         * Registers a throwable and adds it to the list of throwables. Can be
-         * used in any thread.
-         *
-         * @param t
-         */
-        public void register(Throwable t) {
-            t.printStackTrace();
-            throwables.add(t);
-        }
-
-        /**
-         * Registers a throwable and adds it as the first item of the list of
-         * catched throwables.
-         *
-         * @param t
-         */
-        public void registerRoot(Throwable t) {
-            t.printStackTrace();
-            throwables.add(0, t);
-        }
-    }
-
-    /**
-     * Trying to capture as much information as possible. Currently it includes
-     * full dump and a screenshot of the whole screen.
-     */
-    public static void captureAll() {
-        PNGEncoder.captureScreen("failure.png", PNGEncoder.COLOR_MODE);
-        try {
-            Dumper.dumpAll("dumpAll.xml");
-        } catch (FileNotFoundException ex) {
-            Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, null, ex);
-        }
-        captureWindows();
-    }
-
-    /**
-     * Captures each showing window image using Window.paint() method.
-     */
-    private static void captureWindows() {
-        try {
-            EventQueue.invokeAndWait(() -> {
-                Window[] windows = Window.getWindows();
-                int index = 0;
-                for (Window w : windows) {
-                    if (!w.isShowing()) {
-                        continue;
-                    }
-                    BufferedImage img = new BufferedImage(w.getWidth(), w.getHeight(), BufferedImage.TYPE_INT_ARGB);
-                    Graphics g = img.getGraphics();
-                    w.paint(g);
-                    g.dispose();
-
-                    try {
-                        ImageIO.write(img, "png", new File("window" + index++ + ".png"));
-                    } catch (IOException e) {
-                        e.printStackTrace();
-                    }
-                }
-            });
-        } catch (InterruptedException | InvocationTargetException ex) {
-            Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, null, ex);
-        }
-    }
-
-    public static interface RunnableWithException {
-
-        public void run() throws Exception;
-    }
-
-    public static void waitIsFocused(JFrameOperator jfo) {
-        jfo.waitState(new ComponentChooser() {
-
-            @Override
-            public boolean checkComponent(Component comp) {
-                return jfo.isFocused();
-            }
-
-            @Override
-            public String getDescription() {
-                return "JFrame is focused";
-            }
-        });
-    }
-
-    public static int getJWindowCount() {
-        return new QueueTool().invokeAndWait(new QueueTool.QueueAction<Integer>(null) {
-
-            @Override
-            public Integer launch() throws Exception {
-                Window[] windows = Window.getWindows();
-                int windowCount = 0;
-                for (Window w : windows) {
-                    if (w.getClass().equals(JWindow.class)) {
-                        windowCount++;
-                    }
-                }
-                return windowCount;
-            }
-        });
-    }
-
-    public static JWindow getJWindow() {
-        return getJWindow(0);
-    }
-
-    public static JWindow getJWindow(int index) {
-        return new QueueTool().invokeAndWait(new QueueTool.QueueAction<JWindow>(null) {
-
-            @Override
-            public JWindow launch() throws Exception {
-                Window[] windows = Window.getWindows();
-                int windowIndex = 0;
-                for (Window w : windows) {
-                    if (w.getClass().equals(JWindow.class)) {
-                        if (windowIndex == index) {
-                            return (JWindow) w;
-                        }
-                        windowIndex++;
-                    }
-                }
-                return null;
-            }
-        });
-    }
-
-    public static boolean isIconified(FrameOperator frameOperator) {
-        return frameOperator.getQueueTool().invokeAndWait(new QueueTool.QueueAction<Boolean>("Frame is iconified") {
-
-            @Override
-            public Boolean launch() throws Exception {
-                return (((Frame) frameOperator.getSource()).getState() & Frame.ICONIFIED) != 0;
-            }
-        });
-    }
-
-    public static final Operator.DefaultStringComparator EXACT_STRING_COMPARATOR
-            = new Operator.DefaultStringComparator(true, true);
-
-    /**
-     * Finds a label with the exact labelText and returns the operator for its
-     * parent container.
-     *
-     * @param container
-     * @param labelText
-     * @return
-     */
-    public static ContainerOperator<?> getLabeledContainerOperator(ContainerOperator<?> container, String labelText) {
-
-        container.setComparator(EXACT_STRING_COMPARATOR);
-
-        JLabelOperator jLabelOperator = new JLabelOperator(container, labelText);
-
-        assert labelText.equals(jLabelOperator.getText());
-
-        return new ContainerOperator<>(jLabelOperator.getParent());
-    }
-
-    /**
-     * Finds a JPanel with exact title text.
-     *
-     * @param container
-     * @param titleText
-     * @return
-     */
-    public static ContainerOperator<?> getBorderTitledJPanelOperator(ContainerOperator<?> container, String titleText) {
-        return new ContainerOperator<>(container, new JPanelByBorderTitleFinder(titleText, EXACT_STRING_COMPARATOR));
-    }
-
-    public static final QueueTool QUEUE_TOOL = new QueueTool();
-
-    /**
-     * Allows to find JPanel by the title text in its border.
-     */
-    public static class JPanelByBorderTitleFinder implements ComponentChooser {
-
-        String titleText;
-        Operator.StringComparator comparator;
-
-        /**
-         * @param titleText title text pattern
-         * @param comparator specifies string comparison algorithm.
-         */
-        public JPanelByBorderTitleFinder(String titleText, Operator.StringComparator comparator) {
-            this.titleText = titleText;
-            this.comparator = comparator;
-        }
-
-        /**
-         * @param titleText title text pattern
-         */
-        public JPanelByBorderTitleFinder(String titleText) {
-            this(titleText, Operator.getDefaultStringComparator());
-        }
-
-        @Override
-        public boolean checkComponent(Component comp) {
-            assert EventQueue.isDispatchThread();
-            if (comp instanceof JPanel) {
-                return checkBorder(((JPanel) comp).getBorder());
-            }
-            return false;
-        }
-
-        public boolean checkBorder(Border border) {
-            if (border instanceof TitledBorder) {
-                String title = ((TitledBorder) border).getTitle();
-                return comparator.equals(title, titleText);
-            } else if (border instanceof CompoundBorder) {
-                CompoundBorder compoundBorder = (CompoundBorder) border;
-                return checkBorder(compoundBorder.getInsideBorder()) || checkBorder(compoundBorder.getOutsideBorder());
-            } else {
-                return false;
-            }
-        }
-
-        @Override
-        public String getDescription() {
-            return ("JPanel with border title text \"" + titleText + "\" with comparator " + comparator);
-        }
-    }
-
-    public static class ByClassSimpleNameChooser implements ComponentChooser {
-
-        private final String className;
-
-        public ByClassSimpleNameChooser(String className) {
-            this.className = className;
-        }
-
-        @Override
-        public boolean checkComponent(Component comp) {
-            return comp.getClass().getSimpleName().equals(className);
-        }
-
-        @Override
-        public String getDescription() {
-            return "Component with the simple class name of " + className;
-        }
-
-    }
-
-    public static class ByClassChooser implements ComponentChooser {
-
-        private final Class<?> clazz;
-
-        public ByClassChooser(Class<?> clazz) {
-            this.clazz = clazz;
-        }
-
-        @Override
-        public boolean checkComponent(Component comp) {
-            return comp.getClass().equals(clazz);
-        }
-
-        @Override
-        public String getDescription() {
-            return "Component with the class of " + clazz;
-        }
-
-    }
-
-    public static class ByToolTipChooser implements ComponentChooser {
-
-        private final String tooltip;
-
-        public ByToolTipChooser(String tooltip) {
-            if (tooltip == null) {
-                throw new NullPointerException("Tooltip cannot be null");
-            }
-            this.tooltip = tooltip;
-        }
-
-        @Override
-        public boolean checkComponent(Component comp) {
-            return (comp instanceof JComponent)
-                    ? tooltip.equals(((JComponent) comp).getToolTipText())
-                    : false;
-        }
-
-        @Override
-        public String getDescription() {
-            return "JComponent with the tooltip '" + tooltip + "'";
-        }
-
-    }
-
-    @SuppressWarnings(value = "unchecked")
-    public static <R, O extends Operator, S extends Component> R getUIValue(O operator, Function<S, R> getter) {
-        return operator.getQueueTool().invokeSmoothly(new QueueTool.QueueAction<R>("getting UI value through the queue using " + getter) {
-
-            @Override
-            public R launch() throws Exception {
-                return getter.apply((S) operator.getSource());
-            }
-        });
-    }
-}
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/button/ButtonDemo.java	Wed Jul 05 21:39:33 2017 +0200
@@ -36,6 +36,7 @@
 
 import com.sun.swingset3.DemoProperties;
 import com.sun.swingset3.demos.JHyperlink;
+import java.lang.reflect.InvocationTargetException;
 
 /**
  *
@@ -210,10 +211,10 @@
         return panel;
     }
 
-    public static void main(String args[]) {
+    public static void main(String args[]) throws InterruptedException, InvocationTargetException {
         final ButtonDemo buttonDemo = new ButtonDemo();
 
-        javax.swing.SwingUtilities.invokeLater(() -> {
+        javax.swing.SwingUtilities.invokeAndWait(() -> {
             JFrame frame = new JFrame(DEMO_TITLE);
             frame.add(buttonDemo);
             frame.pack();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tabbedpane/TabbedPaneDemo.java	Wed Jul 05 21:39:33 2017 +0200
@@ -91,7 +91,6 @@
     public static void main(String[] args) {
         JFrame frame = new JFrame(DEMO_TITLE);
 
-        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.getContentPane().add(new TabbedPaneDemo());
         frame.setPreferredSize(new Dimension(800, 600));
         frame.pack();
@@ -205,7 +204,9 @@
         }
 
         public void go() {
-            animator = new javax.swing.Timer(22 + 22 + 22, this);
+            if (animator == null) {
+                animator = new javax.swing.Timer(22 + 22 + 22, this);
+            }
             animator.start();
         }
 
@@ -247,7 +248,7 @@
 
         @Override
         public void actionPerformed(ActionEvent e) {
-            if (isVisible()) {
+            if (isShowing()) {
                 repaint();
             } else {
                 animator.stop();
--- a/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/window/WindowDemo.java	Wed Jul 05 21:39:33 2017 +0200
@@ -31,6 +31,7 @@
 
 import com.sun.swingset3.DemoProperties;
 import com.sun.swingset3.demos.DemoUtilities;
+import java.lang.reflect.InvocationTargetException;
 
 /**
  * @author aim
@@ -145,8 +146,8 @@
         }
     }
 
-    public static void main(String args[]) {
-        EventQueue.invokeLater(() -> {
+    public static void main(String args[]) throws InterruptedException, InvocationTargetException {
+        EventQueue.invokeAndWait(() -> {
             JFrame frame = new JFrame();
             WindowDemo demo = new WindowDemo();
             frame.add(demo);
--- a/jdk/test/sun/java2d/OpenGL/GradientPaints.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sun/java2d/OpenGL/GradientPaints.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * 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,11 +23,11 @@
 
 /*
  * @test
- * @bug 6521533 6525997
+ * @bug 6521533 6525997 7102282
  * @summary Verifies that the OGL-accelerated codepaths for GradientPaint,
  * LinearGradientPaint, and RadialGradientPaint produce results that are
  * sufficiently close to those produced by the software codepaths.
- * @run main/othervm -Dsun.java2d.opengl=True GradientPaints
+ * @run main/othervm -Dsun.java2d.uiScale=1 -Dsun.java2d.opengl=True GradientPaints
  * @author campbelc
  */
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/rmi/TEST.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,1 @@
+modules = java.rmi
--- a/jdk/test/sun/security/tools/jarsigner/Warning.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sun/security/tools/jarsigner/Warning.java	Wed Jul 05 21:39:33 2017 +0200
@@ -89,7 +89,7 @@
         issueCert("c");
         run("jarsigner", "a.jar c")
                 .shouldContain("chain is not validated. " +
-                        "Reason: algorithm constraints check failed");
+                        "Reason: Algorithm constraints check failed");
 
         recreateJar();
 
--- a/jdk/test/sun/util/logging/PlatformLoggerTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -197,7 +197,7 @@
         // create a brand new java logger
         Logger javaLogger = sun.util.logging.internal.LoggingProviderImpl.getLogManagerAccess()
                      .demandLoggerFor(LogManager.getLogManager(),
-                          logger.getName()+"."+level.getName(), Thread.class);
+                          logger.getName()+"."+level.getName(), Thread.class.getModule());
 
         // Set a non standard java.util.logging.Level on the java logger
         // (except for OFF & ALL - which will remain unchanged)
--- a/langtools/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -358,3 +358,4 @@
 4e87682893e662421af10a62d29ae822ce0fea04 jdk-9+113
 cba09a2e6ae969b029783eb59bb01017b78f8eef jdk-9+114
 31c8b18fdc5b94a2ddd5ea0694f350a2c907e9f7 jdk-9+115
+3e3553ee39d9e081573bc7c88a252214a3152763 jdk-9+116
--- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java	Wed Jul 05 21:39:33 2017 +0200
@@ -123,7 +123,9 @@
     private static <T> T getSystemTool(Class<T> clazz, String moduleName, String className) {
         if (useLegacy) {
             try {
-                return Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+                @SuppressWarnings("deprecation")
+                T result = Class.forName(className, true, ClassLoader.getSystemClassLoader()).asSubclass(clazz).newInstance();
+                return result;
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Wed Jul 05 21:39:33 2017 +0200
@@ -698,7 +698,7 @@
      */
     public boolean packageExists(ModuleSymbol msym, Name fullname) {
         Assert.checkNonNull(msym);
-        return enterPackage(msym, fullname).exists();
+        return lookupPackage(msym, fullname).exists();
     }
 
     /** Make a package, given its fully qualified name.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -53,10 +53,6 @@
 public class MemberEnter extends JCTree.Visitor {
     protected static final Context.Key<MemberEnter> memberEnterKey = new Context.Key<>();
 
-    /** A switch to determine whether we check for package/class conflicts
-     */
-    final static boolean checkClash = true;
-
     private final Enter enter;
     private final Log log;
     private final Check chk;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -826,7 +826,7 @@
         }
         public void visitClass(Attribute.Class clazz) {
             databuf.appendByte('c');
-            databuf.appendChar(pool.put(typeSig(clazz.classType)));
+            databuf.appendChar(pool.put(typeSig(types.erasure(clazz.classType))));
         }
         public void visitCompound(Attribute.Compound compound) {
             databuf.appendByte('@');
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1086,17 +1086,19 @@
                 genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
                 code.resolve(loopEnv.info.cont);
                 genStats(step, loopEnv);
-                CondItem c;
-                if (cond != null) {
-                    code.statBegin(cond.pos);
+                if (code.isAlive()) {
+                    CondItem c;
+                    if (cond != null) {
+                        code.statBegin(cond.pos);
+                        Assert.check(code.state.stacksize == 0);
+                        c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
+                    } else {
+                        c = items.makeCondItem(goto_);
+                    }
+                    code.resolve(c.jumpTrue(), startpc);
                     Assert.check(code.state.stacksize == 0);
-                    c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER);
-                } else {
-                    c = items.makeCondItem(goto_);
+                    code.resolve(c.falseJumps);
                 }
-                code.resolve(c.jumpTrue(), startpc);
-                Assert.check(code.state.stacksize == 0);
-                code.resolve(c.falseJumps);
             }
             Chain exit = loopEnv.info.exit;
             if (exit != null) {
@@ -1647,6 +1649,7 @@
 
     public void visitConditional(JCConditional tree) {
         Chain thenExit = null;
+        code.statBegin(tree.cond.pos);
         CondItem c = genCond(tree.cond, CRT_FLOW_CONTROLLER);
         Chain elseChain = c.jumpFalse();
         if (!c.isFalse()) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java	Wed Jul 05 21:39:33 2017 +0200
@@ -282,6 +282,7 @@
 
         if (options.isSet(XPRINT)) {
             try {
+                @SuppressWarnings("deprecation")
                 Processor processor = PrintingProcessor.class.newInstance();
                 processorIterator = List.of(processor).iterator();
             } catch (Throwable t) {
@@ -549,8 +550,9 @@
                         try {
                             Class<?> processorClass = processorCL.loadClass(processorName);
                             ensureReadable(processorClass);
-                            processor =
-                                (Processor) (processorClass.newInstance());
+                            @SuppressWarnings("deprecation")
+                            Object tmp = processorClass.newInstance();
+                            processor = (Processor) tmp;
                         } catch (ClassNotFoundException cnfe) {
                             log.error("proc.processor.not.found", processorName);
                             return false;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Option.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -151,6 +151,7 @@
             // Construct transformer
             try {
                 Class<?> trCls = Class.forName(classname);
+                @SuppressWarnings("deprecation")
                 Transformer transformer = (Transformer) trCls.newInstance();
                 transformer.setExtra(extra);
                 helper.addTransformer(suffix, transformer);
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -1,4 +1,4 @@
-doclet.build_version=Standard Doclet version {0}
+doclet.build_version=Standard Doclet (Old) version {0}
 doclet.Contents=Contents
 doclet.Overview=Overview
 doclet.Window_Overview=Overview List
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -242,7 +242,6 @@
             }
 
             customTagClass = tagClassLoader.loadClass(classname);
-            ensureReadable(customTagClass);
 
             Method meth = customTagClass.getMethod("register",
                                                    Map.class);
@@ -270,27 +269,6 @@
     }
 
     /**
-     * Ensures that the module of the given class is readable to this
-     * module.
-     * @param targetClass class in module to be made readable
-     */
-    private void ensureReadable(Class<?> targetClass) {
-        try {
-            Method getModuleMethod = Class.class.getMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(this.getClass());
-            Object targetModule = getModuleMethod.invoke(targetClass);
-
-            Class<?> moduleClass = getModuleMethod.getReturnType();
-            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
-            addReadsMethod.invoke(thisModule, targetModule);
-        } catch (NoSuchMethodException e) {
-            // ignore
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-    }
-
-    /**
      * Export javadoc internal API to the unnamed module for a classloader.
      * This is to support continued use of existing non-standard doclets that
      * use the internal toolkit API and related classes.
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocletInvoker.java	Wed Jul 05 21:39:33 2017 +0200
@@ -102,7 +102,6 @@
         this.apiMode = apiMode;
         this.exportInternalAPI = exportInternalAPI; // for backdoor use by standard doclet for taglets
 
-        ensureReadable(docletClass);
         // this may not be soon enough if the class has already been loaded
         if (exportInternalAPI) {
             exportInternalAPI(docletClass.getClassLoader());
@@ -149,8 +148,6 @@
             messager.exit();
         }
         docletClass = dc;
-
-        ensureReadable(docletClass);
     }
 
     /*
@@ -362,27 +359,6 @@
     }
 
     /**
-     * Ensures that the module of the given class is readable to this
-     * module.
-     * @param targetClass class in module to be made readable
-     */
-    private void ensureReadable(Class<?> targetClass) {
-        try {
-            Method getModuleMethod = Class.class.getMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(this.getClass());
-            Object targetModule = getModuleMethod.invoke(targetClass);
-
-            Class<?> moduleClass = getModuleMethod.getReturnType();
-            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
-            addReadsMethod.invoke(thisModule, targetModule);
-        } catch (NoSuchMethodException e) {
-            // ignore
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-    }
-
-    /**
      * Export javadoc internal API to the unnamed module for a classloader.
      * This is to support continued use of existing non-standard doclets that
      * use the internal toolkit API and related classes.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -168,6 +168,21 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public void addModuleDescription(Content moduleContentTree) {
+        if (!utils.getBody(mdle).isEmpty()) {
+            Content tree = configuration.allowTag(HtmlTag.SECTION) ? HtmlTree.SECTION() : moduleContentTree;
+            tree.addContent(HtmlConstants.START_OF_MODULE_DESCRIPTION);
+            tree.addContent(getMarkerAnchor(SectionName.MODULE_DESCRIPTION));
+            addInlineComment(mdle, tree);
+            if (configuration.allowTag(HtmlTag.SECTION)) {
+                moduleContentTree.addContent(tree);
+            }
+        }
+    }
+
+    /**
      * Adds list of packages in the package summary table. Generate link to each package.
      *
      * @param packages Packages to which link is to be generated
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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
@@ -53,6 +53,7 @@
     METHOD_DETAIL("method.detail"),
     METHODS_INHERITANCE("methods.inherited.from.class."),
     METHOD_SUMMARY("method.summary"),
+    MODULE_DESCRIPTION("module.description"),
     NAVBAR_BOTTOM("navbar.bottom"),
     NAVBAR_BOTTOM_FIRSTROW("navbar.bottom.firstrow"),
     NAVBAR_TOP("navbar.top"),
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -64,6 +64,12 @@
             new Comment("======== END OF BOTTOM NAVBAR =======");
 
     /**
+     * Marker to identify start of module description.
+     */
+    public static final Content START_OF_MODULE_DESCRIPTION =
+            new Comment("============ MODULE DESCRIPTION ===========");
+
+    /**
      * Marker to identify start of class data.
      */
     public static final Content START_OF_CLASS_DATA =
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -1,4 +1,4 @@
-doclet.build_version=Standard Doclet (Next) version {0}
+doclet.build_version=Standard Doclet version {0}
 doclet.Contents=Contents
 doclet.Overview=Overview
 doclet.Window_Overview=Overview List
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -74,6 +74,14 @@
     public abstract Content getSummaryTree(Content summaryContentTree);
 
     /**
+     * Adds the module description.
+     *
+     * @param moduleContentTree the content tree to which the module description
+     *                           will be added
+     */
+    public abstract void addModuleDescription(Content moduleContentTree);
+
+    /**
      * Adds the table of packages to the documentation tree.
      *
      * @param packages the set of packages that should be added.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -185,4 +185,17 @@
                     packageTableSummary, summaryContentTree);
         }
     }
+
+    /**
+     * Build the description for the module.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param moduleContentTree the tree to which the module description will
+     *                           be added
+     */
+    public void buildModuleDescription(XMLNode node, Content moduleContentTree) {
+        if (!configuration.nocomment) {
+            moduleWriter.addModuleDescription(moduleContentTree);
+        }
+    }
 }
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml	Wed Jul 05 21:39:33 2017 +0200
@@ -30,6 +30,7 @@
 
     <ModuleDoc>
         <Content>
+            <ModuleDescription/>
             <Summary>
                 <PackageSummary/>
             </Summary>
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -246,7 +246,7 @@
             }
             tagClassLoader = fileManager.getClassLoader(TAGLET_PATH);
             Class<?> customTagClass = tagClassLoader.loadClass(classname);
-            ensureReadable(customTagClass);
+            @SuppressWarnings("deprecation")
             Object instance = customTagClass.newInstance();
             Taglet newLegacy = new UserTaglet((jdk.javadoc.doclet.taglet.Taglet)instance);
             String tname = newLegacy.getName();
@@ -262,27 +262,6 @@
     }
 
     /**
-     * Ensures that the module of the given class is readable to this
-     * module.
-     * @param targetClass class in module to be made readable
-     */
-    private void ensureReadable(Class<?> targetClass) {
-        try {
-            Method getModuleMethod = Class.class.getMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(this.getClass());
-            Object targetModule = getModuleMethod.invoke(targetClass);
-
-            Class<?> moduleClass = getModuleMethod.getReturnType();
-            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
-            addReadsMethod.invoke(thisModule, targetModule);
-        } catch (NoSuchMethodException e) {
-            // ignore
-        } catch (Exception e) {
-            throw new InternalError(e.toString());
-        }
-    }
-
-    /**
      * Add a new <code>SimpleTaglet</code>.  If this tag already exists
      * and the header passed as an argument is null, move tag to the back of the
      * list. If this tag already exists and the header passed as an argument is
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -73,6 +73,7 @@
 
     private final Configuration configuration;
     private final Utils utils;
+    private final Comparator<Element> comparator;
 
     /**
      * Constructor. Build the index map.
@@ -106,6 +107,9 @@
         this.classesOnly = classesOnly;
         this.javafx = configuration.javafx;
         this.indexmap = new TreeMap<>();
+        comparator = classesOnly
+                ? utils.makeAllClassesComparator()
+                : utils.makeIndexUseComparator();
         buildIndexMap(configuration.root);
     }
 
@@ -175,7 +179,7 @@
                           Character.toUpperCase(name.charAt(0));
                 Character unicode = ch;
                 SortedSet<Element> list = indexmap.computeIfAbsent(unicode,
-                        c -> new TreeSet<>(utils.makeIndexUseComparator()));
+                        c -> new TreeSet<>(comparator));
                 list.add(element);
             }
         }
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1628,6 +1628,7 @@
 
     /**
      * Comparator for ModuleElements, simply compares the fully qualified names
+     * @return a Comparator
      */
     public Comparator<Element> makeModuleComparator() {
         return new Utils.ElementComparator<Element>() {
@@ -1639,7 +1640,28 @@
     }
 
     /**
-     * Comparator for PackageElements, simply compares the fully qualified names
+     * Returns a Comparator for all classes, compares the simple names of
+     * TypeElement, if equal then the fully qualified names.
+     *
+     * @return Comparator
+     */
+    public Comparator<Element> makeAllClassesComparator() {
+        return new Utils.ElementComparator<Element>() {
+            @Override
+            public int compare(Element e1, Element e2) {
+                int result =  compareNames(e1, e2);
+                if (result == 0)
+                    result =  compareFullyQualifiedNames(e1, e2);
+
+                return result;
+            }
+        };
+    }
+
+    /**
+     * Returns a Comparator for packages, by comparing the fully qualified names.
+     *
+     * @return a Comparator
      */
     public Comparator<Element> makePackageComparator() {
         return new Utils.ElementComparator<Element>() {
@@ -1650,6 +1672,10 @@
         };
     }
 
+    /**
+     * Returns a Comparator for SerialFieldTree.
+     * @return a Comparator
+     */
     public Comparator<SerialFieldTree> makeSerialFieldTreeComparator() {
         return (SerialFieldTree o1, SerialFieldTree o2) -> {
             String s1 = o1.getName().toString();
@@ -1659,18 +1685,19 @@
     }
 
     /**
-     * Comparator for General Purpose
-     * @return a ElementComparatorForClassUse
+     * Returns a general purpose comparator.
+     * @return a Comparator
      */
     public Comparator<Element> makeGeneralPurposeComparator() {
         return makeClassUseComparator();
     }
 
     /**
-     * A Comparator for Overrides and Implements use used on ExecutableElements
-     * compares the name first, then compares the SimpleName of the enclosing
-     * class and the FullyQualifiedName of the enclosing class.
-     * @return
+     * Returns a Comparator for overrides and implements,
+     * used primarily on methods, compares the name first,
+     * then compares the simple names of the enclosing
+     * TypeElement and the fully qualified name of the enclosing TypeElement.
+     * @return a Comparator
      */
     public Comparator<Element> makeOverrideUseComparator() {
         return new Utils.ElementComparator<Element>() {
@@ -1696,21 +1723,24 @@
     }
 
     /**
-     * A comparator for index file presentations, and are sorted as follows:
+     * Returns a Comparator for index file presentations, and are sorted as follows.
+     *  If comparing packages then simply compare the qualified names, otherwise
      *  1. sort on simple names of entities
      *  2. if equal, then compare the ElementKind ex: Package, Interface etc.
      *  3a. if equal and if the type is of ExecutableElement(Constructor, Methods),
      *      a case insensitive comparison of parameter the type signatures
      *  3b. if equal, case sensitive comparison of the type signatures
      *  4. finally, if equal, compare the FQNs of the entities
+     * Iff comparing packages then simply sort on qualified names.
      * @return a comparator for index file use
      */
     public Comparator<Element> makeIndexUseComparator() {
         return new Utils.ElementComparator<Element>() {
             /**
-             * Compare two given elements, first sort on names, then on the kinds,
-             * then on the parameters only if the type is an instance of ExecutableElement,
-             * the parameters are compared and finally the fully qualified names.
+             * Compare two given elements, if comparing two packages, return the
+             * comparison of FullyQualifiedName, first sort on names, then on the
+             * kinds, then on the parameters only if the type is an ExecutableElement,
+             * the parameters are compared and finally the qualified names.
              *
              * @param e1 - an element.
              * @param e2 - an element.
@@ -1719,10 +1749,7 @@
              */
             @Override
             public int compare(Element e1, Element e2) {
-                int result = compareElementTypeKinds(e1, e2);
-                if (result != 0) {
-                    return result;
-                }
+                int result = 0;
                 if (isPackage(e1) && isPackage(e2)) {
                     return compareFullyQualifiedNames(e1, e2);
                 }
@@ -1730,6 +1757,10 @@
                 if (result != 0) {
                     return result;
                 }
+                result = compareElementTypeKinds(e1, e2);
+                if (result != 0) {
+                    return result;
+                }
                 if (hasParameters(e1)) {
                     List<? extends VariableElement> parameters1 = ((ExecutableElement)e1).getParameters();
                     List<? extends VariableElement> parameters2 = ((ExecutableElement)e2).getParameters();
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/DocEnv.java	Wed Jul 05 21:39:33 2017 +0200
@@ -550,7 +550,7 @@
         // Messager should be replaced by a more general
         // compilation environment.  This can probably
         // subsume DocEnv as well.
-        messager.exit();
+        throw new Messager.ExitJavadoc();
     }
 
     /**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Main.java	Wed Jul 05 21:39:33 2017 +0200
@@ -59,13 +59,6 @@
      * @return The return code.
      */
     public static int execute(String... args) {
-        // NOTE: the following should be removed when the old doclet
-        // is removed.
-        if (args != null && args.length > 0 && "-Xold".equals(args[0])) {
-            String[] nargs = new String[args.length - 1];
-            System.arraycopy(args, 1, nargs, 0, nargs.length);
-            return com.sun.tools.javadoc.Main.execute(nargs);
-        }
         Start jdoc = new Start();
         return jdoc.begin(args);
     }
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Messager.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -139,7 +139,7 @@
         }
     }
 
-    public class ExitJavadoc extends Error {
+    public static class ExitJavadoc extends Error {
         private static final long serialVersionUID = 0;
     }
 
@@ -416,15 +416,6 @@
         }
     }
 
-    /**
-     * Force program exit, e.g., from a fatal error.
-     * <p>
-     * TODO: This method does not really belong here.
-     */
-    public void exit() {
-        throw new ExitJavadoc();
-    }
-
     private void report(DiagnosticType type, String pos, String msg) {
         switch (type) {
             case ERROR:
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java	Wed Jul 05 21:39:33 2017 +0200
@@ -66,6 +66,7 @@
 import jdk.javadoc.doclet.DocletEnvironment;
 
 import static com.sun.tools.javac.main.Option.*;
+
 /**
  * Main program of Javadoc.
  * Previously named "Main".
@@ -79,6 +80,12 @@
  * @author Neal Gafter (rewrite)
  */
 public class Start extends ToolOption.Helper {
+
+    private static final Class<?> OldStdDoclet =
+            com.sun.tools.doclets.standard.Standard.class;
+
+    private static final Class<?> StdDoclet =
+            jdk.javadoc.internal.doclets.standard.Standard.class;
     /** Context for this invocation. */
     private final Context context;
 
@@ -193,18 +200,26 @@
         if (foot != null)
             messager.notice(foot);
 
-        if (exit) exit();
+        if (exit)
+            throw new Messager.ExitJavadoc();
     }
 
+
     /**
-     * Exit
-     */
-    private void exit() {
-        messager.exit();
-    }
-
-    /**
-     * Main program - external wrapper
+     * Main program - external wrapper. In order to maintain backward
+     * CLI  compatibility, we dispatch to the old tool or the old doclet's
+     * Start mechanism, based on the options present on the command line
+     * with the following precedence:
+     *   1. presence of -Xold, dispatch to old tool
+     *   2. doclet variant, if old, dispatch to old Start
+     *   3. taglet variant, if old, dispatch to old Start
+     *
+     * Thus the presence of -Xold switches the tool, soon after command files
+     * if any, are expanded, this is performed here, noting that the messager
+     * is available at this point in time.
+     * The doclet/taglet tests are performed in the begin method, further on,
+     * this is to minimize argument processing and most importantly the impact
+     * of class loader creation, needed to detect the doclet/taglet class variants.
      */
     int begin(String... argv) {
         // Preprocess @file arguments
@@ -212,14 +227,18 @@
             argv = CommandLine.parse(argv);
         } catch (FileNotFoundException e) {
             messager.error("main.cant.read", e.getMessage());
-            exit();
+            throw new Messager.ExitJavadoc();
         } catch (IOException e) {
             e.printStackTrace(System.err);
-            exit();
+            throw new Messager.ExitJavadoc();
         }
 
-        List<String> argList = Arrays.asList(argv);
-        boolean ok = begin(argList, Collections.<JavaFileObject> emptySet());
+        if (argv.length > 0 && "-Xold".equals(argv[0])) {
+            messager.warning("main.legacy_api");
+            String[] nargv = Arrays.copyOfRange(argv, 1, argv.length);
+            return com.sun.tools.javadoc.Main.execute(nargv);
+        }
+        boolean ok = begin(Arrays.asList(argv), Collections.<JavaFileObject> emptySet());
         return ok ? 0 : 1;
     }
 
@@ -231,11 +250,11 @@
         List<String> opts = new ArrayList<>();
         for (String opt: options)
             opts.add(opt);
+
         return begin(opts, fileObjects);
     }
 
     private boolean begin(List<String> options, Iterable<? extends JavaFileObject> fileObjects) {
-
         fileManager = context.get(JavaFileManager.class);
         if (fileManager == null) {
             JavacFileManager.preRegister(context);
@@ -244,20 +263,21 @@
                 ((BaseFileManager) fileManager).autoClose = true;
             }
         }
-        // locale and doclet needs to be determined first
+        // locale, doclet and maybe taglet, needs to be determined first
         docletClass = preProcess(fileManager, options);
-
         if (jdk.javadoc.doclet.Doclet.class.isAssignableFrom(docletClass)) {
             // no need to dispatch to old, safe to init now
             initMessager();
             messager.setLocale(locale);
             try {
-                doclet = (Doclet) docletClass.newInstance();
+                @SuppressWarnings("deprecation")
+                Object o = docletClass.newInstance();
+                doclet = (Doclet) o;
             } catch (InstantiationException | IllegalAccessException exc) {
                 exc.printStackTrace();
                 if (!apiMode) {
                     error("main.could_not_instantiate_class", docletClass);
-                    messager.exit();
+                    throw new Messager.ExitJavadoc();
                 }
                 throw new ClientCodeException(exc);
             }
@@ -267,6 +287,7 @@
                         = new com.sun.tools.javadoc.Start(context);
                 return ostart.begin(docletClass, options, fileObjects);
             }
+            warn("main.legacy_api");
             String[] array = options.toArray(new String[options.size()]);
             return com.sun.tools.javadoc.Main.execute(array) == 0;
         }
@@ -312,27 +333,6 @@
     }
 
     /**
-     * Ensures that the module of the given class is readable to this
-     * module.
-     * @param targetClass class in module to be made readable
-     */
-    private void ensureReadable(Class<?> targetClass) {
-        try {
-            Method getModuleMethod = Class.class.getMethod("getModule");
-            Object thisModule = getModuleMethod.invoke(this.getClass());
-            Object targetModule = getModuleMethod.invoke(targetClass);
-
-            Class<?> moduleClass = getModuleMethod.getReturnType();
-            Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
-            addReadsMethod.invoke(thisModule, targetModule);
-        } catch (NoSuchMethodException e) {
-            // ignore
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-    }
-
-    /**
      * Main program - internal
      */
     private boolean parseAndExecute(List<String> argList,
@@ -459,6 +459,11 @@
         String userDocletPath = null;
         String userDocletName = null;
 
+        // taglet specifying arguments, since tagletpath is a doclet
+        // functionality, assume they are repeated and inspect all.
+        List<File> userTagletPath = new ArrayList<>();
+        List<String> userTagletNames = new ArrayList<>();
+
         // Step 1: loop through the args, set locale early on, if found.
         for (int i = 0 ; i < argv.size() ; i++) {
             String arg = argv.get(i);
@@ -470,7 +475,7 @@
                 oneArg(argv, i++);
                 if (userDocletName != null) {
                     usageError("main.more_than_one_doclet_specified_0_and_1",
-                               userDocletName, argv.get(i));
+                            userDocletName, argv.get(i));
                 }
                 if (docletName != null) {
                     usageError("main.more_than_one_doclet_specified_0_and_1",
@@ -484,13 +489,20 @@
                 } else {
                     userDocletPath += File.pathSeparator + argv.get(i);
                 }
+            } else if ("-taglet".equals(arg)) {
+                userTagletNames.add(argv.get(i + 1));
+            } else if ("-tagletpath".equals(arg)) {
+                for (String pathname : argv.get(i + 1).split(File.pathSeparator)) {
+                    userTagletPath.add(new File(pathname));
+                }
             }
         }
-        // Step 2: a doclet has already been provided,
-        // nothing more to do.
+
+        // Step 2: a doclet is provided, nothing more to do.
         if (docletClass != null) {
             return docletClass;
         }
+
         // Step 3: doclet name specified ? if so find a ClassLoader,
         // and load it.
         if (userDocletName != null) {
@@ -506,38 +518,78 @@
                     try {
                         ((StandardJavaFileManager)fileManager).setLocation(DOCLET_PATH, paths);
                     } catch (IOException ioe) {
-                        panic("main.doclet_no_classloader_found", ioe);
-                        return null; // keep compiler happy
+                        error("main.doclet_could_not_set_location", paths);
+                        throw new Messager.ExitJavadoc();
                     }
                 }
                 cl = fileManager.getClassLoader(DOCLET_PATH);
                 if (cl == null) {
                     // despite doclet specified on cmdline no classloader found!
-                    panic("main.doclet_no_classloader_found", userDocletName);
-                    return null; // keep compiler happy
-                }
-                try {
-                    Class<?> klass = cl.loadClass(userDocletName);
-                    ensureReadable(klass);
-                    return klass;
-                } catch (ClassNotFoundException cnfe) {
-                    panic("main.doclet_class_not_found", userDocletName);
-                    return null; // keep compiler happy
+                    error("main.doclet_no_classloader_found", userDocletName);
+                    throw new Messager.ExitJavadoc();
                 }
             }
+            try {
+                Class<?> klass = cl.loadClass(userDocletName);
+                return klass;
+            } catch (ClassNotFoundException cnfe) {
+                error("main.doclet_class_not_found", userDocletName);
+                throw new Messager.ExitJavadoc();
+            }
         }
-        // Step 4: we have a doclet, try loading it, otherwise
-        // return back the standard doclet
+
+        // Step 4: we have a doclet, try loading it
         if (docletName != null) {
             try {
                 return Class.forName(docletName, true, getClass().getClassLoader());
             } catch (ClassNotFoundException cnfe) {
-                panic("main.doclet_class_not_found", userDocletName);
-                return null; // happy compiler, should not happen
+                error("main.doclet_class_not_found", userDocletName);
+                throw new Messager.ExitJavadoc();
             }
-        } else {
-            return jdk.javadoc.internal.doclets.standard.Standard.class;
+        }
+
+        // Step 5: we don't have a doclet specified, do we have taglets ?
+        if (!userTagletNames.isEmpty() && hasOldTaglet(userTagletNames, userTagletPath)) {
+            // found a bogey, return the old doclet
+            return OldStdDoclet;
         }
+
+        // finally
+        return StdDoclet;
+    }
+
+    /*
+     * This method returns true iff it finds a legacy taglet, but for
+     * all other conditions including errors it returns false, allowing
+     * nature to take its own course.
+     */
+    private boolean hasOldTaglet(List<String> tagletNames, List<File> tagletPaths) {
+        if (!fileManager.hasLocation(TAGLET_PATH)) {
+            try {
+                ((StandardJavaFileManager) fileManager).setLocation(TAGLET_PATH, tagletPaths);
+            } catch (IOException ioe) {
+                error("main.doclet_could_not_set_location", tagletPaths);
+                throw new Messager.ExitJavadoc();
+            }
+        }
+        ClassLoader cl = fileManager.getClassLoader(TAGLET_PATH);
+        if (cl == null) {
+            // no classloader found!
+            error("main.doclet_no_classloader_found", tagletNames.get(0));
+            throw new Messager.ExitJavadoc();
+        }
+        for (String tagletName : tagletNames) {
+            try {
+                Class<?> klass = cl.loadClass(tagletName);
+                if (com.sun.tools.doclets.Taglet.class.isAssignableFrom(klass)) {
+                    return true;
+                }
+            } catch (ClassNotFoundException cnfe) {
+                error("main.doclet_class_not_found", tagletName);
+                throw new Messager.ExitJavadoc();
+            }
+        }
+        return false;
     }
 
     private void parseArgs(List<String> args, List<String> javaNames) {
@@ -595,14 +647,12 @@
         usage(true);
     }
 
-    // a terminal call, will not return
-    void panic(String key, Object... args) {
-        error(key, args);
-        messager.exit();
+    void error(String key, Object... args) {
+        messager.error(key, args);
     }
 
-    void error(String key, Object... args) {
-        messager.error(key, args);
+    void warn(String key, Object... args)  {
+        messager.warning(key, args);
     }
 
     /**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -73,7 +73,8 @@
 \                                   given module. <other-module> may be ALL-UNNAMED to require\n\
 \                                   the unnamed module.\n\
 \  -Xmodule:<module-name>           Specify a module to which the classes being compiled belong.\n\
-\  -Xpatch:<path>                   Specify location of module class files to patch\n  
+\  -Xpatch:<path>                   Specify location of module class files to patch\n\
+\  -Xold                            Invoke the legacy javadoc tool\n
 
 main.Xusage.foot=\
 These options are non-standard and subject to change without notice.
@@ -96,6 +97,7 @@
 such as -J-Xmx32m.
 main.done_in=[done in {0} ms]
 main.more_than_one_doclet_specified_0_and_1=More than one doclet specified ({0} and {1}).
+main.doclet_could_not_set_location=Could not set location for {0}
 main.doclet_no_classloader_found=Could not obtain classloader to load {0}
 main.could_not_instantiate_class=Could not instantiate class {0}
 main.doclet_class_not_found=Cannot find doclet class {0}
@@ -109,10 +111,15 @@
 main.unsupported.release.version=release version {0} not supported
 main.release.not.standard.file.manager=-release option specified, but the provided JavaFileManager is not a StandardJavaFileManager.
 main.unknown.error=an unknown error has occurred
+main.legacy_api=The old Doclet and Taglet APIs in the packages\n\
+    com.sun.javadoc, com.sun.tools.doclets and their implementations\n\
+    are planned to be removed in a future JDK release. These\n\
+    components have been superseded by the new APIs in jdk.javadoc.doclet.\n\
+    Users are strongly recommended to migrate to the new APIs.\n
+
 javadoc.class_not_found=Class {0} not found.
 javadoc.error=error
 javadoc.warning=warning
-
 javadoc.error.msg={0}: error - {1}
 javadoc.warning.msg={0}: warning - {1}
 javadoc.note.msg = {1}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -35,6 +35,7 @@
 class ArgTokenizer {
 
     private final String str;
+    private final String prefix;
     private final int length;
     private int next = 0;
     private char buf[] = new char[20];
@@ -49,7 +50,12 @@
     private boolean isQuoted = false;
 
     ArgTokenizer(String arg) {
+        this("", arg);
+    }
+
+    ArgTokenizer(String prefix, String arg) {
         this.str = arg;
+        this.prefix = prefix;
         this.length = arg.length();
         quoteChar('"');
         quoteChar('\'');
@@ -88,7 +94,7 @@
     }
 
     String whole() {
-        return str;
+        return prefix + str;
     }
 
     void mark() {
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java	Wed Jul 05 21:39:33 2017 +0200
@@ -95,20 +95,20 @@
         return mode.getContinuationPrompt(nextId);
     }
 
-    public boolean setFeedback(JShellTool tool, ArgTokenizer at) {
-        return new Setter(tool, at).setFeedback();
+    public boolean setFeedback(MessageHandler messageHandler, ArgTokenizer at) {
+        return new Setter(messageHandler, at).setFeedback();
     }
 
-    public boolean setFormat(JShellTool tool, ArgTokenizer at) {
-        return new Setter(tool, at).setFormat();
+    public boolean setFormat(MessageHandler messageHandler, ArgTokenizer at) {
+        return new Setter(messageHandler, at).setFormat();
     }
 
-    public boolean setNewMode(JShellTool tool, ArgTokenizer at) {
-        return new Setter(tool, at).setNewMode();
+    public boolean setNewMode(MessageHandler messageHandler, ArgTokenizer at) {
+        return new Setter(messageHandler, at).setNewMode();
     }
 
-    public boolean setPrompt(JShellTool tool, ArgTokenizer at) {
-        return new Setter(tool, at).setPrompt();
+    public boolean setPrompt(MessageHandler messageHandler, ArgTokenizer at) {
+        return new Setter(messageHandler, at).setPrompt();
     }
 
     {
@@ -529,26 +529,26 @@
     private class Setter {
 
         private final ArgTokenizer at;
-        private final JShellTool tool;
+        private final MessageHandler messageHandler;
         boolean valid = true;
 
-        Setter(JShellTool tool, ArgTokenizer at) {
-            this.tool = tool;
+        Setter(MessageHandler messageHandler, ArgTokenizer at) {
+            this.messageHandler = messageHandler;
             this.at = at;
         }
 
         void fluff(String format, Object... args) {
-            tool.fluff(format, args);
+            messageHandler.fluff(format, args);
         }
 
-        void fluffmsg(String format, Object... args) {
-            tool.fluffmsg(format, args);
+        void fluffmsg(String messageKey, Object... args) {
+            messageHandler.fluffmsg(messageKey, args);
         }
 
         void errorat(String messageKey, Object... args) {
             Object[] a2 = Arrays.copyOf(args, args.length + 2);
-            a2[args.length] = "/set " + at.whole();
-            tool.errormsg(messageKey, a2);
+            a2[args.length] = at.whole();
+            messageHandler.errormsg(messageKey, a2);
         }
 
         // For /set prompt <mode> "<prompt>" "<continuation-prompt>"
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Wed Jul 05 21:39:33 2017 +0200
@@ -108,7 +108,7 @@
  * Command line REPL tool for Java using the JShell API.
  * @author Robert Field
  */
-public class JShellTool {
+public class JShellTool implements MessageHandler {
 
     private static final String LINE_SEP = System.getProperty("line.separator");
     private static final Pattern LINEBREAK = Pattern.compile("\\R");
@@ -166,6 +166,8 @@
     private boolean regenerateOnDeath = true;
     private boolean live = false;
     private boolean feedbackInitialized = false;
+    private String initialMode = null;
+    private List<String> remoteVMOptions = new ArrayList<>();
 
     SourceCodeAnalysis analysis;
     JShell state = null;
@@ -256,7 +258,8 @@
      * @param format printf format
      * @param args printf args
      */
-    void fluff(String format, Object... args) {
+    @Override
+    public void fluff(String format, Object... args) {
         if (feedback.shouldDisplayCommandFluff() && interactive()) {
             hard(format, args);
         }
@@ -362,7 +365,8 @@
      * @param key the resource key
      * @param args
      */
-    void errormsg(String key, Object... args) {
+    @Override
+    public void errormsg(String key, Object... args) {
         cmdout.println(prefix(messageFormat(key, args), feedback.getErrorPre()));
     }
 
@@ -383,7 +387,8 @@
      * @param key the resource key
      * @param args
      */
-    void fluffmsg(String key, Object... args) {
+    @Override
+    public void fluffmsg(String key, Object... args) {
         if (feedback.shouldDisplayCommandFluff() && interactive()) {
             hardmsg(key, args);
         }
@@ -512,6 +517,23 @@
                     case "-fullversion":
                         cmdout.printf("jshell %s\n", fullVersion());
                         return null;
+                    case "-feedback":
+                        if (ai.hasNext()) {
+                            initialMode = ai.next();
+                        } else {
+                            startmsg("jshell.err.opt.feedback.arg");
+                            return null;
+                        }
+                        break;
+                    case "-q":
+                        initialMode = "concise";
+                        break;
+                    case "-qq":
+                        initialMode = "silent";
+                        break;
+                    case "-v":
+                        initialMode = "verbose";
+                        break;
                     case "-startup":
                         if (cmdlineStartup != null) {
                             startmsg("jshell.err.opt.startup.conflict");
@@ -530,6 +552,10 @@
                         cmdlineStartup = "";
                         break;
                     default:
+                        if (arg.startsWith("-R")) {
+                            remoteVMOptions.add(arg.substring(2));
+                            break;
+                        }
                         startmsg("jshell.err.opt.unknown", arg);
                         printUsage();
                         return null;
@@ -567,6 +593,7 @@
                 .idGenerator((sn, i) -> (currentNameSpace == startNamespace || state.status(sn).isActive)
                         ? currentNameSpace.tid(sn)
                         : errorNamespace.tid(sn))
+                .remoteVMOptions(remoteVMOptions.toArray(new String[remoteVMOptions.size()]))
                 .build();
         shutdownSubscription = state.onShutdown((JShell deadState) -> {
             if (deadState == state) {
@@ -596,6 +623,26 @@
             start = cmdlineStartup;
         }
         startUpRun(start);
+        if (initialMode != null) {
+            MessageHandler mh = new MessageHandler() {
+                @Override
+                public void fluff(String format, Object... args) {
+                }
+
+                @Override
+                public void fluffmsg(String messageKey, Object... args) {
+                }
+
+                @Override
+                public void errormsg(String messageKey, Object... args) {
+                    startmsg(messageKey, args);
+                }
+            };
+            if (!feedback.setFeedback(mh, new ArgTokenizer("-feedback ", initialMode))) {
+                regenerateOnDeath = false;
+            }
+            initialMode = null;
+        }
         currentNameSpace = mainNamespace;
     }
     //where
@@ -1050,7 +1097,7 @@
         "format", "feedback", "newmode", "prompt", "editor", "start"};
 
     final boolean cmdSet(String arg) {
-        ArgTokenizer at = new ArgTokenizer(arg.trim());
+        ArgTokenizer at = new ArgTokenizer("/set ", arg.trim());
         String which = setSubCommand(at);
         if (which == null) {
             return false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/MessageHandler.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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;
+
+
+/**
+ * User message reporting support
+ *
+ * @author Robert Field
+ */
+public interface MessageHandler {
+
+    void fluff(String format, Object... args);
+
+    void fluffmsg(String messageKey, Object... args);
+
+    void errormsg(String messageKey, Object... args);
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -28,6 +28,7 @@
 For an introduction type: /help intro\n
 jshell.err.opt.classpath.conflict = Conflicting -classpath option.
 jshell.err.opt.classpath.arg = Argument to -classpath missing.
+jshell.err.opt.feedback.arg = Argument to -feedback missing. Mode required.
 jshell.err.opt.startup.conflict = Conflicting -startup or -nostartup option.
 jshell.err.opt.unknown = Unknown option: {0}
 
@@ -128,13 +129,23 @@
 
 help.usage = \
 Usage:   jshell <options> <load files>\n\
-where possible options include:\n\t\
-  -classpath <path>          Specify where to find user class files\n\t\
-  -cp <path>                 Specify where to find user class files\n\t\
-  -startup <file>            One run replacement for the start-up definitions\n\t\
-  -nostartup                 Do not run the start-up definitions\n\t\
-  -help                      Print a synopsis of standard options\n\t\
-  -version                   Version information\n
+where possible options include:\n\
+\    -classpath <path>    Specify where to find user class files\n\
+\    -cp <path>           Specify where to find user class files\n\
+\    -startup <file>      One run replacement for the start-up definitions\n\
+\    -nostartup           Do not run the start-up definitions\n\
+\    -feedback <mode>     Specify the initial feedback mode. The mode may be\n\
+\                         predefined (silent, concise, normal, or verbose) or\n\
+\                         previously user-defined\n\
+\    -q                   Quiet feedback.  Same as: -feedback concise\n\
+\    -qq                  Really quiet feedback.  Same as: -feedback silent\n\
+\    -v                   Verbose feedback.  Same as: -feedback verbose\n\
+\    -J<flag>             Pass <flag> directly to the runtime system.\n\
+\                         Use one -J for each runtime flag or flag argument\n\
+\    -R<flag>             Pass <flag> to the remote runtime system.\n\
+\                         Use one -R for each remote flag or flag argument\n\
+\    -help                Print this synopsis of standard options\n\
+\    -version             Version information\n
 
 help.list.summary = list the source you have typed
 help.list.args = [all|start|<name or id>]
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Diag.java	Wed Jul 05 21:39:33 2017 +0200
@@ -36,12 +36,18 @@
     // Simplified view on compiler Diagnostic.
 
     /**
+     * In-package creation only.
+     */
+    Diag() {
+    }
+
+    /**
      * Used to signal that no position is available.
      */
     public final static long NOPOS = Diagnostic.NOPOS;
 
     /**
-     * Is this diagnostic and error (as opposed to a warning or note)
+     * Is this diagnostic an error (as opposed to a warning or note)
      * @return true if this diagnostic is an error
      */
     public abstract boolean isError();
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java	Wed Jul 05 21:39:33 2017 +0200
@@ -452,7 +452,7 @@
 
         // If appropriate, execute the snippet
         String value = null;
-        Exception exception = null;
+        JShellException exception = null;
         if (si.status().isDefined) {
             if (si.isExecutable()) {
                 try {
@@ -462,7 +462,8 @@
                             : "";
                 } catch (EvalException ex) {
                     exception = translateExecutionException(ex);
-                } catch (UnresolvedReferenceException ex) {
+                } catch (JShellException ex) {
+                    // UnresolvedReferenceException
                     exception = ex;
                 }
             } else if (si.subKind() == SubKind.VAR_DECLARATION_SUBKIND) {
@@ -499,7 +500,7 @@
                     || e.exception() != null;
     }
 
-    private List<SnippetEvent> events(Unit c, Collection<Unit> outs, String value, Exception exception) {
+    private List<SnippetEvent> events(Unit c, Collection<Unit> outs, String value, JShellException exception) {
         List<SnippetEvent> events = new ArrayList<>();
         events.add(c.event(value, exception));
         events.addAll(outs.stream()
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/EvalException.java	Wed Jul 05 21:39:33 2017 +0200
@@ -40,7 +40,7 @@
  * empty string.
  */
 @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
-public class EvalException extends Exception {
+public class EvalException extends JShellException {
     private final String exceptionClass;
 
     EvalException(String message, String exceptionClass, StackTraceElement[] stackElements) {
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java	Wed Jul 05 21:39:33 2017 +0200
@@ -57,11 +57,19 @@
     private ObjectInputStream in;
     private ObjectOutputStream out;
     private final JShell proc;
+    private final String remoteVMOptions;
 
-    ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc) {
+    ExecutionControl(JDIEnv env, SnippetMaps maps, JShell proc, List<String> extraRemoteVMOptions) {
         this.env = env;
         this.maps = maps;
         this.proc = proc;
+        StringBuilder sb = new StringBuilder();
+        extraRemoteVMOptions.stream()
+                .forEach(s -> {
+                    sb.append(" ");
+                    sb.append(s);
+                });
+        this.remoteVMOptions = sb.toString();
     }
 
     void launch() throws IOException {
@@ -111,7 +119,7 @@
         }
     }
 
-    String commandInvoke(String classname) throws EvalException, UnresolvedReferenceException {
+    String commandInvoke(String classname) throws JShellException {
         try {
             synchronized (STOP_LOCK) {
                 userCodeRunning = true;
@@ -205,7 +213,7 @@
         }
     }
 
-    private boolean readAndReportExecutionResult() throws IOException, EvalException, UnresolvedReferenceException {
+    private boolean readAndReportExecutionResult() throws IOException, JShellException {
         int ok = in.readInt();
         switch (ok) {
             case RESULT_SUCCESS:
@@ -257,11 +265,9 @@
         //        Locale.getDefault());
 
         String connectorName = "com.sun.jdi.CommandLineLaunch";
-        String classPath = System.getProperty("java.class.path");
-        String javaArgs = "-classpath " + classPath;
         Map<String, String> argumentName2Value = new HashMap<>();
         argumentName2Value.put("main", "jdk.internal.jshell.remote.RemoteAgent " + port);
-        argumentName2Value.put("options", javaArgs);
+        argumentName2Value.put("options", remoteVMOptions);
 
         boolean launchImmediately = true;
         int traceFlags = 0;// VirtualMachine.TRACE_SENDS | VirtualMachine.TRACE_EVENTS;
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java	Wed Jul 05 21:39:33 2017 +0200
@@ -26,10 +26,11 @@
 package jdk.jshell;
 
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
 import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -84,6 +85,7 @@
     final PrintStream err;
     final Supplier<String> tempVariableNameGenerator;
     final BiFunction<Snippet, Integer, String> idGenerator;
+    final List<String> extraRemoteVMOptions;
 
     private int nextKeyIndex = 1;
 
@@ -105,6 +107,7 @@
         this.err = b.err;
         this.tempVariableNameGenerator = b.tempVariableNameGenerator;
         this.idGenerator = b.idGenerator;
+        this.extraRemoteVMOptions = b.extraRemoteVMOptions;
 
         this.maps = new SnippetMaps(this);
         this.keyMap = new KeyMap(this);
@@ -139,6 +142,7 @@
         PrintStream err = System.err;
         Supplier<String> tempVariableNameGenerator = null;
         BiFunction<Snippet, Integer, String> idGenerator = null;
+        List<String> extraRemoteVMOptions = new ArrayList<>();
 
         Builder() { }
 
@@ -264,6 +268,18 @@
         }
 
         /**
+         * Set additional VM options for launching the VM.
+         *
+         * @param options The options for the remote VM.
+         * @return the <code>Builder</code> instance (for use in chained
+         * initialization).
+         */
+        public Builder remoteVMOptions(String... options) {
+            this.extraRemoteVMOptions.addAll(Arrays.asList(options));
+            return this;
+        }
+
+        /**
          * Build a JShell state engine. This is the entry-point to all JShell
          * functionality. This creates a remote process for execution. It is
          * thus important to close the returned instance.
@@ -621,10 +637,10 @@
 
     ExecutionControl executionControl() {
         if (executionControl == null) {
-            this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this);
+            this.executionControl = new ExecutionControl(new JDIEnv(this), maps, this, extraRemoteVMOptions);
             try {
                 executionControl.launch();
-            } catch (IOException ex) {
+            } catch (Throwable ex) {
                 throw new InternalError("Launching JDI execution engine threw: " + ex.getMessage(), ex);
             }
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShellException.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.jshell;
+
+/**
+ * The superclass of JShell generated exceptions
+ */
+@SuppressWarnings("serial")             // serialVersionUID intentionally omitted
+public class JShellException extends Exception {
+
+    JShellException(String message) {
+        super(message);
+    }
+}
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SnippetEvent.java	Wed Jul 05 21:39:33 2017 +0200
@@ -44,7 +44,7 @@
 
     SnippetEvent(Snippet snippet, Status previousStatus, Status status,
             boolean isSignatureChange, Snippet causeSnippet,
-            String value, Exception exception) {
+            String value, JShellException exception) {
         this.snippet = snippet;
         this.previousStatus = previousStatus;
         this.status = status;
@@ -60,7 +60,7 @@
     private final boolean isSignatureChange;
     private final Snippet causeSnippet;
     private final String value;
-    private final Exception exception;
+    private final JShellException exception;
 
     /**
      * The Snippet which has changed
@@ -121,7 +121,7 @@
      * during execution, otherwise <code>null</code>.
      * @return the exception or <code>null</code>.
      */
-    public Exception exception() {
+    public JShellException exception() {
         return exception;
     }
 
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Unit.java	Wed Jul 05 21:39:33 2017 +0200
@@ -440,7 +440,7 @@
                 : msi.parameterTypes();
     }
 
-    SnippetEvent event(String value, Exception exception) {
+    SnippetEvent event(String value, JShellException exception) {
         boolean wasSignatureChanged = sigChanged();
         state.debug(DBG_EVNT, "Snippet: %s id: %s before: %s status: %s sig: %b cause: %s\n",
                 si, si.id(), prevStatus, si.status(), wasSignatureChanged, causalSnippet);
--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java	Wed Jul 05 21:39:33 2017 +0200
@@ -38,7 +38,7 @@
  * empty string.
  */
 @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
-public class UnresolvedReferenceException extends Exception {
+public class UnresolvedReferenceException extends JShellException {
 
     final DeclarationSnippet snippet;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8154119
+ * @summary Test modules support in javadoc.
+ * @author bpatel
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester
+ * @run main TestModules
+ */
+
+public class TestModules extends JavadocTester {
+
+    public static void main(String... args) throws Exception {
+        TestModules tester = new TestModules();
+        tester.runTests();
+    }
+
+    @Test
+    void test1() {
+        javadoc("-d", "out",
+                "-modulesourcepath", testSrc,
+                "-addmods", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2");
+        checkExit(Exit.OK);
+        testDescription(true);
+        testNoDescription(false);
+    }
+
+    @Test
+    void test2() {
+        javadoc("-d", "out-html5", "-html5",
+                "-modulesourcepath", testSrc,
+                "-addmods", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2");
+        checkExit(Exit.OK);
+        testHtml5Description(true);
+        testHtml5NoDescription(false);
+    }
+
+    @Test
+    void test3() {
+        javadoc("-d", "out-nocomment", "-nocomment",
+                "-modulesourcepath", testSrc,
+                "-addmods", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2");
+        checkExit(Exit.OK);
+        testDescription(false);
+        testNoDescription(true);
+    }
+
+    @Test
+    void test4() {
+        javadoc("-d", "out-html5-nocomment", "-nocomment", "-html5",
+                "-modulesourcepath", testSrc,
+                "-addmods", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2");
+        checkExit(Exit.OK);
+        testHtml5Description(false);
+        testHtml5NoDescription(true);
+    }
+
+    void testDescription(boolean found) {
+        checkOutput("module1-summary.html", found,
+                "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+                + "<a name=\"module.description\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<div class=\"block\">This is a test description for the module1 module.</div>");
+        checkOutput("module2-summary.html", found,
+                "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+                + "<a name=\"module.description\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<div class=\"block\">This is a test description for the module2 module.</div>");
+    }
+
+    void testNoDescription(boolean found) {
+        checkOutput("module1-summary.html", found,
+                "<div class=\"contentContainer\">\n"
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+        checkOutput("module2-summary.html", found,
+                "<div class=\"contentContainer\">\n"
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+    }
+
+    void testHtml5Description(boolean found) {
+        checkOutput("module1-summary.html", found,
+                "<section role=\"region\">\n"
+                + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+                + "<a id=\"module.description\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<div class=\"block\">This is a test description for the module1 module.</div>\n"
+                + "</section>");
+        checkOutput("module2-summary.html", found,
+                "<section role=\"region\">\n"
+                + "<!-- ============ MODULE DESCRIPTION =========== -->\n"
+                + "<a id=\"module.description\">\n"
+                + "<!--   -->\n"
+                + "</a>\n"
+                + "<div class=\"block\">This is a test description for the module2 module.</div>\n"
+                + "</section>");
+    }
+
+    void testHtml5NoDescription(boolean found) {
+        checkOutput("module1-summary.html", found,
+                "<div class=\"contentContainer\">\n"
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<table class=\"overviewSummary\">");
+        checkOutput("module2-summary.html", found,
+                "<div class=\"contentContainer\">\n"
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<table class=\"overviewSummary\">");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+  * This is a test description for the module1 module.
+  */
+module module1 {
+    requires module2;
+
+    exports testpkgmdl1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module1/testpkgmdl1/TestClassInModule1.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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 testpkgmdl1;
+
+public class TestClassInModule1 {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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.
+ */
+
+/**
+  * This is a test description for the module2 module.
+  */
+module module2 {
+    exports testpkgmdl2;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java	Wed Jul 05 21:39:33 2017 +0200
@@ -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 testpkgmdl2;
+
+public class TestClassInModule2 {
+}
--- a/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8039410 8042601 8042829 8049393 8050031
+ * @bug 8039410 8042601 8042829 8049393 8050031 8155061
  * @summary test to determine if members are ordered correctly
  * @author ksrini
  * @library ../lib/
@@ -72,6 +72,8 @@
         checkOrder("pkg1/class-use/UsedClass.html", expectedInnerClassContructors);
         checkOrder("pkg1/ImplementsOrdering.html", expectedImplementsOrdering);
         checkOrder("pkg1/OverrideOrdering.html", expectedOverrideOrdering);
+        checkOrder("allclasses-noframe.html", expectedAllClasses);
+        checkOrder("allclasses-frame.html", expectedAllClasses);
     }
 
     enum ListOrder { NONE, REVERSE, SHUFFLE };
@@ -179,6 +181,22 @@
     };
     String[] composeTestVectors() {
         List<String> testList = new ArrayList<>();
+
+        testList.addAll(Arrays.asList(expectedPackageOrdering));
+
+        for (String x : expectedMethodOrdering) {
+            testList.add(x);
+            for (int i = 0; i < MAX_PACKAGES; i++) {
+                String wpkg = "add" + i;
+                testList.add(wpkg + "/" + x);
+                String dpkg = wpkg;
+                for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
+                    dpkg = dpkg + "/" + "add";
+                    testList.add(dpkg + "/" + x);
+                }
+            }
+        }
+
         for (String x : expectedEnumOrdering) {
             testList.add(x.replace("REPLACE_ME", "&lt;Unnamed&gt;"));
             for (int i = 0; i < MAX_PACKAGES; i++) {
@@ -194,20 +212,9 @@
 
         testList.addAll(Arrays.asList(expectedFieldOrdering));
 
-        for (String x : expectedMethodOrdering) {
-            testList.add(x);
-            for (int i = 0; i < MAX_PACKAGES; i++) {
-                String wpkg = "add" + i;
-                testList.add(wpkg + "/" + x);
-                String dpkg = wpkg;
-                for (int j = 1; j < MAX_SUBPACKAGES_DEPTH; j++) {
-                    dpkg = dpkg + "/" + "add";
-                    testList.add(dpkg + "/" + x);
-                }
-            }
-        }
         return testList.toArray(new String[testList.size()]);
     }
+
     void checkExecutableMemberOrdering(String usePage) {
         String contents = readFile(usePage);
         // check constructors
@@ -309,6 +316,22 @@
         return in.replace("/", ".");
     }
 
+    final String expectedAllClasses[] = {
+        "pkg1/A.html\" title=\"class in pkg1",
+        "pkg1/A.C.html\" title=\"class in pkg1",
+        "pkg1/B.html\" title=\"class in pkg1",
+        "pkg1/B.A.html\" title=\"class in pkg1",
+        "pkg1/C1.html\" title=\"class in pkg1",
+        "pkg1/C2.html\" title=\"class in pkg1",
+        "pkg1/C3.html\" title=\"class in pkg1",
+        "pkg1/C4.html\" title=\"class in pkg1",
+        "pkg1/ImplementsOrdering.html\" title=\"interface in pkg1",
+        "pkg1/MethodOrder.html\" title=\"class in pkg1",
+        "pkg1/OverrideOrdering.html\" title=\"class in pkg1",
+        "pkg1/UsedClass.html\" title=\"class in pkg1"
+
+    };
+
     final String expectedInnerClassContructors[] = {
         "../../pkg1/A.html#A-pkg1.UsedClass-",
         "../../pkg1/B.A.html#A-pkg1.UsedClass-",
@@ -342,12 +365,33 @@
         "../../pkg1/MethodOrder.html#m-java.util.Collection-",
         "../../pkg1/MethodOrder.html#m-java.util.List-"
     };
+
     final String expectedClassUseWithTypeParams[] = {
         "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-",
         "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass-",
         "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-pkg1.UsedClass:A-",
         "../../pkg1/MethodOrder.html#tpm-pkg1.UsedClass-java.lang.String-"
     };
+
+    final String expectedPackageOrdering[] = {
+        "\"add0/package-summary.html\">add0</a> - package add0",
+        "\"add0/add/package-summary.html\">add0.add</a> - package add0.add",
+        "\"add0/add/add/package-summary.html\">add0.add.add</a> - package add0.add.add",
+        "\"add0/add/add/add/package-summary.html\">add0.add.add.add</a> - package add0.add.add.add",
+        "\"add1/package-summary.html\">add1</a> - package add1",
+        "\"add1/add/package-summary.html\">add1.add</a> - package add1.add",
+        "\"add1/add/add/package-summary.html\">add1.add.add</a> - package add1.add.add",
+        "\"add1/add/add/add/package-summary.html\">add1.add.add.add</a> - package add1.add.add.add",
+        "\"add2/package-summary.html\">add2</a> - package add2",
+        "\"add2/add/package-summary.html\">add2.add</a> - package add2.add",
+        "\"add2/add/add/package-summary.html\">add2.add.add</a> - package add2.add.add",
+        "\"add2/add/add/add/package-summary.html\">add2.add.add.add</a> - package add2.add.add.add",
+        "\"add3/package-summary.html\">add3</a> - package add3",
+        "\"add3/add/package-summary.html\">add3.add</a> - package add3.add",
+        "\"add3/add/add/package-summary.html\">add3.add.add</a> - package add3.add.add",
+        "\"add3/add/add/add/package-summary.html\">add3.add.add.add</a> - package add3.add.add.add"
+    };
+
     final String expectedMethodOrdering[] = {
         "Add.html#add--",
         "Add.html#add-double-",
@@ -361,10 +405,12 @@
         "Add.html#add-java.lang.Double-",
         "Add.html#add-java.lang.Integer-"
     };
+
     final String expectedEnumOrdering[] = {
         "Add.add.html\" title=\"enum in REPLACE_ME\"",
         "Add.ADD.html\" title=\"enum in REPLACE_ME\""
     };
+
     final String expectedFieldOrdering[] = {
         "Add.html#addadd\"",
         "add0/add/add/add/Add.html#addadd\"",
@@ -418,10 +464,12 @@
         "add3/add/Add.html#ADDADD\"",
         "add3/Add.html#ADDADD\""
     };
+
     final String expectedPackageTreeOrdering[] = {
         "<a href=\"../../add0/add/Add.add.html\" title=\"enum in add0.add\">",
         "<a href=\"../../add0/add/Add.ADD.html\" title=\"enum in add0.add\">"
     };
+
     final String expectedOverviewOrdering[] = {
         "<a href=\"Add.add.html\" title=\"enum in &lt;Unnamed&gt;\">",
         "<a href=\"add0/Add.add.html\" title=\"enum in add0\">",
@@ -458,6 +506,7 @@
         "<a href=\"add3/add/add/Add.ADD.html\" title=\"enum in add3.add.add\">",
         "<a href=\"add3/add/add/add/Add.ADD.html\" title=\"enum in add3.add.add.add\">",
     };
+
     final static String expectedOverviewFrameOrdering[] = {
         "<a href=\"package-frame.html\" target=\"packageFrame\">&lt;unnamed package&gt;</a>",
         "<a href=\"add0/package-frame.html\" target=\"packageFrame\">add0</a>",
@@ -477,11 +526,13 @@
         "<a href=\"add3/add/add/package-frame.html\" target=\"packageFrame\">add3.add.add</a>",
         "<a href=\"add3/add/add/add/package-frame.html\" target=\"packageFrame\">add3.add.add.add</a></li>"
     };
+
     final static String expectedImplementsOrdering[] = {
         "<dd><code>close</code>&nbsp;in interface&nbsp;<code>java.lang.AutoCloseable</code></dd>",
         "<dd><code>close</code>&nbsp;in interface&nbsp;<code>java.nio.channels.Channel</code></dd>",
         "<dd><code>close</code>&nbsp;in interface&nbsp;<code>java.io.Closeable</code></dd>"
     };
+
     final static String expectedOverrideOrdering[] = {
         "<dd><code>iterator</code>&nbsp;in interface&nbsp;<code>java.util.Collection&lt;",
         "<dd><code>iterator</code>&nbsp;in interface&nbsp;<code>java.lang.Iterable&lt;"
--- a/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/jdk/javadoc/tool/EnsureNewOldDoclet.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,96 +23,349 @@
 
 /*
  * @test
- * @bug 8035473
- * @summary make sure the new doclet is invoked by default, and -Xold
+ * @bug 8035473 8154482
+ * @summary make sure the javadoc tool responds correctly to Xold,
+ *          old doclets and taglets.
+ * @library /tools/lib
+ * @build toolbox.ToolBox toolbox.TestRunner
+ * @run main EnsureNewOldDoclet
  */
 
 import java.io.*;
-import java.util.ArrayList;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import com.sun.javadoc.Tag;
+import com.sun.source.doctree.DocTree;
+
+import toolbox.*;
+
 
 /**
- * Dummy javadoc comment.
+ * This test ensures the doclet responds correctly when given
+ * various conditions that force a fall back to the old javadoc
+ * tool. The following condition in the order described will
+ * force a dispatch to the old tool, -Xold, old doclet and old taglet.
+ *
  */
-public class EnsureNewOldDoclet {
+public class EnsureNewOldDoclet extends TestRunner {
+
+    final ToolBox tb;
+    final File testSrc;
+    final Path javadocPath;
+    final ExecTask task;
+    final String testClasses;
+    final PrintStream ostream;
 
-    final File javadoc;
-    final File testSrc;
-    final String thisClassName;
+    final static String CLASS_NAME = "EnsureNewOldDoclet";
+    final static String OLD_DOCLET_CLASS_NAME = CLASS_NAME + "$OldDoclet";
+    final static String NEW_DOCLET_CLASS_NAME = CLASS_NAME + "$NewDoclet"; //unused
+    final static String OLD_TAGLET_CLASS_NAME = CLASS_NAME + "$OldTaglet";
+    final static String NEW_TAGLET_CLASS_NAME = CLASS_NAME + "$NewTaglet";
+
+    final static Pattern OLD_HEADER = Pattern.compile("^Standard Doclet \\(Old\\) version.*");
+    final static Pattern NEW_HEADER = Pattern.compile("^Standard Doclet version.*");
+
+
+    final static String OLD_DOCLET_MARKER = "OLD_DOCLET_MARKER";
+    final static String OLD_TAGLET_MARKER = "Registered: OldTaglet";
+
+    final static String NEW_DOCLET_MARKER = "NEW_DOCLET_MARKER";
+    final static String NEW_TAGLET_MARKER = "Registered Taglet " + CLASS_NAME + "\\$NewTaglet";
 
-    final static Pattern Expected1 = Pattern.compile("^Standard Doclet \\(Next\\) version.*");
-    final static Pattern Expected2 = Pattern.compile("^Standard Doclet version.*");
+    final static Pattern WARN_TEXT = Pattern.compile("Users are strongly recommended to migrate" +
+                                                    " to the new APIs.");
+    final static String OLD_DOCLET_ERROR = "java.lang.NoSuchMethodException: " +
+            CLASS_NAME +"\\$NewTaglet";
+    final static Pattern NEW_DOCLET_ERROR = Pattern.compile(".*java.lang.ClassCastException.*Taglet " +
+            CLASS_NAME + "\\$OldTaglet.*");
+
+    final static String OLD_STDDOCLET = "com.sun.tools.doclets.standard.Standard";
+    final static String NEW_STDDOCLET = "jdk.javadoc.internal.doclets.standard.Standard";
+
 
-    public EnsureNewOldDoclet() {
-        File javaHome = new File(System.getProperty("java.home"));
-        if (javaHome.getName().endsWith("jre"))
-            javaHome = javaHome.getParentFile();
-        javadoc = new File(new File(javaHome, "bin"), "javadoc");
-        testSrc = new File(System.getProperty("test.src"));
-        thisClassName = EnsureNewOldDoclet.class.getName();
+    public EnsureNewOldDoclet() throws Exception {
+        super(System.err);
+        ostream = System.err;
+        testClasses = System.getProperty("test.classes");
+        tb = new ToolBox();
+        javadocPath = tb.getJDKTool("javadoc");
+        task = new ExecTask(tb, javadocPath);
+        testSrc = new File("Foo.java");
+        generateSample(testSrc);
+    }
+
+    void generateSample(File testSrc) throws Exception {
+        String nl = System.getProperty("line.separator");
+        String src = Arrays.asList(
+            "/**",
+            " * A test class to test javadoc. Nothing more nothing less.",
+            " */",
+            " public class Foo{}").stream().collect(Collectors.joining(nl));
+        tb.writeFile(testSrc.getPath(), src);
     }
 
     public static void main(String... args) throws Exception {
-        EnsureNewOldDoclet test = new EnsureNewOldDoclet();
-        test.run1();
-        test.run2();
+        new EnsureNewOldDoclet().runTests();
+    }
+
+    // input: nothing, default mode
+    // outcome: new tool and new doclet
+    @Test
+    public void testDefault() throws Exception {
+        setArgs("-classpath", ".", // insulates us from ambient classpath
+                  testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        checkOutput(testName, out, NEW_HEADER);
+    }
+
+    // input: -Xold
+    // outcome: old tool
+    @Test
+    public void testXold() throws Exception {
+        setArgs("-Xold",
+                "-classpath", ".", // ambient classpath insulation
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, OLD_HEADER);
+        checkOutput(testName, err, WARN_TEXT);
+    }
+
+    // input: old doclet
+    // outcome: old tool
+    @Test
+    public void testOldDoclet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+                "-doclet",
+                OLD_DOCLET_CLASS_NAME,
+                "-docletpath",
+                testClasses,
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, OLD_DOCLET_MARKER);
+        checkOutput(testName, err, WARN_TEXT);
+    }
+
+    // input: old taglet
+    // outcome: old tool
+    @Test
+    public void testOldTaglet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+            "-taglet",
+            OLD_TAGLET_CLASS_NAME,
+            "-tagletpath",
+            testClasses,
+            testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, OLD_TAGLET_MARKER);
+        checkOutput(testName, err, WARN_TEXT);
     }
 
-    // make sure new doclet is invoked by default
-    void run1() throws Exception {
-        List<String> output = doTest(javadoc.getPath(),
-                "-classpath", ".", // insulates us from ambient classpath
-                "-Xdoclint:none",
-                "-package",
-                new File(testSrc, thisClassName + ".java").getPath());
-        System.out.println(output);
-        for (String x : output) {
-            if (Expected1.matcher(x).matches()) {
+    // input: new doclet and old taglet
+    // outcome: new doclet with failure
+    @Test
+    public void testNewDocletOldTaglet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+                "-doclet",
+                NEW_STDDOCLET,
+                "-taglet",
+                OLD_TAGLET_CLASS_NAME,
+                "-tagletpath",
+                testClasses,
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.FAIL, 1);
+        //Task.Result tr = task.run();
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, NEW_HEADER);
+        checkOutput(testName, err, NEW_DOCLET_ERROR);
+    }
+
+    // input: old doclet and old taglet
+    // outcome: old doclet and old taglet should register
+    @Test
+    public void testOldDocletOldTaglet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+                "-doclet",
+                OLD_STDDOCLET,
+                "-taglet",
+                OLD_TAGLET_CLASS_NAME,
+                "-tagletpath",
+                testClasses,
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, OLD_HEADER);
+        checkOutput(testName, out, OLD_TAGLET_MARKER);
+        checkOutput(testName, err, WARN_TEXT);
+    }
+
+    // input: new doclet and new taglet
+    // outcome: new doclet and new taglet should register
+    @Test
+    public void testNewDocletNewTaglet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+                "-doclet",
+                NEW_STDDOCLET,
+                "-taglet",
+                NEW_TAGLET_CLASS_NAME,
+                "-tagletpath",
+                testClasses,
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.SUCCESS);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, NEW_HEADER);
+        checkOutput(testName, out, NEW_TAGLET_MARKER);
+    }
+
+    // input: old doclet and new taglet
+    // outcome: old doclet and error
+    @Test
+    public void testOldDocletNewTaglet() throws Exception {
+        setArgs("-classpath", ".", // ambient classpath insulation
+                "-doclet",
+                OLD_STDDOCLET,
+                "-taglet",
+                NEW_TAGLET_CLASS_NAME,
+                "-tagletpath",
+                testClasses,
+                testSrc.toString());
+        Task.Result tr = task.run(Task.Expect.FAIL, 1);
+        List<String> out = tr.getOutputLines(Task.OutputKind.STDOUT);
+        List<String> err = tr.getOutputLines(Task.OutputKind.STDERR);
+        checkOutput(testName, out, OLD_HEADER);
+        checkOutput(testName, err, WARN_TEXT);
+        checkOutput(testName, err, OLD_DOCLET_ERROR);
+    }
+
+    void setArgs(String... args) {
+        ostream.println("cmds: " + Arrays.asList(args));
+        task.args(args);
+    }
+
+    void checkOutput(String testCase, List<String> content, String toFind) throws Exception {
+        checkOutput(testCase, content, Pattern.compile(".*" + toFind + ".*"));
+    }
+
+    void checkOutput(String testCase, List<String> content, Pattern toFind) throws Exception {
+        ostream.println("---" + testCase + "---");
+        content.stream().forEach(x -> System.out.println(x));
+        for (String x : content) {
+            ostream.println(x);
+            if (toFind.matcher(x).matches()) {
                 return;
             }
         }
-        throw new Exception("run1: Expected string not found:");
+        throw new Exception(testCase + ": Expected string not found: " +  toFind);
     }
 
-    // make sure the old doclet is invoked with -Xold
-    void run2() throws Exception {
-        List<String> output = doTest(javadoc.getPath(),
-                "-Xold",
-                "-classpath", ".", // insulates us from ambient classpath
-                "-Xdoclint:none",
-                "-package",
-                new File(testSrc, thisClassName + ".java").getPath());
-
-        for (String x : output) {
-            if (Expected2.matcher(x).matches()) {
-                throw new Exception("run2: Expected string not found");
-            }
-            return;
+    public static class OldDoclet extends com.sun.javadoc.Doclet {
+        public static boolean start(com.sun.javadoc.RootDoc root) {
+            System.out.println(OLD_DOCLET_MARKER);
+            return true;
         }
     }
 
-    /**
-     * More dummy comments.
-     */
-    List<String> doTest(String... args) throws Exception {
-        List<String> output = new ArrayList<>();
-        // run javadoc in separate process to ensure doclet executed under
-        // normal user conditions w.r.t. classloader
-        Process p = new ProcessBuilder()
-                .command(args)
-                .redirectErrorStream(true)
-                .start();
-        try (BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
-            String line = in.readLine();
-            while (line != null) {
-                output.add(line.trim());
-                line = in.readLine();
-            }
+    public static class OldTaglet implements com.sun.tools.doclets.Taglet {
+
+        public static void register(Map map) {
+            EnsureNewOldDoclet.OldTaglet tag = new OldTaglet();
+            com.sun.tools.doclets.Taglet t = (com.sun.tools.doclets.Taglet) map.get(tag.getName());
+            System.out.println(OLD_TAGLET_MARKER);
+        }
+
+        @Override
+        public boolean inField() {
+            return true;
+        }
+
+        @Override
+        public boolean inConstructor() {
+            return true;
+        }
+
+        @Override
+        public boolean inMethod() {
+            return true;
+        }
+
+        @Override
+        public boolean inOverview() {
+            return true;
+        }
+
+        @Override
+        public boolean inPackage() {
+            return true;
+        }
+
+        @Override
+        public boolean inType() {
+            return true;
+        }
+
+        @Override
+        public boolean isInlineTag() {
+            return true;
         }
-        int rc = p.waitFor();
-        if (rc != 0)
-            throw new Exception("javadoc failed, rc:" + rc);
-        return output;
+
+        @Override
+        public String getName() {
+            return "OldTaglet";
+        }
+
+        @Override
+        public String toString(Tag tag) {
+            return getName();
+        }
+
+        @Override
+        public String toString(Tag[] tags) {
+            return getName();
+        }
+    }
+
+    public static class NewTaglet implements jdk.javadoc.doclet.taglet.Taglet {
+
+        @Override
+        public Set<Location> getAllowedLocations() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        public boolean isInlineTag() {
+            return true;
+        }
+
+        @Override
+        public String getName() {
+            return "NewTaglet";
+        }
+
+        @Override
+        public String toString(DocTree tag) {
+            return tag.toString();
+        }
+
+        @Override
+        public String toString(List<? extends DocTree> tags) {
+            return tags.toString();
+        }
+
     }
 }
--- a/langtools/test/jdk/jshell/StartOptionTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/jdk/jshell/StartOptionTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -22,7 +22,7 @@
  */
 
 /*
- * @test
+ * @test 8151754
  * @summary Testing start-up options.
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -34,6 +34,7 @@
  */
 
 import java.io.ByteArrayOutputStream;
+import java.io.OutputStream;
 import java.io.PrintStream;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
@@ -47,6 +48,7 @@
 
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 @Test
 public class StartOptionTest {
@@ -55,9 +57,24 @@
     private ByteArrayOutputStream err;
 
     private JShellTool getShellTool() {
-        return new JShellTool(null, new PrintStream(out), new PrintStream(err), null, null, null,
-                              null, new ReplToolTesting.MemoryPreferences(),
-                              Locale.ROOT);
+        class NoOutputAllowedStream extends OutputStream {
+            private final String label;
+            NoOutputAllowedStream(String label) {
+               this.label = label;
+            }
+            @Override
+            public void write(int b) { fail("Unexpected output to: " + label); }
+        }
+        return new JShellTool(
+                new TestingInputStream(),
+                new PrintStream(out),
+                new PrintStream(err),
+                new PrintStream(new NoOutputAllowedStream("console")),
+                new TestingInputStream(),
+                new PrintStream(new NoOutputAllowedStream("userout")),
+                new PrintStream(new NoOutputAllowedStream("usererr")),
+                new ReplToolTesting.MemoryPreferences(),
+                Locale.ROOT);
     }
 
     private String getOutput() {
@@ -133,6 +150,12 @@
     }
 
     @Test
+    public void testNegFeedbackOption() throws Exception {
+        start("", "Argument to -feedback missing. Mode required.", "-feedback");
+        start("", "Does not match any current feedback mode: blorp -- -feedback blorp", "-feedback", "blorp");
+    }
+
+    @Test
     public void testVersion() throws Exception {
         start(s -> assertTrue(s.startsWith("jshell")), null, "-version");
     }
--- a/langtools/test/jdk/jshell/ToolSimpleTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/jdk/jshell/ToolSimpleTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8153716 8143955
+ * @bug 8153716 8143955 8151754 8150382
  * @summary Simple jshell tool tests
  * @modules jdk.compiler/com.sun.tools.javac.api
  *          jdk.compiler/com.sun.tools.javac.main
@@ -349,4 +349,39 @@
             System.setProperty("java.awt.headless", prevHeadless==null? "false" : prevHeadless);
         }
     }
+
+    public void testOptionQ() {
+        test(new String[]{"-q", "-nostartup"},
+                (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
+                (a) -> assertCommand(a, "int x = 5", "")
+        );
+    }
+
+    public void testOptionQq() {
+        test(new String[]{"-qq", "-nostartup"},
+                (a) -> assertCommand(a, "1+1", "")
+        );
+    }
+
+    public void testOptionV() {
+        test(new String[]{"-v", "-nostartup"},
+                (a) -> assertCommand(a, "1+1",
+                        "$1 ==> 2\n" +
+                        "|  created scratch variable $1 : int")
+        );
+    }
+
+    public void testOptionFeedback() {
+        test(new String[]{"-feedback", "concise", "-nostartup"},
+                (a) -> assertCommand(a, "1+1", "$1 ==> 2"),
+                (a) -> assertCommand(a, "int x = 5", "")
+        );
+    }
+
+    public void testOptionR() {
+        test(new String[]{"-R-Dthe.sound=blorp", "-nostartup"},
+                (a) -> assertCommand(a, "System.getProperty(\"the.sound\")",
+                        "$1 ==> \"blorp\"")
+        );
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/UnreachableLoopCond.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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 8155028
+ * @summary javac crashes in silly do-while loop
+ * @compile UnreachableLoopCond.java
+ */
+
+class UnreachableLoopCond {
+
+    public void foo() {
+        Integer i = 100;
+        do {
+            return;
+        } while (i++ < 10);
+    }
+
+    public void goo() {
+        Integer i = 100;
+        do {
+            break;
+        } while (i++ < 10);
+    }
+
+    public void zoo() {
+        Integer i = 100;
+        do {
+            throw new RuntimeException();
+        } while (i++ < 10);
+    }
+
+    public void loo() {
+        Integer i = 100;
+        Integer j = 100;
+        do {
+           do {
+               return;
+           } while (i++ < 10);
+        } while (j++ < 10);
+    }
+
+    public void moo() {
+        Integer i = 100;
+        do {
+            if (true) {
+                return;
+            } else {
+                return;
+            }
+        } while (i++ < 10);
+    }
+
+    public void moo(boolean cond) {
+        Integer i = 100;
+        do {
+            if (cond) {
+                return;
+            } else {
+                return;
+            }
+        } while (i++ < 10);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/T8154270/EraseClassInfoAnnotationValueTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2016 Google Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/*
+ * @test
+ * @bug 8154270
+ * @summary javac wrongly rejects some class literals as annotation element values
+ * @compile EraseClassInfoAnnotationValueTest.java
+ * @compile -implicit:none Other.java
+ * @run main EraseClassInfoAnnotationValueTest
+ */
+public class EraseClassInfoAnnotationValueTest {
+
+  @Retention(RetentionPolicy.RUNTIME)
+  public @interface A {
+    Class<?> value();
+  }
+
+  static class ParametricType<T> {
+
+    @A(Inner.class)
+    public static class Nested {}
+
+    public class Inner {}
+  }
+
+  public static void main(String[] args) {
+    Class<?> clazz = ParametricType.Nested.class.getAnnotation(A.class).value();
+    if (!clazz.equals(ParametricType.Inner.class)) {
+      throw new AssertionError(clazz);
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/annotations/T8154270/Other.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016 Google Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests separate compilation.
+ */
+public class Other {
+  Class<?> clazz = EraseClassInfoAnnotationValueTest.ParametricType.Nested.class;
+}
--- a/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/LineNumberTestBase.java	Wed Jul 05 21:39:33 2017 +0200
@@ -191,7 +191,7 @@
         CONDITION("int res = \n" +
                 "testField == 2 ?\n" +
                 "10\n" +
-                ":9;", 1, 3, 4), // see issue https://bugs.openjdk.java.net/browse/JDK-8050993
+                ":9;", 2, 3, 4),
         TRY("try{\n" +
                 "    --testField;\n" +
                 "}\n" +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/classfiles/attributes/LineNumberTable/T8050993.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,53 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8050993
+ * @summary Verify that the condition in the conditional lexpression gets a LineNumberTable entry
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * @compile -g T8050993.java
+ * @run main T8050993
+ */
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.sun.tools.classfile.*;
+
+public class T8050993 {
+    public static void main(String[] args) throws IOException, ConstantPoolException {
+        ClassFile someTestIn = ClassFile.read(T8050993.class.getResourceAsStream("T8050993.class"));
+        Set<Integer> expectedLineNumbers = new HashSet<>(Arrays.asList(49, 50, 47, 48));
+        for (Method m : someTestIn.methods) {
+            if ("method".equals(m.getName(someTestIn.constant_pool))) {
+                Code_attribute code_attribute = (Code_attribute) m.attributes.get(Attribute.Code);
+                for (Attribute at : code_attribute.attributes) {
+                    if (Attribute.LineNumberTable.equals(at.getName(someTestIn.constant_pool))) {
+                        LineNumberTable_attribute att = (LineNumberTable_attribute) at;
+                        Set<Integer> actualLinesNumbers = Arrays.stream(att.line_number_table)
+                                                                .map(e -> e.line_number)
+                                                                .collect(Collectors.toSet());
+                        if (!Objects.equals(expectedLineNumbers, actualLinesNumbers)) {
+                            throw new AssertionError("Expected LineNumber entries not found;" +
+                                                     "actual=" + actualLinesNumbers + ";" +
+                                                     "expected=" + expectedLineNumbers);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public static int field;
+
+    public static String method() {
+        String s =
+                field % 2 == 0 ?
+                "true" + field :
+                "false" + field;
+        return s;
+    }
+
+}
--- a/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AbstractOrInnerClassServiceImplTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,7 +47,7 @@
     }
 
     @Test
-    void testAbstractServiceImpl(Path base) throws Exception {
+    public void testAbstractServiceImpl(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.Service with p2.Impl; }",
@@ -68,7 +68,7 @@
     }
 
     @Test
-    void testInnerClassServiceImpl(Path base) throws Exception {
+    public void testInnerClassServiceImpl(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.Service with p2.Outer.Inner; }",
@@ -89,7 +89,7 @@
     }
 
     @Test
-    void testInnerInterfaceServiceImpl(Path base) throws Exception {
+    public void testInnerInterfaceServiceImpl(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.Service with p2.Outer.Inner; }",
--- a/langtools/test/tools/javac/modules/AddLimitMods.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AddLimitMods.java	Wed Jul 05 21:39:33 2017 +0200
@@ -79,7 +79,7 @@
     }
 
     @Test
-    void testManual(Path base) throws Exception {
+    public void testManual(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
@@ -176,7 +176,7 @@
     }
 
     @Test
-    void testAllModulePath(Path base) throws Exception {
+    public void testAllModulePath(Path base) throws Exception {
         if (Files.isDirectory(base))
             tb.cleanDirectory(base);
 
@@ -284,7 +284,7 @@
     }
 
     @Test
-    void testRuntime2Compile(Path base) throws Exception {
+    public void testRuntime2Compile(Path base) throws Exception {
         Path classpathSrc = base.resolve("classpath-src");
         Path classpathOut = base.resolve("classpath-out");
 
--- a/langtools/test/tools/javac/modules/AddReadsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AddReadsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -58,7 +58,7 @@
     }
 
     @Test
-    void testAddReads(Path base) throws Exception {
+    public void testAddReads(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1,
@@ -150,7 +150,7 @@
     }
 
     @Test
-    void testAddReadsUnnamedModule(Path base) throws Exception {
+    public void testAddReadsUnnamedModule(Path base) throws Exception {
         Path jar = prepareTestJar(base);
 
         Path moduleSrc = base.resolve("module-src");
@@ -175,7 +175,7 @@
     }
 
     @Test
-    void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
+    public void testAddReadsUnnamedModulePackageConflict(Path base) throws Exception {
         Path jar = prepareTestJar(base);
 
         Path moduleSrc = base.resolve("module-src");
@@ -202,7 +202,7 @@
     }
 
     @Test
-    void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
+    public void testAddReadsUnnamedToJavaBase(Path base) throws Exception {
         Path jar = prepareTestJar(base);
         Path src = base.resolve("src");
         Path classes = base.resolve("classes");
@@ -223,7 +223,7 @@
     }
 
     @Test
-    void testAddReadsToJavaBase(Path base) throws Exception {
+    public void testAddReadsToJavaBase(Path base) throws Exception {
         Path src = base.resolve("src");
         Path classes = base.resolve("classes");
 
@@ -275,7 +275,7 @@
     }
 
     @Test
-    void testX(Path base) throws Exception {
+    public void testX(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1,
--- a/langtools/test/tools/javac/modules/AnnotationProcessing.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AnnotationProcessing.java	Wed Jul 05 21:39:33 2017 +0200
@@ -68,7 +68,7 @@
     }
 
     @Test
-    void testAPSingleModule(Path base) throws Exception {
+    public void testAPSingleModule(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
@@ -95,7 +95,7 @@
     }
 
     @Test
-    void testAPMultiModule(Path base) throws Exception {
+    public void testAPMultiModule(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
         Path m2 = moduleSrc.resolve("m2");
@@ -196,7 +196,7 @@
     }
 
     @Test
-    void testVerifyUsesProvides(Path base) throws Exception {
+    public void testVerifyUsesProvides(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
@@ -254,7 +254,7 @@
     }
 
     @Test
-    void testPackageNoModule(Path base) throws Exception {
+    public void testPackageNoModule(Path base) throws Exception {
         Path src = base.resolve("src");
         Path classes = base.resolve("classes");
 
--- a/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AnnotationProcessorsInModulesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -156,7 +156,7 @@
     Path classes;
 
     @Test
-    void testUseOnlyOneProcessor(Path base) throws Exception {
+    public void testUseOnlyOneProcessor(Path base) throws Exception {
         initialization(base);
         String log = new JavacTask(tb)
                 .options("-processormodulepath", processorCompiledModules.toString(),
@@ -172,7 +172,7 @@
     }
 
     @Test
-    void testAnnotationProcessorExecutionOrder(Path base) throws Exception {
+    public void testAnnotationProcessorExecutionOrder(Path base) throws Exception {
         initialization(base);
         List<String> log = new JavacTask(tb)
                 .options("-processormodulepath", processorCompiledModules.toString(),
@@ -202,7 +202,7 @@
     }
 
     @Test
-    void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception {
+    public void testErrorOutputIfOneProcessorNameIsIncorrect(Path base) throws Exception {
         initialization(base);
         String log = new JavacTask(tb)
                 .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
@@ -218,7 +218,7 @@
     }
 
     @Test
-    void testOptionsExclusion(Path base) throws Exception {
+    public void testOptionsExclusion(Path base) throws Exception {
         initialization(base);
         List<String> log = new JavacTask(tb)
                 .options("-XDrawDiagnostics", "-processormodulepath", processorCompiledModules.toString(),
--- a/langtools/test/tools/javac/modules/AutomaticModules.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/AutomaticModules.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,7 +48,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path legacySrc = base.resolve("legacy-src");
         tb.writeJavaFiles(legacySrc,
                           "package api; import java.awt.event.ActionListener; public abstract class Api implements ActionListener {}");
@@ -98,7 +98,7 @@
     }
 
     @Test
-    void testUnnamedModule(Path base) throws Exception {
+    public void testUnnamedModule(Path base) throws Exception {
         Path legacySrc = base.resolve("legacy-src");
         tb.writeJavaFiles(legacySrc,
                           "package api; public abstract class Api { public void run(CharSequence str) { } private void run(base.Base base) { } }",
@@ -156,7 +156,7 @@
     }
 
     @Test
-    void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
+    public void testModuleInfoFromClassFileDependsOnAutomatic(Path base) throws Exception {
         Path automaticSrc = base.resolve("automaticSrc");
         tb.writeJavaFiles(automaticSrc, "package api; public class Api {}");
         Path automaticClasses = base.resolve("automaticClasses");
--- a/langtools/test/tools/javac/modules/DoclintOtherModules.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/DoclintOtherModules.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,7 +47,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         Path m2 = src.resolve("m2");
--- a/langtools/test/tools/javac/modules/DuplicateClassTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/DuplicateClassTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,7 +47,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path m1 = base.resolve("m1");
         Path m2 = base.resolve("m2");
         tb.writeJavaFiles(m1,
--- a/langtools/test/tools/javac/modules/EdgeCases.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/EdgeCases.java	Wed Jul 05 21:39:33 2017 +0200
@@ -23,6 +23,7 @@
 
 /*
  * @test
+ * @bug 8154283
  * @summary tests for multi-module mode compilation
  * @library /tools/lib
  * @modules
@@ -57,7 +58,6 @@
 import toolbox.JarTask;
 import toolbox.JavacTask;
 import toolbox.Task;
-import toolbox.ToolBox;
 
 public class EdgeCases extends ModuleTestBase {
 
@@ -66,7 +66,7 @@
     }
 
     @Test
-    void testAddExportUndefinedModule(Path base) throws Exception {
+    public void testAddExportUndefinedModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "package test; import undef.Any; public class Test {}");
         Path classes = base.resolve("classes");
@@ -89,7 +89,7 @@
     }
 
     @Test
-    void testModuleSymbolOutterMostClass(Path base) throws Exception {
+    public void testModuleSymbolOutterMostClass(Path base) throws Exception {
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
             Path moduleSrc = base.resolve("module-src");
@@ -110,7 +110,7 @@
     }
 
     @Test
-    void testParseEnterAnalyze(Path base) throws Exception {
+    public void testParseEnterAnalyze(Path base) throws Exception {
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
             Path moduleSrc = base.resolve("module-src");
@@ -148,7 +148,7 @@
     }
 
     @Test
-    void testModuleImplicitModuleBoundaries(Path base) throws Exception {
+    public void testModuleImplicitModuleBoundaries(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1,
@@ -180,7 +180,7 @@
     }
 
     @Test
-    void testAssignClassToAutomaticModule(Path base) throws Exception {
+    public void testAssignClassToAutomaticModule(Path base) throws Exception {
         //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not
         //duplicated when being accessed through a classfile.
         Path automaticSrc = base.resolve("automaticSrc");
@@ -239,7 +239,7 @@
     }
 
     @Test
-    void testEmptyImplicitModuleInfo(Path base) throws Exception {
+    public void testEmptyImplicitModuleInfo(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         Files.createDirectories(src_m1);
@@ -269,4 +269,39 @@
 
     }
 
+    @Test
+    public void testClassPackageClash(Path base) throws Exception {
+        Path src = base.resolve("src");
+        Path src_m1 = src.resolve("m1");
+        tb.writeJavaFiles(src_m1,
+                          "module m1 { exports test.m1; }",
+                          "package test.m1;\n" +
+                          "public class Test {}\n");
+        Path src_m2 = src.resolve("m2");
+        tb.writeJavaFiles(src_m2,
+                          "module m2 { requires m1; }",
+                          "package test;\n" +
+                          "public class m1 {}\n");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log = new JavacTask(tb)
+                .options("-modulesourcepath", src.toString(),
+                         "-XDrawDiagnostics")
+                .outdir(classes)
+                .files(findJavaFiles(src))
+                .run(Task.Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> expected = Arrays.asList(
+            "m1.java:2:8: compiler.err.clash.with.pkg.of.same.name: kindname.class, test.m1",
+            "1 error"
+        );
+
+        if (!expected.equals(log)) {
+            throw new IllegalStateException(log.toString());
+        }
+    }
+
 }
--- a/langtools/test/tools/javac/modules/GraphsTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/GraphsTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,8 @@
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
+ *      ModuleTestBase
  * @run main GraphsTest
  */
 
@@ -41,6 +42,7 @@
 
 import toolbox.JarTask;
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
 import toolbox.ToolBox;
 
@@ -69,11 +71,11 @@
      *
      */
     @Test
-    void diamond(Path base) throws Exception {
+    public void diamond(Path base) throws Exception {
 
         Path modules = Files.createDirectories(base.resolve("modules"));
 
-        new ModuleBuilder("J")
+        new ModuleBuilder(tb, "J")
                 .exports("openJ")
                 .classes("package openJ; public class J { }")
                 .classes("package closedJ; public class J { }")
@@ -87,25 +89,25 @@
                 .run()
                 .writeAll();
 
-        new ModuleBuilder("O")
+        new ModuleBuilder(tb, "O")
                 .exports("openO")
                 .requiresPublic("J", jarModules)
                 .classes("package openO; public class O { openJ.J j; }")
                 .classes("package closedO; public class O { }")
                 .build(modules);
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .requiresPublic("O", modules, jarModules)
                 .exports("openN")
                 .classes("package openN; public class N { }")
                 .classes("package closedN; public class N { }")
                 .build(modules);
-        new ModuleBuilder("L")
+        new ModuleBuilder(tb, "L")
                 .requiresPublic("O", modules, jarModules)
                 .exports("openL")
                 .classes("package openL; public class L { }")
                 .classes("package closedL; public class L { }")
                 .build(modules);
-        ModuleBuilder m = new ModuleBuilder("M");
+        ModuleBuilder m = new ModuleBuilder(tb, "M");
         //positive case
         Path positiveSrc = m
                 .requires("N", modules)
@@ -178,14 +180,14 @@
     @Test
     public void reexportOfQualifiedExport(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "M")
                 .requiresPublic("N")
                 .write(modules);
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exportsTo("pack", "M")
                 .classes("package pack; public class Clazz { }")
                 .write(modules);
-        new ModuleBuilder("L")
+        new ModuleBuilder(tb, "L")
                 .requires("M")
                 .classes("package p; public class A { A(pack.Clazz cl){} } ")
                 .write(modules);
--- a/langtools/test/tools/javac/modules/HelloWorldTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/HelloWorldTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -58,7 +58,7 @@
         + HELLO_WORLD;
 
     @Test
-    void testLegacyMode(Path base) throws Exception {
+    public void testLegacyMode(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, HELLO_WORLD);
 
@@ -85,7 +85,7 @@
     }
 
     @Test
-    void testUnnamedModule(Path base) throws Exception {
+    public void testUnnamedModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, HELLO_WORLD);
 
@@ -101,7 +101,7 @@
     }
 
     @Test
-    void testSingleModule(Path base) throws Exception {
+    public void testSingleModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeFile(src.resolve("module-info.java"), "module m { }");
         tb.writeJavaFiles(src, PKG_HELLO_WORLD);
@@ -121,7 +121,7 @@
     }
 
     @Test
-    void testModuleSourcePath(Path base) throws Exception {
+    public void testModuleSourcePath(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
--- a/langtools/test/tools/javac/modules/MOptionTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/MOptionTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,7 +47,7 @@
     }
 
     @Test
-    void testOneModule(Path base) throws Exception {
+    public void testOneModule(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         Path build = base.resolve("build");
@@ -112,7 +112,7 @@
     }
 
     @Test
-    void testNoOutputDir(Path base) throws Exception {
+    public void testNoOutputDir(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         Path build = base.resolve("build");
@@ -135,7 +135,7 @@
     }
 
     @Test
-    void testNoModuleSourcePath(Path base) throws Exception {
+    public void testNoModuleSourcePath(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         Path build = base.resolve("build");
@@ -158,7 +158,7 @@
     }
 
     @Test
-    void testMultiModule(Path base) throws Exception {
+    public void testMultiModule(Path base) throws Exception {
         Path src = base.resolve("src");
         Path m1 = src.resolve("m1");
         Path m2 = src.resolve("m2");
--- a/langtools/test/tools/javac/modules/ModuleFinderTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModuleFinderTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,7 +48,7 @@
     }
 
     @Test
-    void testDuplicateModulesOnPath(Path base) throws Exception {
+    public void testDuplicateModulesOnPath(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m1 { }");
 
--- a/langtools/test/tools/javac/modules/ModuleInfoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModuleInfoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -51,7 +51,7 @@
      * Check error message if module declaration not in module-info.java.
      */
     @Test
-    void testModuleDeclNotInModuleJava(Path base) throws Exception {
+    public void testModuleDeclNotInModuleJava(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeFile(src.resolve("M.java"), "module M { }");
         String log = new JavacTask(tb)
@@ -69,7 +69,7 @@
      * Verify that a package private class can be put in module-info.java.
      */
     @Test
-    void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
+    public void testNotModuleDeclInModuleJava_1(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeFile(src.resolve("module-info.java"), "class C { }");
         new JavacTask(tb)
@@ -83,7 +83,7 @@
      * Verify that a public class cannot be put in module-info.java.
      */
     @Test
-    void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
+    public void testNotModuleDeclInModuleJava_2(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeFile(src.resolve("module-info.java"), "public class C { }");
         String log = new JavacTask(tb)
@@ -101,7 +101,7 @@
      * Verify that only one module decl can be put in module-info.java.
      */
     @Test
-    void testSingleModuleDecl(Path base) throws Exception {
+    public void testSingleModuleDecl(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module M1 { } /*...*/ module M2 { }");
         String log = new JavacTask(tb)
@@ -119,7 +119,7 @@
      * Verify that missing requires are reported.
      */
     @Test
-    void testRequiresNotFound(Path base) throws Exception {
+    public void testRequiresNotFound(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module M1 { requires M2; }");
         String log = new JavacTask(tb)
@@ -137,7 +137,7 @@
      * Verify that missing exports are reported.
      */
     @Test
-    void testExportsNotFound(Path base) throws Exception {
+    public void testExportsNotFound(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module M1 { exports p to M2; }");
         String log = new JavacTask(tb)
@@ -155,7 +155,7 @@
      * Verify that a simple loop is detected.
      */
     @Test
-    void testRequiresSelf(Path base) throws Exception {
+    public void testRequiresSelf(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module M { requires M; }");
         String log = new JavacTask(tb)
@@ -173,7 +173,7 @@
      * Verify that a multi-module loop is detected.
      */
     @Test
-    void testRequiresLoop(Path base) throws Exception {
+    public void testRequiresLoop(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
@@ -201,7 +201,7 @@
      * Verify that a multi-module loop is detected.
      */
     @Test
-    void testRequiresPublicLoop(Path base) throws Exception {
+    public void testRequiresPublicLoop(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { requires m2; }");
@@ -229,7 +229,7 @@
      * Verify that duplicate requires are detected.
      */
     @Test
-    void testDuplicateRequires(Path base) throws Exception {
+    public void testDuplicateRequires(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
@@ -255,7 +255,7 @@
      * Verify that duplicate exported packages are detected.
      */
     @Test
-    void testDuplicateExports_packages(Path base) throws Exception {
+    public void testDuplicateExports_packages(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m1 { exports p; exports p; }");
 
@@ -278,7 +278,7 @@
      * Verify that duplicate exported packages are detected.
      */
     @Test
-    void testDuplicateExports_packages2(Path base) throws Exception {
+    public void testDuplicateExports_packages2(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"), "module m1 { exports p; exports p to m2; }");
         tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
@@ -302,7 +302,7 @@
      * Verify that duplicate exported packages are detected.
      */
     @Test
-    void testDuplicateExports_modules(Path base) throws Exception {
+    public void testDuplicateExports_modules(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeFile(src_m1.resolve("module-info.java"), "module m1 { }");
--- a/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModuleInfoTreeAccess.java	Wed Jul 05 21:39:33 2017 +0200
@@ -61,7 +61,7 @@
     }
 
     @Test
-    void testTreePathForModuleDecl(Path base) throws Exception {
+    public void testTreePathForModuleDecl(Path base) throws Exception {
 
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
--- a/langtools/test/tools/javac/modules/ModulePathTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModulePathTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -30,7 +30,8 @@
  *      jdk.compiler/com.sun.tools.javac.main
  *      jdk.jdeps/com.sun.tools.javap
  *      jdk.jlink/jdk.tools.jmod
- * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.ModuleBuilder
+ *      ModuleTestBase
  * @run main ModulePathTest
  */
 
@@ -41,6 +42,7 @@
 
 import toolbox.JarTask;
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
 import toolbox.ToolBox;
 
@@ -54,7 +56,7 @@
     }
 
     @Test
-    void testNotExistsOnPath(Path base) throws Exception {
+    public void testNotExistsOnPath(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { }");
 
@@ -71,7 +73,7 @@
     }
 
     @Test
-    void testNotADirOnPath_1(Path base) throws Exception {
+    public void testNotADirOnPath_1(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { }");
         tb.writeFile("dummy.txt", "");
@@ -89,7 +91,7 @@
     }
 
     @Test
-    void testNotADirOnPath_2(Path base) throws Exception {
+    public void testNotADirOnPath_2(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { }");
         tb.writeFile("dummy.jimage", "");
@@ -107,7 +109,7 @@
     }
 
     @Test
-    void testExplodedModuleOnPath(Path base) throws Exception {
+    public void testExplodedModuleOnPath(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         tb.writeJavaFiles(modSrc,
                 "module m1 { exports p; }",
@@ -137,7 +139,7 @@
     }
 
     @Test
-    void testBadExplodedModuleOnPath(Path base) throws Exception {
+    public void testBadExplodedModuleOnPath(Path base) throws Exception {
         Path modClasses = base.resolve("modClasses");
         tb.writeFile(modClasses.resolve("module-info.class"), "module m1 { }");
 
@@ -162,7 +164,7 @@
     }
 
     @Test
-    void testAutoJarOnPath(Path base) throws Exception {
+    public void testAutoJarOnPath(Path base) throws Exception {
         Path jarSrc = base.resolve("jarSrc");
         tb.writeJavaFiles(jarSrc,
                 "package p; public class CC { }");
@@ -195,7 +197,7 @@
     }
 
     @Test
-    void testModJarOnPath(Path base) throws Exception {
+    public void testModJarOnPath(Path base) throws Exception {
         Path jarSrc = base.resolve("jarSrc");
         tb.writeJavaFiles(jarSrc,
                 "module m1 { exports p; }",
@@ -231,7 +233,7 @@
     }
 
     @Test
-    void testBadJarOnPath(Path base) throws Exception {
+    public void testBadJarOnPath(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { }");
         tb.writeFile("dummy.jar", "");
@@ -249,7 +251,7 @@
     }
 
     @Test
-    void testJModOnPath(Path base) throws Exception {
+    public void testJModOnPath(Path base) throws Exception {
         Path jmodSrc = base.resolve("jmodSrc");
         tb.writeJavaFiles(jmodSrc,
                 "module m1 { exports p; }",
@@ -282,7 +284,7 @@
     }
 
     @Test
-    void testBadJModOnPath(Path base) throws Exception {
+    public void testBadJModOnPath(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { }");
         tb.writeFile("dummy.jmod", "");
@@ -300,9 +302,9 @@
     }
 
     @Test
-    void relativePath(Path base) throws Exception {
+    public void relativePath(Path base) throws Exception {
         final Path modules = base.resolve("modules");
-        new ModuleBuilder("m1").build(modules);
+        new ModuleBuilder(tb, "m1").build(modules);
 
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -316,9 +318,9 @@
     }
 
     @Test
-    void duplicatePaths_1(Path base) throws Exception {
+    public void duplicatePaths_1(Path base) throws Exception {
         final Path modules = base.resolve("modules");
-        new ModuleBuilder("m1").build(modules);
+        new ModuleBuilder(tb, "m1").build(modules);
 
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -332,9 +334,9 @@
     }
 
     @Test
-    void duplicatePaths_2(Path base) throws Exception {
+    public void duplicatePaths_2(Path base) throws Exception {
         final Path modules = base.resolve("modules");
-        new ModuleBuilder("m1").build(modules);
+        new ModuleBuilder(tb, "m1").build(modules);
 
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m2 { requires m1; }", "class A { }");
@@ -349,15 +351,15 @@
     }
 
     @Test
-    void oneModuleHidesAnother(Path base) throws Exception {
+    public void oneModuleHidesAnother(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path deepModuleDir = module.resolve("deepModuleDir");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class E { }")
                 .build(deepModuleDir);
@@ -374,19 +376,19 @@
     }
 
     @Test
-    void modulesInDifferentContainers(Path base) throws Exception {
+    public void modulesInDifferentContainers(Path base) throws Exception {
         final Path modules = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("one")
                 .classes("package one; public class A { }")
                 .build(modules);
 
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .requires("m1", modules)
                 .build(base.resolve("tmp"));
         jar(base.resolve("tmp/m2"), modules.resolve("m2.jar"));
 
-        new ModuleBuilder("m3")
+        new ModuleBuilder(tb, "m3")
                 .requires("m2", modules)
                 .build(base.resolve("tmp"));
         jmod(base.resolve("tmp/m3"), modules.resolve("m3.jmod"));
--- a/langtools/test/tools/javac/modules/ModuleSourcePathTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModuleSourcePathTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -56,7 +56,7 @@
     }
 
     @Test
-    void testSourcePathConflict(Path base) throws Exception {
+    public void testSourcePathConflict(Path base) throws Exception {
         Path sp = base.resolve("src");
         Path msp = base.resolve("srcmodules");
 
@@ -74,7 +74,7 @@
     }
 
     @Test
-    void testUnnormalizedPath1(Path base) throws Exception {
+    public void testUnnormalizedPath1(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -91,7 +91,7 @@
     }
 
     @Test
-    void testUnnormalizedPath2(Path base) throws Exception {
+    public void testUnnormalizedPath2(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -115,7 +115,7 @@
     }
 
     @Test
-    void regularBraces(Path base) throws Exception {
+    public void regularBraces(Path base) throws Exception {
         generateModules(base, "src1", "src2/inner_dir");
 
         final Path modules = base.resolve("modules");
@@ -136,7 +136,7 @@
     }
 
     @Test
-    void mismatchedBraces(Path base) throws Exception {
+    public void mismatchedBraces(Path base) throws Exception {
         final List<String> sourcePaths = Arrays.asList(
                 "{",
                 "}",
@@ -165,7 +165,7 @@
     }
 
     @Test
-    void deepBraces(Path base) throws Exception {
+    public void deepBraces(Path base) throws Exception {
         String[] modulePaths = {"src/src1",
                 "src/src2",
                 "src/src3",
@@ -197,7 +197,7 @@
     }
 
     @Test
-    void fileInPath(Path base) throws Exception {
+    public void fileInPath(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
         tb.writeFile(base.resolve("dummy.txt"), "");
@@ -218,7 +218,7 @@
     }
 
     @Test
-    void noAlternative(Path base) throws Exception {
+    public void noAlternative(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
 
@@ -238,7 +238,7 @@
     }
 
     @Test
-    void noChoice(Path base) throws Exception {
+    public void noChoice(Path base) throws Exception {
         tb.writeJavaFiles(base.resolve("kettle$"), "module kettle$ { }", "package electric; class Heater { }");
 
         final Path modules = base.resolve("modules");
@@ -257,7 +257,7 @@
     }
 
     @Test
-    void nestedModules(Path src) throws Exception {
+    public void nestedModules(Path src) throws Exception {
         Path carModule = src.resolve("car");
         tb.writeJavaFiles(carModule, "module car { }", "package light; class Headlight { }");
         tb.writeJavaFiles(carModule.resolve("engine"), "module engine { }", "package flat; class Piston { }");
@@ -277,7 +277,7 @@
     }
 
     @Test
-    void relativePaths(Path base) throws Exception {
+    public void relativePaths(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("kettle"), "module kettle { }", "package electric; class Heater { }");
 
@@ -296,7 +296,7 @@
     }
 
     @Test
-    void duplicatePaths(Path base) throws Exception {
+    public void duplicatePaths(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
 
@@ -315,7 +315,7 @@
     }
 
     @Test
-    void notExistentPaths(Path base) throws Exception {
+    public void notExistentPaths(Path base) throws Exception {
         tb.writeJavaFiles(base.resolve("m1"), "module m1 { requires m0; }", "package a; class A { }");
 
         final Path modules = base.resolve("modules");
@@ -334,7 +334,7 @@
     }
 
     @Test
-    void notExistentPathShouldBeSkipped(Path base) throws Exception {
+    public void notExistentPathShouldBeSkipped(Path base) throws Exception {
         tb.writeJavaFiles(base.resolve("m1"), "module m1 { }", "package a; class A { }");
 
         final Path modules = base.resolve("modules");
@@ -352,7 +352,7 @@
     }
 
     @Test
-    void commas(Path base) throws Exception {
+    public void commas(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"), "module m1 { }", "package a; class A { }");
 
@@ -371,7 +371,7 @@
     }
 
     @Test
-    void asterisk(Path base) throws Exception {
+    public void asterisk(Path base) throws Exception {
         tb.writeJavaFiles(base.resolve("kettle").resolve("classes"), "module kettle { }",
                 "package electric; class Heater { }");
 
@@ -391,7 +391,7 @@
     }
 
     @Test
-    void asteriskInDifferentSets(Path base) throws Exception {
+    public void asteriskInDifferentSets(Path base) throws Exception {
         Path src = base.resolve("src");
         final Path module = src.resolve("kettle");
         tb.writeJavaFiles(module.resolve("classes"), "module kettle { }", "package electric; class Heater { }");
@@ -417,7 +417,7 @@
     }
 
     @Test
-    void asteriskIllegalUse(Path base) throws Exception {
+    public void asteriskIllegalUse(Path base) throws Exception {
         final List<String> sourcePaths = Arrays.asList(
                 "*",
                 "**",
--- a/langtools/test/tools/javac/modules/ModuleTestBase.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModuleTestBase.java	Wed Jul 05 21:39:33 2017 +0200
@@ -43,19 +43,20 @@
 import java.util.stream.Collectors;
 
 import toolbox.JavacTask;
+import toolbox.TestRunner;
 import toolbox.ToolBox;
 
 /**
  * Base class for module tests.
  */
-public class ModuleTestBase {
+public class ModuleTestBase extends TestRunner {
     protected ToolBox tb;
-    protected PrintStream out;
     private int errors;
 
-    /** Marker annotation for test methods to be invoked by runTests. */
-    @Retention(RetentionPolicy.RUNTIME)
-    @interface Test { }
+    ModuleTestBase() {
+        super(System.err);
+        tb = new ToolBox();
+    }
 
     /**
      * Run all methods annotated with @Test, and throw an exception if any
@@ -63,47 +64,12 @@
      *
      * @throws Exception if any errors occurred
      */
-    void runTests() throws Exception {
-        if (tb == null)
-            tb = new ToolBox();
-        out = System.err;
-
-        for (Method m: getClass().getDeclaredMethods()) {
-            Annotation a = m.getAnnotation(Test.class);
-            if (a != null) {
-                try {
-                    out.println("Running test " + m.getName());
-                    Path baseDir = Paths.get(m.getName());
-                    m.invoke(this, new Object[] { baseDir });
-                } catch (InvocationTargetException e) {
-                    Throwable cause = e.getCause();
-                    error("Exception: " + e.getCause());
-                    cause.printStackTrace(out);
-                }
-                out.println();
-            }
-        }
-        if (errors > 0)
-            throw new Exception(errors + " errors occurred");
+    protected void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()) });
     }
 
-    // move to ToolBox?
-    // change returntyp to List<Path> -- means updating ToolBox methods
     Path[] findJavaFiles(Path... paths) throws IOException {
-        Set<Path> files = new TreeSet<>();
-        for (Path p : paths) {
-            Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
-                @Override
-                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
-                        throws IOException {
-                    if (file.getFileName().toString().endsWith(".java")) {
-                        files.add(file);
-                    }
-                    return FileVisitResult.CONTINUE;
-                }
-            });
-        }
-        return files.toArray(new Path[files.size()]);
+        return tb.findJavaFiles(paths);
     }
 
     void error(String message) {
@@ -111,79 +77,4 @@
         errors++;
     }
 
-    public class ModuleBuilder {
-
-        private final String name;
-        private String requires = "";
-        private String exports = "";
-        private String uses = "";
-        private String provides = "";
-        private String modulePath = "";
-        private List<String> content = new ArrayList<>();
-
-        public ModuleBuilder(String name) {
-            this.name = name;
-        }
-
-        public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
-            return requires("public " + requires, modulePath);
-        }
-
-        public ModuleBuilder requires(String requires, Path... modulePath) {
-            this.requires += "    requires " + requires + ";\n";
-            this.modulePath += Arrays.stream(modulePath)
-                    .map(Path::toString)
-                    .collect(Collectors.joining(File.pathSeparator));
-            return this;
-        }
-
-        public ModuleBuilder exportsTo(String pkg, String module) {
-            return exports(pkg + " to " + module);
-        }
-
-        public ModuleBuilder exports(String pkg) {
-            this.exports += "    exports " + pkg + ";\n";
-            return this;
-        }
-
-        public ModuleBuilder uses(String uses) {
-            this.uses += "    uses " + uses + ";\n";
-            return this;
-        }
-
-        public ModuleBuilder provides(String service, String implementation) {
-            this.provides += "    provides " + service + " with " + implementation + ";\n";
-            return this;
-        }
-
-        public ModuleBuilder classes(String... content) {
-            this.content.addAll(Arrays.asList(content));
-            return this;
-        }
-
-        public Path write(Path where) throws IOException {
-            Files.createDirectories(where);
-            List<String> sources = new ArrayList<>();
-            sources.add("module " + name + "{"
-                    + requires
-                    + exports
-                    + uses
-                    + provides
-                    + "}");
-            sources.addAll(content);
-            Path moduleSrc = where.resolve(name + "/src");
-            tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
-            return moduleSrc;
-        }
-
-        public void build(Path where) throws IOException {
-            Path moduleSrc = write(where);
-            new JavacTask(tb)
-                    .outdir(where.resolve(name))
-                    .options("-mp", modulePath)
-                    .files(findJavaFiles(moduleSrc))
-                    .run()
-                    .writeAll();
-        }
-    }
 }
--- a/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ModulesAndClassPathTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -55,7 +55,7 @@
     }
 
     @Test
-    void testModulesAndClassPath(Path base) throws Exception {
+    public void testModulesAndClassPath(Path base) throws Exception {
         Path jar = prepareTestJar(base);
 
         Path moduleSrc = base.resolve("module-src");
@@ -106,7 +106,7 @@
     }
 
     @Test
-    void testImplicitSourcePathModuleInfo(Path base) throws Exception {
+    public void testImplicitSourcePathModuleInfo(Path base) throws Exception {
         Path jar = prepareTestJar(base);
 
         Path moduleSrc = base.resolve("module-src");
@@ -139,7 +139,7 @@
     }
 
     @Test
-    void testModuleInfoFromOutput(Path base) throws Exception {
+    public void testModuleInfoFromOutput(Path base) throws Exception {
         Path jar = prepareTestJar(base);
 
         Path moduleSrc = base.resolve("module-src");
@@ -221,7 +221,7 @@
     }
 
     @Test
-    void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
+    public void testClassOutputVisibleForIncrementalCompilation(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
--- a/langtools/test/tools/javac/modules/MultiModuleModeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/MultiModuleModeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -49,7 +49,7 @@
     }
 
     @Test
-    void testDuplicateModules(Path base) throws Exception {
+    public void testDuplicateModules(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -72,7 +72,7 @@
     }
 
     @Test
-    void testCantFindModule(Path base) throws Exception {
+    public void testCantFindModule(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1, "module m1 { }");
@@ -95,7 +95,7 @@
     }
 
     @Test
-    void testModuleNameMismatch(Path base) throws Exception {
+    public void testModuleNameMismatch(Path base) throws Exception {
         Path src = base.resolve("src");
         Path src_m1 = src.resolve("m1");
         tb.writeJavaFiles(src_m1, "module m2 { }");
@@ -116,7 +116,7 @@
     }
 
     @Test
-    void testImplicitModuleSource(Path base) throws Exception {
+    public void testImplicitModuleSource(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
         tb.writeJavaFiles(src.resolve("m2"), "module m2 { requires m1; }");
@@ -132,7 +132,7 @@
     }
 
     @Test
-    void testImplicitModuleClass(Path base) throws Exception {
+    public void testImplicitModuleClass(Path base) throws Exception {
         Path src1 = base.resolve("src1");
         tb.writeJavaFiles(src1.resolve("m1"), "module m1 { }");
         Path modules1 = base.resolve("modules1");
--- a/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/NPECompilingModuleInfoTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -45,7 +45,7 @@
     }
 
     @Test
-    void testCompileNoError(Path base) throws Exception {
+    public void testCompileNoError(Path base) throws Exception {
         Path mod = base.resolve("mod");
         tb.writeJavaFiles(mod, "module mod { exports pkg; }");
         Path pkg = mod.resolve("pkg");
--- a/langtools/test/tools/javac/modules/NPEEmptyFileTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/NPEEmptyFileTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -45,7 +45,7 @@
     }
 
     @Test
-    void compileEmptyFile(Path base) throws Exception {
+    public void compileEmptyFile(Path base) throws Exception {
         Path modules = base.resolve("modules");
         Files.createDirectories(modules);
         Path emptyJavaFile = base.resolve("Test.java");
--- a/langtools/test/tools/javac/modules/OutputDirTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/OutputDirTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -60,7 +60,7 @@
     }
 
     @Test
-    void testError(Path base) throws Exception {
+    public void testError(Path base) throws Exception {
         String log = new JavacTask(tb)
                 .options("-XDrawDiagnostics",
                         "-modulesourcepath", src.toString())
@@ -74,7 +74,7 @@
     }
 
     @Test
-    void testProcOnly(Path base) throws IOException {
+    public void testProcOnly(Path base) throws IOException {
         new JavacTask(tb)
                 .options("-XDrawDiagnostics",
                         "-proc:only",
@@ -85,7 +85,7 @@
     }
 
     @Test
-    void testClassOutDir(Path base) throws IOException {
+    public void testClassOutDir(Path base) throws IOException {
         Path classes = base.resolve("classes");
         new JavacTask(tb)
                 .options("-XDrawDiagnostics",
@@ -97,7 +97,7 @@
     }
 
     @Test
-    void testExplodedOutDir(Path base) throws Exception {
+    public void testExplodedOutDir(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         tb.writeJavaFiles(modSrc,
                 "module m1 { exports p; }",
@@ -131,7 +131,7 @@
     }
 
     @Test
-    void testInExplodedOutDir(Path base) throws Exception {
+    public void testInExplodedOutDir(Path base) throws Exception {
         Path modSrc = base.resolve("modSrc");
         tb.writeJavaFiles(modSrc,
                 "module m1 { exports p; }",
--- a/langtools/test/tools/javac/modules/PackageConflictTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/PackageConflictTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,7 @@
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main PackageConflictTest
  */
 
@@ -38,6 +38,7 @@
 import java.util.List;
 
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
 import toolbox.ToolBox;
 
@@ -48,7 +49,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "package java.util; public class MyList { }");
@@ -68,7 +69,7 @@
     }
 
     @Test
-    void testDisjoint(Path base) throws Exception {
+    public void testDisjoint(Path base) throws Exception {
         Path m1 = base.resolve("m1");
         Path m2 = base.resolve("m2");
         tb.writeJavaFiles(m1,
@@ -89,7 +90,7 @@
     }
 
     @Test
-    void testConflictInDependencies(Path base) throws Exception {
+    public void testConflictInDependencies(Path base) throws Exception {
         Path m1 = base.resolve("m1");
         Path m2 = base.resolve("m2");
         Path m3 = base.resolve("m3");
@@ -123,13 +124,13 @@
     }
 
     @Test
-    void testSimple2(Path base) throws Exception {
+    public void testSimple2(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exports("pack")
                 .classes("package pack; public class A { }")
                 .build(modules);
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "M")
                 .requires("N")
                 .classes("package pack; public class B { pack.A f; }")
                 .write(modules);
@@ -147,14 +148,14 @@
     }
 
     @Test
-    void testPrivateConflict(Path base) throws Exception {
+    public void testPrivateConflict(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exports("publ")
                 .classes("package pack; public class A { }")
                 .classes("package publ; public class B { }")
                 .write(modules);
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "M")
                 .requires("N")
                 .classes("package pack; public class C { publ.B b; }")
                 .write(modules);
@@ -173,14 +174,14 @@
     }
 
     @Test
-    void testPrivateConflictOnModulePath(Path base) throws Exception {
+    public void testPrivateConflictOnModulePath(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exports("publ")
                 .classes("package pack; public class A { }")
                 .classes("package publ; public class B { }")
                 .build(modules);
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "M")
                 .requires("N")
                 .classes("package pack; public class C { publ.B b; }")
                 .write(modules);
@@ -199,17 +200,17 @@
     }
 
     @Test
-    void testRequiresConflictExports(Path base) throws Exception {
+    public void testRequiresConflictExports(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "M")
                 .exports("pack")
                 .classes("package pack; public class A { }")
                 .build(modules);
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exports("pack")
                 .classes("package pack; public class B { }")
                 .build(modules);
-        new ModuleBuilder("K")
+        new ModuleBuilder(tb, "K")
                 .requires("M")
                 .requires("N")
                 .classes("package pkg; public class C { pack.A a; pack.B b; }")
@@ -231,18 +232,18 @@
     }
 
     @Test
-    void testQulifiedExportsToDifferentModules(Path base) throws Exception {
+    public void testQulifiedExportsToDifferentModules(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("U").write(modules);
-        new ModuleBuilder("M")
+        new ModuleBuilder(tb, "U").write(modules);
+        new ModuleBuilder(tb, "M")
                 .exports("pkg to U")
                 .classes("package pkg; public class A { public static boolean flagM; }")
                 .write(modules);
-        new ModuleBuilder("N")
+        new ModuleBuilder(tb, "N")
                 .exports("pkg to K")
                 .classes("package pkg; public class A { public static boolean flagN; }")
                 .write(modules);
-        ModuleBuilder moduleK = new ModuleBuilder("K");
+        ModuleBuilder moduleK = new ModuleBuilder(tb, "K");
         moduleK.requires("M")
                 .requires("N")
                 .classes("package p; public class DependsOnN { boolean f = pkg.A.flagN; } ")
--- a/langtools/test/tools/javac/modules/PackageMultipleModules.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/PackageMultipleModules.java	Wed Jul 05 21:39:33 2017 +0200
@@ -49,7 +49,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path m1 = base.resolve("m1");
         Path m2 = base.resolve("m2");
         tb.writeJavaFiles(m1,
--- a/langtools/test/tools/javac/modules/PluginsInModulesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/PluginsInModulesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -127,7 +127,7 @@
     Path classes;
 
     @Test
-    void testUseOnlyOneProcessor(Path base) throws Exception {
+    public void testUseOnlyOneProcessor(Path base) throws Exception {
         initialization(base);
         List<String> log = new JavacTask(tb)
                 .options("-processormodulepath", processorCompiledModules.toString(),
--- a/langtools/test/tools/javac/modules/ProvidesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ProvidesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,7 +48,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; }",
@@ -65,7 +65,7 @@
     }
 
     @Test
-    void testMulti(Path base) throws Exception {
+    public void testMulti(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1; }",
@@ -86,7 +86,7 @@
     }
 
     @Test
-    void testMissingWith(Path base) throws Exception {
+    public void testMissingWith(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.C; }",
@@ -108,7 +108,7 @@
     }
 
     @Test
-    void testDuplicateProvides(Path base) throws Exception {
+    public void testDuplicateProvides(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
@@ -126,7 +126,7 @@
     }
 
     @Test
-    void testMissingService(Path base) throws Exception {
+    public void testMissingService(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.Missing with p.C; }",
@@ -151,7 +151,7 @@
     }
 
     @Test
-    void testProvidesFromAnotherModule(Path base) throws Exception {
+    public void testProvidesFromAnotherModule(Path base) throws Exception {
         Path modules = base.resolve("modules");
         tb.writeJavaFiles(modules.resolve("M"),
                 "module M { exports p; }",
@@ -177,7 +177,7 @@
     }
 
     @Test
-    void testServiceIsNotImplemented(Path base) throws Exception {
+    public void testServiceIsNotImplemented(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.A with p.B; }",
@@ -200,7 +200,7 @@
     }
 
     @Test
-    void testMissingImplementation(Path base) throws Exception {
+    public void testMissingImplementation(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.C with p.Impl; }",
@@ -222,7 +222,7 @@
     }
 
     @Test
-    void testSeveralImplementations(Path base) throws Exception {
+    public void testSeveralImplementations(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.C with p.Impl1; provides p.C with p.Impl2; }",
@@ -238,7 +238,7 @@
     }
 
     @Test
-    void testOneImplementationsForServices(Path base) throws Exception {
+    public void testOneImplementationsForServices(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p.Service1 with p.Impl; provides p.Service2 with p.Impl; }",
@@ -254,7 +254,7 @@
     }
 
     @Test
-    void testAbstractImplementation(Path base) throws Exception {
+    public void testAbstractImplementation(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; }",
@@ -277,7 +277,7 @@
     }
 
     @Test
-    void testInterfaceImplementation(Path base) throws Exception {
+    public void testInterfaceImplementation(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.Service with p2.Impl; }",
@@ -300,7 +300,7 @@
     }
 
     @Test
-    void testProtectedImplementation(Path base) throws Exception {
+    public void testProtectedImplementation(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; }",
@@ -323,7 +323,7 @@
     }
 
     @Test
-    void testNoNoArgConstructor(Path base) throws Exception {
+    public void testNoNoArgConstructor(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
@@ -346,7 +346,7 @@
     }
 
     @Test
-    void testPrivateNoArgConstructor(Path base) throws Exception {
+    public void testPrivateNoArgConstructor(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p1.C1; provides p1.C1 with p2.C2; }",
@@ -369,7 +369,7 @@
     }
 
     @Test
-    void testServiceIndirectlyImplemented(Path base) throws Exception {
+    public void testServiceIndirectlyImplemented(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C3; }",
@@ -385,7 +385,7 @@
     }
 
     @Test
-    void testServiceImplementationInnerClass(Path base) throws Exception {
+    public void testServiceImplementationInnerClass(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2.Inner; }",
@@ -408,7 +408,7 @@
     }
 
     @Test
-    void testServiceDefinitionInnerClass(Path base) throws Exception {
+    public void testServiceDefinitionInnerClass(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1.InnerDefinition with p2.C2; }",
--- a/langtools/test/tools/javac/modules/QueryBeforeEnter.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/QueryBeforeEnter.java	Wed Jul 05 21:39:33 2017 +0200
@@ -65,7 +65,7 @@
     }
 
     @Test
-    void testEmpty(Path base) throws Exception {
+    public void testEmpty(Path base) throws Exception {
         JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
         com.sun.source.util.JavacTask task =
             (com.sun.source.util.JavacTask) javaCompiler.getTask(null, null, null, null, null, null);
@@ -75,7 +75,7 @@
     }
 
     @Test
-    void testUnnamed(Path base) throws Exception {
+    public void testUnnamed(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
@@ -151,7 +151,7 @@
     }
 
     @Test
-    void testSingleNamed(Path base) throws Exception {
+    public void testSingleNamed(Path base) throws Exception {
         Path moduleSrc = base.resolve("module-src");
         Path m1 = moduleSrc.resolve("m1");
 
@@ -226,7 +226,7 @@
     }
 
     @Test
-    void testMultiModule(Path base) throws Exception {
+    public void testMultiModule(Path base) throws Exception {
         Path modulePathSrc = base.resolve("module-path-src");
         Path m1 = modulePathSrc.resolve("m1");
 
@@ -311,7 +311,7 @@
     }
 
     @Test
-    void testTooSoon(Path base) throws Exception {
+    public void testTooSoon(Path base) throws Exception {
         Path src = base.resolve("src");
 
         tb.writeJavaFiles(src,
--- a/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/RepeatedUsesAndProvidesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -46,7 +46,7 @@
     }
 
     @Test
-    void testDuplicateUses(Path base) throws Exception {
+    public void testDuplicateUses(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p1.C1; uses p1.C1; }",
@@ -66,7 +66,7 @@
     }
 
     @Test
-    void testDuplicateProvides(Path base) throws Exception {
+    public void testDuplicateProvides(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; provides p1.C1 with p2.C2; }",
--- a/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ReportNonExistentPackageTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -46,7 +46,7 @@
     }
 
     @Test
-    void testExportUnknownPackage(Path base) throws Exception {
+    public void testExportUnknownPackage(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m { exports p1; }");
         Path classes = base.resolve("classes");
@@ -64,7 +64,7 @@
     }
 
     @Test
-    void testExportEmptyPackage(Path base) throws Exception {
+    public void testExportEmptyPackage(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { exports p1; }",
@@ -84,7 +84,7 @@
     }
 
     @Test
-    void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception {
+    public void testPackageWithMemberWOPackageDeclaration(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "module m { exports p1; }");
         Path p1 = src.resolve("p1");
--- a/langtools/test/tools/javac/modules/RequiresPublicTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/RequiresPublicTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,7 +47,7 @@
     }
 
     @Test
-    void testJavaSE_OK(Path base) throws Exception {
+    public void testJavaSE_OK(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { requires java.se; }",
@@ -66,7 +66,7 @@
     }
 
     @Test
-    void testJavaSE_Fail(Path base) throws Exception {
+    public void testJavaSE_Fail(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { requires java.se; }",
@@ -90,7 +90,7 @@
     }
 
     @Test
-    void testComplex_OK(Path base) throws Exception {
+    public void testComplex_OK(Path base) throws Exception {
         Path src = getComplexSrc(base, "", "");
         Path classes = base.resolve("classes");
         Files.createDirectories(classes);
@@ -104,7 +104,7 @@
     }
 
     @Test
-    void testComplex_Fail(Path base) throws Exception {
+    public void testComplex_Fail(Path base) throws Exception {
         Path src = getComplexSrc(base,
                 "import p5.C5; import p6.C6; import p7.C7;\n",
                 "C5 c5; C6 c6; C7 c7;\n");
--- a/langtools/test/tools/javac/modules/ResolveTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ResolveTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -45,7 +45,7 @@
     }
 
     @Test
-    void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
+    public void testMissingSimpleTypeUnnamedModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "class C { D d; }");
 
@@ -62,7 +62,7 @@
     }
 
     @Test
-    void testMissingSimpleTypeNamedModule(Path base) throws Exception {
+    public void testMissingSimpleTypeNamedModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { }",
@@ -81,7 +81,7 @@
     }
 
     @Test
-    void testUnexportedTypeUnreadableModule(Path base) throws Exception {
+    public void testUnexportedTypeUnreadableModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { }",
@@ -105,7 +105,7 @@
     }
 
     @Test
-    void testUnexportedTypeReadableModule(Path base) throws Exception {
+    public void testUnexportedTypeReadableModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { }",
@@ -129,7 +129,7 @@
     }
 
     @Test
-    void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
+    public void testQualifiedExportedTypeReadableModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1 to m3; }",
@@ -155,7 +155,7 @@
     }
 
     @Test
-    void testExportedTypeUnreadableModule(Path base) throws Exception {
+    public void testExportedTypeUnreadableModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1; }",
@@ -179,7 +179,7 @@
     }
 
     @Test
-    void testExportedTypeReadableModule(Path base) throws Exception {
+    public void testExportedTypeReadableModule(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1; }",
@@ -199,7 +199,7 @@
     }
 
     @Test
-    void testExportedTypeReadableModule2(Path base) throws Exception {
+    public void testExportedTypeReadableModule2(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1 to m2; }",
--- a/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ServiceInStaticClassErrorTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -48,7 +48,7 @@
     }
 
     @Test
-    void testError(Path base) throws Exception {
+    public void testError(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.I with p1.Outer.A; }",
--- a/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/ServiceProvidedButNotExportedOrUsedTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -49,7 +49,7 @@
     }
 
     @Test
-    void testWarning(Path base) throws Exception {
+    public void testWarning(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { provides p1.C1 with p2.C2; }",
@@ -76,7 +76,7 @@
     }
 
     @Test
-    void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception {
+    public void testImplementationMustBeInSameModuleAsProvidesDirective(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p1; }",
--- a/langtools/test/tools/javac/modules/SingleModuleModeTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/SingleModuleModeTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -59,7 +59,7 @@
     }
 
     @Test
-    void testTooManyModules(Path base) throws Exception {
+    public void testTooManyModules(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"), "module m1 { }");
         tb.writeJavaFiles(src.resolve("m2"), "module m2 { }");
@@ -76,7 +76,7 @@
     }
 
     @Test
-    void testImplicitModuleSource(Path base) throws Exception {
+    public void testImplicitModuleSource(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { }",
@@ -90,7 +90,7 @@
     }
 
     @Test
-    void testImplicitModuleClass(Path base) throws Exception {
+    public void testImplicitModuleClass(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { }",
@@ -112,7 +112,7 @@
     }
 
     @Test
-    void testImplicitModuleClassAP(Path base) throws Exception {
+    public void testImplicitModuleClassAP(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses java.lang.Runnable; }",
@@ -137,7 +137,7 @@
     }
 
     @Test
-    void testImplicitModuleSourceAP(Path base) throws Exception {
+    public void testImplicitModuleSourceAP(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses java.lang.Runnable; }",
--- a/langtools/test/tools/javac/modules/SubpackageTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/SubpackageTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -52,7 +52,7 @@
     }
 
     @Test // based on JDK-8075435
-    void testUnnamedModule(Path base) throws Exception {
+    public void testUnnamedModule(Path base) throws Exception {
         Path libsrc = base.resolve("lib/src");
         tb.writeJavaFiles(libsrc,
             "package p; public class E extends Error { }");
@@ -83,7 +83,7 @@
     }
 
     @Test
-    void testSimpleMulti(Path base) throws Exception {
+    public void testSimpleMulti(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("mp"),
                 "module mp { exports p; }",
--- a/langtools/test/tools/javac/modules/UpgradeModulePathTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/UpgradeModulePathTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,7 @@
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main UpgradeModulePathTest
  */
 
@@ -36,6 +36,7 @@
 import java.nio.file.Path;
 
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
 import toolbox.ToolBox;
 
@@ -47,15 +48,15 @@
     }
 
     @Test
-    void simpleUsage(Path base) throws Exception {
+    public void simpleUsage(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path upgradeModule = base.resolve("upgradeModule");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class E { }")
                 .build(upgradeModule);
@@ -73,15 +74,15 @@
     }
 
     @Test
-    void onlyUpgradeModulePath(Path base) throws Exception {
+    public void onlyUpgradeModulePath(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path upgradeModule = base.resolve("upgradeModule");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class E { }")
                 .build(upgradeModule);
@@ -98,15 +99,15 @@
     }
 
     @Test
-    void withModuleSourcePath(Path base) throws Exception {
+    public void withModuleSourcePath(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path upgradeModule = base.resolve("upgradeModule");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class E { }")
                 .build(upgradeModule);
@@ -115,7 +116,7 @@
         tb.writeJavaFiles(s.resolve("m3"), "module m3 { }");
 
         final Path upgradeModule3 = base.resolve("upgradeModule");
-        new ModuleBuilder("m3")
+        new ModuleBuilder(tb, "m3")
                 .exports("pkg3")
                 .classes("package pkg3; public class E { }")
                 .build(upgradeModule);
@@ -135,15 +136,15 @@
     }
 
     @Test
-    void sameUpgradeAndModulePath(Path base) throws Exception {
+    public void sameUpgradeAndModulePath(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path upgradeModule = base.resolve("upgradeModule");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class E { }")
                 .build(upgradeModule);
@@ -161,9 +162,9 @@
     }
 
     @Test
-    void dummyFileInUpgradeModulePath(Path base) throws Exception {
+    public void dummyFileInUpgradeModulePath(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
@@ -189,24 +190,24 @@
     }
 
     @Test
-    void severalUpgradeModules(Path base) throws Exception {
+    public void severalUpgradeModules(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class A { }")
                 .build(module);
 
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .exports("pkg2")
                 .classes("package pkg2; public class B { }")
                 .build(module);
 
         Path upgradeModule = base.resolve("upgradeModule");
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .exports("pkg2")
                 .classes("package pkg2; public class BC { }")
                 .build(upgradeModule);
-        new ModuleBuilder("m3")
+        new ModuleBuilder(tb, "m3")
                 .exports("pkg3")
                 .classes("package pkg3; public class DC { }")
                 .build(upgradeModule);
@@ -240,21 +241,21 @@
     }
 
     @Test
-    void severalUpgradeModulePathsLastWin(Path base) throws Exception {
+    public void severalUpgradeModulePathsLastWin(Path base) throws Exception {
         final Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg1")
                 .classes("package pkg1; public class E { }")
                 .build(module);
 
         final Path upgradeModule1 = base.resolve("upgradeModule1");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class EC1 { }")
                 .build(upgradeModule1);
 
         final Path upgradeModule2 = base.resolve("upgradeModule2");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("pkg2")
                 .classes("package pkg2; public class EC2 { }")
                 .build(upgradeModule2);
--- a/langtools/test/tools/javac/modules/UsesTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/UsesTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,7 @@
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main UsesTest
  */
 
@@ -39,6 +39,7 @@
 import java.util.List;
 
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
 import toolbox.ToolBox;
 
@@ -49,7 +50,7 @@
     }
 
     @Test
-    void testSimple(Path base) throws Exception {
+    public void testSimple(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p.C; }",
@@ -65,7 +66,7 @@
     }
 
     @Test
-    void testSimpleInner(Path base) throws Exception {
+    public void testSimpleInner(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p.C.Inner; }",
@@ -81,7 +82,7 @@
     }
 
     @Test
-    void testSimpleAnnotation(Path base) throws Exception {
+    public void testSimpleAnnotation(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p.C; }",
@@ -97,7 +98,7 @@
     }
 
     @Test
-    void testPrivateService(Path base) throws Exception {
+    public void testPrivateService(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p.C.A; uses p.C; }",
@@ -119,7 +120,7 @@
     }
 
     @Test
-    void testMulti(Path base) throws Exception {
+    public void testMulti(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { exports p; }",
@@ -138,13 +139,13 @@
     }
 
     @Test
-    void testMultiOnModulePath(Path base) throws Exception {
+    public void testMultiOnModulePath(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("p")
                 .classes("package p; public class C { }")
                 .build(modules);
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .requires("m1")
                 .uses("p.C")
                 .write(modules);
@@ -158,13 +159,13 @@
     }
 
     @Test
-    void testMultiOnModulePathInner(Path base) throws Exception {
+    public void testMultiOnModulePathInner(Path base) throws Exception {
         Path modules = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .exports("p")
                 .classes("package p; public class C { public class Inner { } }")
                 .build(modules);
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .requires("m1")
                 .uses("p.C.Inner")
                 .write(modules);
@@ -178,7 +179,7 @@
     }
 
     @Test
-    void testDuplicateUses(Path base) throws Exception {
+    public void testDuplicateUses(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m"),
                 "module m { uses p.C; uses p.C; }",
@@ -199,7 +200,7 @@
     }
 
     @Test
-    void testServiceNotExist(Path base) throws Exception {
+    public void testServiceNotExist(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
                 "module m { uses p.NotExist; }",
@@ -220,7 +221,7 @@
     }
 
     @Test
-    void testUsesUnexportedService(Path base) throws Exception {
+    public void testUsesUnexportedService(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { }",
@@ -244,7 +245,7 @@
     }
 
     @Test
-    void testUsesUnexportedButProvidedService(Path base) throws Exception {
+    public void testUsesUnexportedButProvidedService(Path base) throws Exception {
         Path src = base.resolve("src");
         tb.writeJavaFiles(src.resolve("m1"),
                 "module m1 { provides p.C with p.C; }",
--- a/langtools/test/tools/javac/modules/XModuleTest.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/javac/modules/XModuleTest.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,7 +28,7 @@
  * @modules
  *      jdk.compiler/com.sun.tools.javac.api
  *      jdk.compiler/com.sun.tools.javac.main
- * @build toolbox.ToolBox toolbox.JavacTask ModuleTestBase
+ * @build toolbox.ToolBox toolbox.JavacTask toolbox.ModuleBuilder ModuleTestBase
  * @run main XModuleTest
  */
 
@@ -37,7 +37,9 @@
 import java.util.List;
 
 import toolbox.JavacTask;
+import toolbox.ModuleBuilder;
 import toolbox.Task;
+import toolbox.TestRunner;
 import toolbox.ToolBox;
 
 public class XModuleTest extends ModuleTestBase {
@@ -47,7 +49,7 @@
     }
 
     @Test
-    void testCorrectXModule(Path base) throws Exception {
+    public void testCorrectXModule(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -67,7 +69,7 @@
     }
 
     @Test
-    void testSourcePath(Path base) throws Exception {
+    public void testSourcePath(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element, Other { }", "package javax.lang.model.element; interface Other { }");
@@ -87,7 +89,7 @@
     }
 
     @Test
-    void testClassPath(Path base) throws Exception {
+    public void testClassPath(Path base) throws Exception {
         Path cpSrc = base.resolve("cpSrc");
         tb.writeJavaFiles(cpSrc, "package p; public interface Other { }");
         Path cpClasses = base.resolve("cpClasses");
@@ -122,7 +124,7 @@
     }
 
     @Test
-    void testNoModuleInfoOnSourcePath(Path base) throws Exception {
+    public void testNoModuleInfoOnSourcePath(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path src = base.resolve("src");
         tb.writeJavaFiles(src,
@@ -147,7 +149,7 @@
     }
 
     @Test
-    void testNoModuleInfoInClassOutput(Path base) throws Exception {
+    public void testNoModuleInfoInClassOutput(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path srcMod = base.resolve("src-mod");
         tb.writeJavaFiles(srcMod,
@@ -187,7 +189,7 @@
     }
 
     @Test
-    void testModuleSourcePathXModule(Path base) throws Exception {
+    public void testModuleSourcePathXModule(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -210,7 +212,7 @@
     }
 
     @Test
-    void testXModuleTooMany(Path base) throws Exception {
+    public void testXModuleTooMany(Path base) throws Exception {
         //note: avoiding use of java.base, as that gets special handling on some places:
         Path src = base.resolve("src");
         tb.writeJavaFiles(src, "package javax.lang.model.element; public interface Extra extends Element { }");
@@ -234,9 +236,9 @@
     }
 
     @Test
-    void testWithModulePath(Path base) throws Exception {
+    public void testWithModulePath(Path base) throws Exception {
         Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .classes("package pkg1; public interface E { }")
                 .build(module);
 
@@ -251,7 +253,7 @@
                 .writeAll();
 
         //checks module bounds still exist
-        new ModuleBuilder("m2")
+        new ModuleBuilder(tb, "m2")
                 .classes("package pkg2; public interface D { }")
                 .build(module);
 
@@ -275,14 +277,14 @@
     }
 
     @Test
-    void testWithUpgradeModulePath(Path base) throws Exception {
+    public void testWithUpgradeModulePath(Path base) throws Exception {
         Path module = base.resolve("modules");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .classes("package pkg1; public interface E { }")
                 .build(module);
 
         Path upgrade = base.resolve("upgrade");
-        new ModuleBuilder("m1")
+        new ModuleBuilder(tb, "m1")
                 .classes("package pkg1; public interface D { }")
                 .build(upgrade);
 
--- a/langtools/test/tools/lib/toolbox/JavacTask.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/lib/toolbox/JavacTask.java	Wed Jul 05 21:39:33 2017 +0200
@@ -103,6 +103,16 @@
     }
 
     /**
+     * Sets the classpath.
+     * @param classpath the classpath
+     * @return this task object
+     */
+    public JavacTask classpath(List<Path> classpath) {
+        this.classpath = classpath;
+        return this;
+    }
+
+    /**
      * Sets the sourcepath.
      * @param sourcepath the sourcepath
      * @return this task object
@@ -126,6 +136,16 @@
     }
 
     /**
+     * Sets the sourcepath.
+     * @param sourcepath the sourcepath
+     * @return this task object
+     */
+    public JavacTask sourcepath(List<Path> sourcepath) {
+        this.sourcepath = sourcepath;
+        return this;
+    }
+
+    /**
      * Sets the output directory.
      * @param outdir the output directory
      * @return this task object
@@ -188,6 +208,18 @@
     }
 
     /**
+     * Sets the files to be compiled or analyzed.
+     * @param files the files
+     * @return this task object
+     */
+    public JavacTask files(List<Path> files) {
+        this.files = files.stream()
+                .map(Path::toString)
+                .collect(Collectors.toList());
+        return this;
+    }
+
+    /**
      * Sets the sources to be compiled or analyzed.
      * Each source string is converted into an in-memory object that
      * can be passed directly to the compiler.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/lib/toolbox/ModuleBuilder.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package toolbox;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ModuleBuilder {
+
+    private final ToolBox tb;
+    private final String name;
+    private String requires = "";
+    private String exports = "";
+    private String uses = "";
+    private String provides = "";
+    private String modulePath = "";
+    private List<String> content = new ArrayList<>();
+
+    public ModuleBuilder(ToolBox tb, String name) {
+        this.tb = tb;
+        this.name = name;
+    }
+
+    public ModuleBuilder requiresPublic(String requires, Path... modulePath) {
+        return requires("public " + requires, modulePath);
+    }
+
+    public ModuleBuilder requires(String requires, Path... modulePath) {
+        this.requires += "    requires " + requires + ";\n";
+        this.modulePath += Arrays.stream(modulePath)
+                .map(Path::toString)
+                .collect(Collectors.joining(File.pathSeparator));
+        return this;
+    }
+
+    public ModuleBuilder exportsTo(String pkg, String module) {
+        return exports(pkg + " to " + module);
+    }
+
+    public ModuleBuilder exports(String pkg) {
+        this.exports += "    exports " + pkg + ";\n";
+        return this;
+    }
+
+    public ModuleBuilder uses(String uses) {
+        this.uses += "    uses " + uses + ";\n";
+        return this;
+    }
+
+    public ModuleBuilder provides(String service, String implementation) {
+        this.provides += "    provides " + service + " with " + implementation + ";\n";
+        return this;
+    }
+
+    public ModuleBuilder classes(String... content) {
+        this.content.addAll(Arrays.asList(content));
+        return this;
+    }
+
+    public Path write(Path where) throws IOException {
+        Files.createDirectories(where);
+        List<String> sources = new ArrayList<>();
+        sources.add("module " + name + "{"
+                + requires
+                + exports
+                + uses
+                + provides
+                + "}");
+        sources.addAll(content);
+        Path moduleSrc = where.resolve(name + "/src");
+        tb.writeJavaFiles(moduleSrc, sources.toArray(new String[]{}));
+        return moduleSrc;
+    }
+
+    public void build(Path where) throws IOException {
+        Path moduleSrc = write(where);
+        new JavacTask(tb)
+                .outdir(where.resolve(name))
+                .options("-mp", modulePath)
+                .files(tb.findJavaFiles(moduleSrc))
+                .run()
+                .writeAll();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/lib/toolbox/TestRunner.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package toolbox;
+
+import java.io.PrintStream;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.function.Function;
+
+/**
+ * Utility class to manage and execute sub-tests within a test.
+ *
+ * This class does the following:
+ * <ul>
+ * <li>  invokes those test methods annotated with @Test
+ * <li>  keeps track of successful and failed tests
+ * <li>  throws an Exception if any test fails.
+ * <li>  provides a test summary at the end of the run.
+ * </ul>
+
+ * Tests must extend this class, annotate the test methods
+ * with @Test and call one of the runTests method.
+ */
+public abstract class TestRunner {
+   /** Marker annotation for test cases. */
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface Test { }
+
+    int testCount = 0;
+    int errorCount = 0;
+
+    public String testName = null;
+
+    protected PrintStream out;
+
+    /**
+     * Constructs the Object.
+     * @param out the PrintStream to print output to.
+     */
+    public TestRunner(PrintStream out) {
+        this.out = out;
+    }
+
+    /**
+     * Invoke all methods annotated with @Test.
+     * @throws java.lang.Exception if any errors occur
+     */
+    protected void runTests() throws Exception {
+        runTests(f -> new Object[0]);
+    }
+
+    /**
+     * Invoke all methods annotated with @Test.
+     * @param f a lambda expression to specify arguments for the test method
+     * @throws java.lang.Exception if any errors occur
+     */
+    protected void runTests(Function<Method, Object[]> f) throws Exception {
+        for (Method m : getClass().getDeclaredMethods()) {
+            Annotation a = m.getAnnotation(Test.class);
+            if (a != null) {
+                testName = m.getName();
+                try {
+                    testCount++;
+                    out.println("test: " + testName);
+                    m.invoke(this, f.apply(m));
+                } catch (InvocationTargetException e) {
+                    errorCount++;
+                    Throwable cause = e.getCause();
+                    out.println("Exception: " + e.getCause());
+                    cause.printStackTrace(out);
+                }
+                out.println();
+            }
+        }
+
+        if (testCount == 0) {
+            throw new Error("no tests found");
+        }
+
+        StringBuilder summary = new StringBuilder();
+        if (testCount != 1) {
+            summary.append(testCount).append(" tests");
+        }
+        if (errorCount > 0) {
+            if (summary.length() > 0) {
+                summary.append(", ");
+            }
+            summary.append(errorCount).append(" errors");
+        }
+        out.println(summary);
+        if (errorCount > 0) {
+            throw new Exception(errorCount + " errors found");
+        }
+    }
+}
--- a/langtools/test/tools/lib/toolbox/ToolBox.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/langtools/test/tools/lib/toolbox/ToolBox.java	Wed Jul 05 21:39:33 2017 +0200
@@ -41,6 +41,7 @@
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.StandardCopyOption;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
@@ -49,6 +50,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
@@ -315,7 +317,7 @@
      * Reads the lines of a file.
      * The file is read using the default character encoding.
      * @param path the file to be read
-     * @return the lines of the file.
+     * @return the lines of the file
      * @throws IOException if an error occurred while reading the file
      */
     public List<String> readAllLines(String path) throws IOException {
@@ -326,7 +328,7 @@
      * Reads the lines of a file.
      * The file is read using the default character encoding.
      * @param path the file to be read
-     * @return the lines of the file.
+     * @return the lines of the file
      * @throws IOException if an error occurred while reading the file
      */
     public List<String> readAllLines(Path path) throws IOException {
@@ -348,7 +350,7 @@
      * Reads the lines of a file using the given encoding.
      * @param path the file to be read
      * @param encoding the encoding to be used to read the file
-     * @return the lines of the file.
+     * @return the lines of the file
      * @throws IOException if an error occurred while reading the file
      */
     public List<String> readAllLines(Path path, String encoding) throws IOException {
@@ -360,6 +362,30 @@
     }
 
     /**
+     * Find .java files in one or more directories.
+     * <p>Similar to the shell "find" command: {@code find paths -name \*.java}.
+     * @param paths the directories in which to search for .java files
+     * @return the .java files found
+     * @throws IOException if an error occurred while searching for files
+     */
+    public Path[] findJavaFiles(Path... paths) throws IOException {
+        Set<Path> files = new TreeSet<>();  // use TreeSet to force a consistent order
+        for (Path p : paths) {
+            Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+                        throws IOException {
+                    if (file.getFileName().toString().endsWith(".java")) {
+                        files.add(file);
+                    }
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        }
+        return files.toArray(new Path[files.size()]);
+    }
+
+    /**
      * Writes a file containing the given content.
      * Any necessary directories for the file will be created.
      * @param path where to write the file
--- a/make/CompileJavaModules.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/CompileJavaModules.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -99,7 +99,7 @@
 ################################################################################
 
 java.desktop_ADD_JAVAC_FLAGS := -Xdoclint:all/protected,-reference \
-    '-Xdoclint/package:java.*,javax.*' -Xlint:-deprecation
+    '-Xdoclint/package:java.*,javax.*'
 java.desktop_COPY := .gif .png .wav .txt .xml .css .pf
 java.desktop_CLEAN := iio-plugin.properties cursors.properties
 
--- a/make/CreateJmods.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/CreateJmods.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -82,7 +82,7 @@
             --os-version $(REQUIRED_OS_VERSION) \
 	    --modulepath $(IMAGES_OUTPUTDIR)/jmods\
             --hash-dependencies '.*' \
-            --exclude '**_the.*' \
+            --exclude '**{_the.*,*.diz,*.debuginfo,*.dSYM/**,*.pdb,*.map}' \
 	    $(JMOD_FLAGS) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@)
 	$(MV) $(SUPPORT_OUTPUTDIR)/jmods/$(notdir $@) $@
 
--- a/make/GensrcModuleInfo.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/GensrcModuleInfo.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -78,21 +78,30 @@
   # let space represent new lines in the variable as $(shell) normalizes all
   # whitespace.
   $(foreach f, $(MOD_FILES), \
-    $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v ".\*" $f | $(TR) ' ' '/')))
+    $(eval MOD_FILE_CONTENTS += $(shell $(GREP) -v -e ".\*" -e "//" $f | $(TR) ' ' '/')))
+
+  # Separate the modifications into qualified exports and the rest
+  MODS_QUALIFIED_EXPORTS := $(call containing, /to/, $(MOD_FILE_CONTENTS))
+  MODS_REST := $(filter-out $(MODS_QUALIFIED_EXPORTS), $(MOD_FILE_CONTENTS))
 
   # Filter the contents for modules that are actually being built
   MODULES_FILTER := $(addprefix %/, $(addsuffix ;, $(ALL_MODULES)))
-  MODULES_FILTER += provides%
-  MODIFICATIONS := $(filter $(MODULES_FILTER), $(MOD_FILE_CONTENTS))
+  MODIFICATIONS := $(filter $(MODULES_FILTER), $(MODS_QUALIFIED_EXPORTS)) \
+      $(MODS_REST)
 
   # Convert the modification lines into arguments for the modification tool.
   # Filter out modifications for non existing to-modules.
   $(foreach line, $(MODIFICATIONS), \
     $(eval split_line := $(subst /,$(SPACE),$(line))) \
     $(eval command := $(word 1, $(split_line))) \
-    $(eval package := $(word 2, $(split_line))) \
+    $(eval package := $(patsubst %;,%,$(word 2, $(split_line)))) \
     $(eval to_module := $(patsubst %;,%,$(word 4, $(split_line)))) \
-    $(eval ARGS += -$(command) $(package)/$(to_module)))
+    $(if $(to_module), \
+      $(eval ARGS += -$(command) $(package)/$(to_module)) \
+    , \
+      $(eval ARGS += -$(command) $(package)) \
+    ) \
+  )
 
   ifneq ($(ARGS), )
     $(SUPPORT_OUTPUTDIR)/gensrc/$(MODULE)/module-info.java: \
--- a/make/Images.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/Images.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -423,6 +423,55 @@
 endif
 
 ################################################################################
+# Debug symbols
+# Since debug symbols are not included in the jmod files, they need to be copied
+# in manually after generating the images.
+
+ALL_JDK_MODULES := $(JDK_MODULES)
+ALL_JRE_MODULES := $(sort $(JRE_MODULES), $(foreach m, $(JRE_MODULES), \
+    $(call FindTransitiveDepsForModule, $m)))
+
+ifeq ($(OPENJDK_TARGET_OS), windows)
+  LIBS_TARGET_SUBDIR := bin
+else
+  LIBS_TARGET_SUBDIR := lib
+endif
+
+DEBUGINFO_SUFFIXES := .diz .debuginfo .pdb .map
+
+# Param 1 - dir to find debuginfo files in
+FindDebuginfoFiles = \
+    $(wildcard $(addprefix $1/*, $(DEBUGINFO_SUFFIXES)) \
+        $(addprefix $1/*/*, $(DEBUGINFO_SUFFIXES)) \
+        $(addprefix $1/*/*/*, $(DEBUGINFO_SUFFIXES)))
+
+# On Macosx, if debug symbols have not been zipped, find all files inside *.dSYM
+# dirs.
+ifeq ($(OPENJDK_TARGET_OS)-$(ZIP_EXTERNAL_DEBUG_SYMBOLS), macosx-false)
+  $(eval $(call FillCacheFind, \
+      $(SUPPORT_OUTPUTDIR)/modules_cmds $(SUPPORT_OUTPUTDIR)/modules_libs/))
+  FindDebuginfoFiles = \
+      $(if $(wildcard $1), $(call containing, .dSYM/, $(call CacheFind, $1)))
+endif
+
+# Param 1 - either JDK or JRE
+SetupCopyDebuginfo = \
+    $(foreach m, $(ALL_$1_MODULES), \
+      $(eval $(call SetupCopyFiles, COPY_$1_LIBS_DEBUGINFO_$m, \
+          SRC := $(SUPPORT_OUTPUTDIR)/modules_libs/$m, \
+          DEST := $($1_IMAGE_DIR)/$(LIBS_TARGET_SUBDIR), \
+          FILES := $(call FindDebuginfoFiles, \
+              $(SUPPORT_OUTPUTDIR)/modules_libs/$m), \
+      )) \
+      $(eval $1_TARGETS += $$(COPY_$1_LIBS_DEBUGINFO_$m)) \
+    )
+
+# No space before argument to avoid having to put $(strip ) everywhere in
+# implementation above.
+$(call SetupCopyDebuginfo,JDK)
+$(call SetupCopyDebuginfo,JRE)
+
+################################################################################
 
 # Include custom post hook here to make it possible to augment the target lists
 # before actual target prerequisites are declared.
--- a/make/Init.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/Init.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -268,8 +268,13 @@
   ##############################################################################
 
   MAIN_TARGETS := $(SEQUENTIAL_TARGETS) $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE)
+  # If building the default target, add what they are to the description.
+  DESCRIPTION_TARGETS := $(strip $(MAIN_TARGETS))
+  ifeq ($(DESCRIPTION_TARGETS), default)
+    DESCRIPTION_TARGETS += ($(DEFAULT_MAKE_TARGET))
+  endif
   TARGET_DESCRIPTION := target$(if $(word 2, $(MAIN_TARGETS)),s) \
-      '$(strip $(MAIN_TARGETS))' in configuration '$(CONF_NAME)'
+      '$(strip $(DESCRIPTION_TARGETS))' in configuration '$(CONF_NAME)'
 
   # MAKEOVERRIDES is automatically set and propagated by Make to sub-Make calls.
   # We need to clear it of the init-specific variables. The user-specified
--- a/make/Javadoc.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/Javadoc.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -1580,7 +1580,7 @@
 JDKNET_PACKAGES_FILE = $(DOCSTMPDIR)/jdknet.packages
 
 # The modules required to be documented
-JDKNET_MODULES = java.base
+JDKNET_MODULES = jdk.net
 
 jdknetdocs: $(JDKNET_INDEX_HTML)
 
--- a/make/Jprt.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/Jprt.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -108,8 +108,8 @@
 SRC_JRE_MACOSX_BUNDLE_DIR := $(JRE_MACOSX_BUNDLE_DIR)
 
 # Bundle up the images
-JPRT_TARGET ?= all
-ifeq ($(JPRT_TARGET), all)
+JPRT_TARGET ?= default
+ifeq ($(JPRT_TARGET), default)
   bundles: $(JPRT_TARGET)
 	@$(call TargetEnter)
 	$(MKDIR) -p $(BUILD_OUTPUT)/bundles
--- a/make/Main.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/Main.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -340,10 +340,10 @@
 docs-jvmtidoc:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk jvmtidocs)
 
-zip-docs: docs-javadoc docs-jvmtidoc
+zip-docs:
 	+($(CD) $(SRC_ROOT)/make && $(MAKE) $(MAKE_ARGS) -f Javadoc.gmk zip-docs)
 
-ALL_TARGETS += docs-javadoc docs-jvmtidoc
+ALL_TARGETS += docs-javadoc docs-jvmtidoc zip-docs
 
 ################################################################################
 # Cross compilation support
@@ -602,6 +602,8 @@
 
   docs-jvmtidoc: hotspot
 
+  zip-docs: docs-javadoc docs-jvmtidoc
+
   test: jimages test-image
 
   create-buildjdk-copy: jdk.jlink-java java.base-gendata
@@ -703,7 +705,7 @@
 endif
 
 # This target builds the documentation image
-docs-image: zip-docs
+docs-image: docs-javadoc docs-jvmtidoc
 
 # This target builds the test image
 test-image: prepare-test-image test-image-hotspot-jtreg-native \
@@ -727,7 +729,7 @@
 docs: docs-image
 all: all-images
 
-ALL_TARGETS += default jdk images docs all zip-docs
+ALL_TARGETS += default jdk images docs all
 
 ################################################################################
 ################################################################################
@@ -829,6 +831,10 @@
 
 ################################################################################
 
+
+# workaround issue when building open targets when closed jib-profiles.js is used
+installer: product-images test-image
+
 .PHONY: $(ALL_TARGETS)
 
 FRC: # Force target
--- a/make/common/Modules.gmk	Wed Jul 05 21:38:13 2017 +0200
+++ b/make/common/Modules.gmk	Wed Jul 05 21:39:33 2017 +0200
@@ -63,6 +63,7 @@
     java.xml.crypto \
     jdk.httpserver \
     jdk.management \
+    jdk.net \
     jdk.sctp \
     jdk.security.auth \
     jdk.security.jgss \
@@ -185,7 +186,8 @@
     $(call GetModuleNameFromModuleInfo, $(MODULE_INFOS))))
 
 FindImportedModules = \
-    $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*)))
+    $(filter-out $(MODULES_FILTER), \
+    $(if $(IMPORT_MODULES_CLASSES), $(notdir $(wildcard $(IMPORT_MODULES_CLASSES)/*))))
 
 # Find all source dirs for a particular module
 # $1 - Module to find source dirs for
--- a/nashorn/.hgtags	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/.hgtags	Wed Jul 05 21:39:33 2017 +0200
@@ -349,3 +349,4 @@
 a5d1990fd32d908da8154d79116fce8013ba4d40 jdk-9+113
 ba21793a0e4816283cc0ecdab5142a4959363529 jdk-9+114
 295ac208a4443d433214d0c1f32d2ea45a3a32d2 jdk-9+115
+208388a5622dcca8227d6ad6c268f2c88087d283 jdk-9+116
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java	Wed Jul 05 21:39:33 2017 +0200
@@ -4310,7 +4310,7 @@
      * @param ident identifier for block or function where applicable
      */
     private void printSymbols(final Block block, final FunctionNode function, final String ident) {
-        if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
+        if (compiler.getScriptEnvironment()._print_symbols || function.getDebugFlag(FunctionNode.DEBUG_PRINT_SYMBOLS)) {
             final PrintWriter out = compiler.getScriptEnvironment().getErr();
             out.println("[BLOCK in '" + ident + "']");
             if (!block.printSymbols(out)) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CompilationPhase.java	Wed Jul 05 21:39:33 2017 +0200
@@ -278,12 +278,12 @@
             final PrintWriter       err  = senv.getErr();
 
             //TODO separate phase for the debug printouts for abstraction and clarity
-            if (senv._print_lower_ast || fn.getFlag(FunctionNode.IS_PRINT_LOWER_AST)) {
+            if (senv._print_lower_ast || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_AST)) {
                 err.println("Lower AST for: " + quote(newFunctionNode.getName()));
                 err.println(new ASTWriter(newFunctionNode));
             }
 
-            if (senv._print_lower_parse || fn.getFlag(FunctionNode.IS_PRINT_LOWER_PARSE)) {
+            if (senv._print_lower_parse || fn.getDebugFlag(FunctionNode.DEBUG_PRINT_LOWER_PARSE)) {
                 err.println("Lower AST for: " + quote(newFunctionNode.getName()));
                 err.println(new PrintVisitor(newFunctionNode));
             }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Wed Jul 05 21:39:33 2017 +0200
@@ -175,7 +175,9 @@
                 // we still use IS_SPLIT as the criteria in CompilationPhase.SERIALIZE_SPLIT_PHASE.
                 FunctionNode.IS_ANONYMOUS | FunctionNode.USES_ANCESTOR_SCOPE | FunctionNode.IS_SPLIT,
                 body,
-                null
+                null,
+                originalFn.getModule(),
+                originalFn.getDebugFlags()
         )
         .setCompileUnit(lc, splitNode.getCompileUnit());
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/WeighNodes.java	Wed Jul 05 21:39:33 2017 +0200
@@ -435,7 +435,7 @@
     }
 
     @Override
-    public Node leaveBIND(final BinaryNode binaryNode) {
+    public Node leaveARROW(final BinaryNode binaryNode) {
         return binaryNodeWeight(binaryNode);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/AccessNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,12 +48,13 @@
      * @param property  property
      */
     public AccessNode(final long token, final int finish, final Expression base, final String property) {
-        super(token, finish, base, false);
+        super(token, finish, base, false, false);
         this.property = property;
     }
 
-    private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) {
-        super(accessNode, base, isFunction, type, id);
+    private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction,
+                       final Type type, final int id, final boolean isSuper) {
+        super(accessNode, base, isFunction, type, id, isSuper);
         this.property = property;
     }
 
@@ -105,7 +106,7 @@
         if (this.base == base) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction(), type, programPoint);
+        return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
     }
 
     @Override
@@ -113,7 +114,7 @@
         if (this.type == type) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction(), type, programPoint);
+        return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
     }
 
     @Override
@@ -121,7 +122,7 @@
         if (this.programPoint == programPoint) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction(), type, programPoint);
+        return new AccessNode(this, base, property, isFunction(), type, programPoint, isSuper());
     }
 
     @Override
@@ -129,6 +130,14 @@
         if (isFunction()) {
             return this;
         }
-        return new AccessNode(this, base, property, true, type, programPoint);
+        return new AccessNode(this, base, property, true, type, programPoint, isSuper());
+    }
+
+    @Override
+    public AccessNode setIsSuper() {
+        if (isSuper()) {
+            return this;
+        }
+        return new AccessNode(this, base, property, isFunction(), type, programPoint, true);
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/BaseNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -52,6 +52,9 @@
     /** Program point id */
     protected final int programPoint;
 
+    /** Super property access. */
+    private final boolean isSuper;
+
     /**
      * Constructor
      *
@@ -59,13 +62,15 @@
      * @param finish finish
      * @param base   base node
      * @param isFunction is this a function
+     * @param isSuper is this a super property access
      */
-    public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
+    public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction, final boolean isSuper) {
         super(token, base.getStart(), finish);
         this.base           = base;
         this.isFunction     = isFunction;
         this.type = null;
         this.programPoint   = INVALID_PROGRAM_POINT;
+        this.isSuper        = isSuper;
     }
 
     /**
@@ -75,13 +80,15 @@
      * @param isFunction is this a function
      * @param callSiteType  the callsite type for this base node, either optimistic or conservative
      * @param programPoint  program point id
+     * @param isSuper is this a super property access
      */
-    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) {
+    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint, final boolean isSuper) {
         super(baseNode);
         this.base           = base;
         this.isFunction     = isFunction;
         this.type = callSiteType;
         this.programPoint   = programPoint;
+        this.isSuper        = isSuper;
     }
 
     /**
@@ -136,4 +143,17 @@
      */
     public abstract BaseNode setIsFunction();
 
+    /**
+     * @return {@code true} if a SuperProperty access.
+     */
+    public boolean isSuper() {
+        return isSuper;
+    }
+
+    /**
+     * Mark this node as being a SuperProperty access.
+     *
+     * @return  a base node identical to this one in all aspects except with its super flag set.
+     */
+    public abstract BaseNode setIsSuper();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java	Wed Jul 05 21:39:33 2017 +0200
@@ -65,24 +65,39 @@
     private final LocalVariableConversion conversion;
 
     /** Flag indicating that this block needs scope */
-    public static final int NEEDS_SCOPE = 1 << 0;
+    public static final int NEEDS_SCOPE        = 1 << 0;
 
     /**
      * Is this block tagged as terminal based on its contents
      * (usually the last statement)
      */
-    public static final int IS_TERMINAL = 1 << 2;
+    public static final int IS_TERMINAL        = 1 << 2;
 
     /**
      * Is this block the eager global scope - i.e. the original program. This isn't true for the
      * outermost level of recompiles
      */
-    public static final int IS_GLOBAL_SCOPE = 1 << 3;
+    public static final int IS_GLOBAL_SCOPE    = 1 << 3;
 
     /**
      * Is this block a synthetic one introduced by Parser?
      */
-    public static final int IS_SYNTHETIC = 1 << 4;
+    public static final int IS_SYNTHETIC       = 1 << 4;
+
+    /**
+     * Is this the function body block? May not be the first, if parameter list contains expressions.
+     */
+    public static final int IS_BODY            = 1 << 5;
+
+    /**
+     * Is this the parameter initialization block? If present, must be the first block, immediately wrapping the function body block.
+     */
+    public static final int IS_PARAMETER_BLOCK = 1 << 6;
+
+    /**
+     * Marks the variable declaration block for case clauses of a switch statement.
+     */
+    public static final int IS_SWITCH_BLOCK    = 1 << 7;
 
     /**
      * Constructor
@@ -489,4 +504,31 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         return Acceptor.accept(this, visitor);
     }
+
+    /**
+     * Checks if this is a function body.
+     *
+     * @return true if the function body flag is set
+     */
+    public boolean isFunctionBody() {
+        return getFlag(IS_BODY);
+    }
+
+    /**
+     * Checks if this is a parameter block.
+     *
+     * @return true if the parameter block flag is set
+     */
+    public boolean isParameterBlock() {
+        return getFlag(IS_PARAMETER_BLOCK);
+    }
+
+    /**
+     * Checks whether this is a switch block.
+     *
+     * @return true if this is a switch block
+     */
+    public boolean isSwitchBlock() {
+        return getFlag(IS_SWITCH_BLOCK);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,147 @@
+/*
+ * 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.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR representation for class definitions.
+ */
+public class ClassNode extends Expression {
+    private static final long serialVersionUID = 1L;
+
+    private final IdentNode ident;
+    private final Expression classHeritage;
+    private final PropertyNode constructor;
+    private final List<PropertyNode> classElements;
+    private final int line;
+
+    /**
+     * Constructor.
+     *
+     * @param line line number
+     * @param token token
+     * @param finish finish
+     * @param ident ident
+     * @param classHeritage class heritage
+     * @param constructor constructor
+     * @param classElements class elements
+     */
+    public ClassNode(final int line, final long token, final int finish, final IdentNode ident, final Expression classHeritage, final PropertyNode constructor,
+                     final List<PropertyNode> classElements) {
+        super(token, finish);
+        this.line = line;
+        this.ident = ident;
+        this.classHeritage = classHeritage;
+        this.constructor = constructor;
+        this.classElements = classElements;
+    }
+
+    /**
+     * Class identifier. Optional.
+     *
+     * @return the class identifier
+     */
+    public IdentNode getIdent() {
+        return ident;
+    }
+
+    /**
+     * The expression of the {@code extends} clause. Optional.
+     *
+     * @return the class heritage
+     */
+    public Expression getClassHeritage() {
+        return classHeritage;
+    }
+
+    /**
+     * Get the constructor method definition.
+     *
+     * @return the constructor
+     */
+    public PropertyNode getConstructor() {
+        return constructor;
+    }
+
+    /**
+     * Get method definitions except the constructor.
+     *
+     * @return the class elements
+     */
+    public List<PropertyNode> getClassElements() {
+        return Collections.unmodifiableList(classElements);
+    }
+
+    /**
+     * Returns the line number.
+     *
+     * @return the line number
+     */
+    public int getLineNumber() {
+        return line;
+    }
+
+    @Override
+    public Type getType() {
+        return Type.OBJECT;
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterClassNode(this)) {
+            return visitor.leaveClassNode(this);
+        }
+
+        return this;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb, final boolean printType) {
+        sb.append("class");
+        if (ident != null) {
+            sb.append(' ');
+            ident.toString(sb, printType);
+        }
+        if (classHeritage != null) {
+            sb.append(" extends");
+            classHeritage.toString(sb, printType);
+        }
+        sb.append(" {");
+        if (constructor != null) {
+            constructor.toString(sb, printType);
+        }
+        for (final PropertyNode classElement : classElements) {
+            sb.append(" ");
+            classElement.toString(sb, printType);
+        }
+        sb.append("}");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionList.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,87 @@
+/*
+ * 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.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * IR for CoverParenthesizedExpressionAndArrowParameterList, used only during parsing.
+ */
+public final class ExpressionList extends Expression {
+    private static final long serialVersionUID = 1L;
+
+    private final List<Expression> expressions;
+
+    /**
+     * Constructor.
+     *
+     * @param token token
+     * @param finish finish
+     * @param expressions expression
+     */
+    public ExpressionList(final long token, final int finish, final List<Expression> expressions) {
+        super(token, finish);
+        this.expressions = expressions;
+    }
+
+    /**
+     * Get the list of expressions.
+     *
+     * @return the list of expressions
+     */
+    public List<Expression> getExpressions() {
+        return Collections.unmodifiableList(expressions);
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Type getType() {
+        return null;
+    }
+
+    @Override
+    public void toString(StringBuilder sb, boolean printType) {
+        sb.append("(");
+        boolean first = true;
+        for (Expression expression : expressions) {
+            if (first) {
+                first = false;
+            } else {
+                sb.append(", ");
+            }
+            expression.toString(sb, printType);
+        }
+        sb.append(")");
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -90,7 +90,6 @@
         this.init = init;
         this.modify = modify;
         this.iterator = null;
-
     }
 
     private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -69,7 +69,13 @@
         /** a getter, @see {@link UserAccessorProperty} */
         GETTER,
         /** a setter, @see {@link UserAccessorProperty} */
-        SETTER
+        SETTER,
+        /** an arrow function */
+        ARROW,
+        /** a generator function */
+        GENERATOR,
+        /** a module function */
+        MODULE
     }
 
     /** Source of entity. */
@@ -122,6 +128,12 @@
     /** Root class for function */
     private final Class<?> rootClass;
 
+    /** The ES6 module */
+    private final Module module;
+
+    /** The debug flags */
+    private final int debugFlags;
+
     /** Is anonymous function flag. */
     public static final int IS_ANONYMOUS                = 1 << 0;
 
@@ -172,49 +184,21 @@
     /**
      * Is this function the top-level program?
      */
-    public static final int IS_PROGRAM = 1 << 13;
+    public static final int IS_PROGRAM                  = 1 << 13;
 
     /**
      * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
      * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
      * use the symbol in their parent scope instead when they reference themselves by name.
      */
-    public static final int USES_SELF_SYMBOL = 1 << 14;
+    public static final int USES_SELF_SYMBOL            = 1 << 14;
 
     /** Does this function use the "this" keyword? */
-    public static final int USES_THIS = 1 << 15;
+    public static final int USES_THIS                   = 1 << 15;
 
     /** Is this declared in a dynamic context */
-    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
-
-    /**
-     * The following flags are derived from directive comments within this function.
-     * Note that even IS_STRICT is one such flag but that requires special handling.
-     */
+    public static final int IN_DYNAMIC_CONTEXT          = 1 << 16;
 
-    /** parser, print parse tree */
-    public static final int IS_PRINT_PARSE       = 1 << 17;
-    /** parser, print lower parse tree */
-    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
-    /** parser, print AST */
-    public static final int IS_PRINT_AST         = 1 << 19;
-    /** parser, print lower AST */
-    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
-    /** parser, print symbols */
-    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
-
-    // callsite tracing, profiling within this function
-    /** profile callsites in this function? */
-    public static final int IS_PROFILE         = 1 << 22;
-
-    /** trace callsite enterexit in this function? */
-    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
-
-    /** trace callsite misses in this function? */
-    public static final int IS_TRACE_MISSES    = 1 << 24;
-
-    /** trace callsite values in this function? */
-    public static final int IS_TRACE_VALUES    = 1 << 25;
 
     /**
      * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
@@ -222,18 +206,41 @@
      * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
      * will, however, cache the value of this flag.
      */
-    public static final int NEEDS_CALLEE       = 1 << 26;
+    public static final int NEEDS_CALLEE                = 1 << 17;
 
     /**
      * Is the function node cached?
      */
-    public static final int IS_CACHED = 1 << 27;
+    public static final int IS_CACHED                   = 1 << 18;
+
+    /**
+     * Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper)
+     */
+    public static final int ES6_HAS_DIRECT_SUPER        = 1 << 19;
+
+    /**
+     * Does this function use the super binding?
+     */
+    public static final int ES6_USES_SUPER              = 1 << 20;
 
-    /** extension callsite flags mask */
-    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
-        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
-        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
-        IS_TRACE_MISSES | IS_TRACE_VALUES;
+    /**
+     * Is this function a (class or object) method?
+     */
+    public static final int ES6_IS_METHOD               = 1 << 21;
+
+    /**
+     * Is this the constructor method?
+     */
+    public static final int ES6_IS_CLASS_CONSTRUCTOR    = 1 << 22;
+
+    /** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */
+    public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23;
+
+    /** is this a strong mode function? */
+    public static final int ES6_IS_STRONG               = 1 << 24;
+
+    /** Does this function use new.target? */
+    public static final int ES6_USES_NEW_TARGET         = 1 << 25;
 
     /** Does this function or any nested functions contain an eval? */
     private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
@@ -247,8 +254,44 @@
     /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
     public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
 
+
+    /**
+     * The following flags are derived from directive comments within this function.
+     * Note that even IS_STRICT is one such flag but that requires special handling.
+     */
+
+    /** parser, print parse tree */
+    public static final int DEBUG_PRINT_PARSE       = 1 << 0;
+    /** parser, print lower parse tree */
+    public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1;
+    /** parser, print AST */
+    public static final int DEBUG_PRINT_AST         = 1 << 2;
+    /** parser, print lower AST */
+    public static final int DEBUG_PRINT_LOWER_AST   = 1 << 3;
+    /** parser, print symbols */
+    public static final int DEBUG_PRINT_SYMBOLS     = 1 << 4;
+
+    // callsite tracing, profiling within this function
+    /** profile callsites in this function? */
+    public static final int DEBUG_PROFILE           = 1 << 5;
+
+    /** trace callsite enterexit in this function? */
+    public static final int DEBUG_TRACE_ENTEREXIT   = 1 << 6;
+
+    /** trace callsite misses in this function? */
+    public static final int DEBUG_TRACE_MISSES      = 1 << 7;
+
+    /** trace callsite values in this function? */
+    public static final int DEBUG_TRACE_VALUES      = 1 << 8;
+
+    /** extension callsite flags mask */
+    public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE |
+            DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST |
+            DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT |
+            DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES;
+
     /** What is the return type of this function? */
-    private Type returnType = Type.UNKNOWN;
+    public Type returnType = Type.UNKNOWN;
 
     /**
      * Constructor
@@ -267,6 +310,8 @@
      * @param flags      initial flags
      * @param body       body of the function
      * @param endParserState The parser state at the end of the parsing.
+     * @param module     the module
+     * @param debugFlags the debug flags
      */
     public FunctionNode(
         final Source source,
@@ -282,7 +327,9 @@
         final FunctionNode.Kind kind,
         final int flags,
         final Block body,
-        final Object endParserState) {
+        final Object endParserState,
+        final Module module,
+        final int debugFlags) {
         super(token, finish);
 
         this.source           = source;
@@ -299,7 +346,9 @@
         this.body             = body;
         this.thisProperties   = 0;
         this.rootClass        = null;
-        this.endParserState    = endParserState;
+        this.endParserState   = endParserState;
+        this.module           = module;
+        this.debugFlags       = debugFlags;
     }
 
     private FunctionNode(
@@ -335,6 +384,8 @@
         this.ident           = functionNode.ident;
         this.kind            = functionNode.kind;
         this.firstToken      = functionNode.firstToken;
+        this.module          = functionNode.module;
+        this.debugFlags      = functionNode.debugFlags;
     }
 
     @Override
@@ -366,23 +417,23 @@
         }
 
         // quick check for extension callsite flags turned on by directives.
-        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
+        if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) {
             return callsiteFlags;
         }
 
-        if (getFlag(IS_PROFILE)) {
+        if (getDebugFlag(DEBUG_PROFILE)) {
             callsiteFlags |= CALLSITE_PROFILE;
         }
 
-        if (getFlag(IS_TRACE_MISSES)) {
+        if (getDebugFlag(DEBUG_TRACE_MISSES)) {
             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
         }
 
-        if (getFlag(IS_TRACE_VALUES)) {
+        if (getDebugFlag(DEBUG_TRACE_VALUES)) {
             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
         }
 
-        if (getFlag(IS_TRACE_ENTEREXIT)) {
+        if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) {
             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
         }
 
@@ -466,23 +517,23 @@
     public static int getDirectiveFlag(final String directive) {
         switch (directive) {
             case "nashorn callsite trace enterexit":
-                return IS_TRACE_ENTEREXIT;
+                return DEBUG_TRACE_ENTEREXIT;
             case "nashorn callsite trace misses":
-                return IS_TRACE_MISSES;
+                return DEBUG_TRACE_MISSES;
             case "nashorn callsite trace objects":
-                return IS_TRACE_VALUES;
+                return DEBUG_TRACE_VALUES;
             case "nashorn callsite profile":
-                return IS_PROFILE;
+                return DEBUG_PROFILE;
             case "nashorn print parse":
-                return IS_PRINT_PARSE;
+                return DEBUG_PRINT_PARSE;
             case "nashorn print lower parse":
-                return IS_PRINT_LOWER_PARSE;
+                return DEBUG_PRINT_LOWER_PARSE;
             case "nashorn print ast":
-                return IS_PRINT_AST;
+                return DEBUG_PRINT_AST;
             case "nashorn print lower ast":
-                return IS_PRINT_LOWER_AST;
+                return DEBUG_PRINT_LOWER_AST;
             case "nashorn print symbols":
-                return IS_PRINT_SYMBOLS;
+                return DEBUG_PRINT_SYMBOLS;
             default:
                 // unknown/unsupported directive
                 return 0;
@@ -579,6 +630,25 @@
     }
 
     /**
+     * Returns the debug flags for this function.
+     *
+     * @return the debug flags
+     */
+    public int getDebugFlags() {
+        return debugFlags;
+    }
+
+    /**
+     * Checks whether a debug flag is set for this function.
+     *
+     * @param debugFlag the debug flag
+     * @return true if the flag is set
+     */
+    public boolean getDebugFlag(final int debugFlag) {
+        return (debugFlags & debugFlag) != 0;
+    }
+
+    /**
      * Returns true if the function is the top-level program.
      * @return True if this function node represents the top-level program.
      */
@@ -1065,6 +1135,86 @@
         return setFlag(lc, IS_CACHED);
     }
 
+    /**
+     * Checks if the function is generated in strong mode.
+     *
+     * @return true if strong mode enabled for function
+     */
+    public boolean isStrong() {
+        return getFlag(ES6_IS_STRONG);
+    }
+
+    /**
+     * Checks if this is an ES6 method.
+     *
+     * @return true if the ES6 method flag is set
+     */
+    public boolean isMethod() {
+        return getFlag(ES6_IS_METHOD);
+    }
+
+    /**
+     * Checks if this function uses the ES6 super binding.
+     *
+     * @return true if the ES6 super flag is set
+     */
+    public boolean usesSuper() {
+        return getFlag(ES6_USES_SUPER);
+    }
+
+    /**
+     * Checks if this function directly uses the super binding.
+     *
+     * @return true if the ES6 has-direct-super flag is set
+     */
+    public boolean hasDirectSuper() {
+        return getFlag(ES6_HAS_DIRECT_SUPER);
+    }
+
+    /**
+     * Checks if this is an ES6 class constructor.
+     *
+     * @return true if the ES6 class constructor flag is set
+     */
+    public boolean isClassConstructor() {
+        return getFlag(ES6_IS_CLASS_CONSTRUCTOR);
+    }
+
+    /**
+     * Checks if this is an ES6 subclass constructor.
+     *
+     * @return true if the ES6 subclass constructor flag is set
+     */
+    public boolean isSubclassConstructor() {
+        return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR);
+    }
+
+    /**
+     * Checks if this function uses the ES6 new-targert.
+     *
+     * @return true if the ES6 new-target flag is set
+     */
+    public boolean usesNewTarget() {
+        return getFlag(ES6_USES_NEW_TARGET);
+    }
+
+    /**
+     * Checks if this is an ES6 module.
+     *
+     * @return true if this is an ES6 module
+     */
+    public boolean isModule() {
+        return kind == Kind.MODULE;
+    }
+
+    /**
+     * Returns the functions's ES6 module.
+     *
+     * @return the module, or null if this function is not part of one
+     */
+    public Module getModule() {
+        return module;
+    }
 
     /**
      * Get the compile unit used to compile this function
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IdentNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -49,6 +49,11 @@
     private static final int FUTURESTRICT_NAME = 1 << 3;
     private static final int IS_DECLARED_HERE  = 1 << 4;
     private static final int IS_DEAD           = 1 << 5;
+    private static final int DIRECT_SUPER      = 1 << 6;
+    private static final int REST_PARAMETER    = 1 << 7;
+    private static final int PROTO_PROPERTY    = 1 << 8;
+    private static final int DEFAULT_PARAMETER = 1 << 9;
+    private static final int DESTRUCTURED_PARAMETER = 1 << 10;
 
     /** Identifier. */
     private final String name;
@@ -382,4 +387,94 @@
     public LocalVariableConversion getLocalVariableConversion() {
         return conversion;
     }
+
+    /**
+     * Checks if this is a direct super identifier
+     *
+     * @return true if the direct super flag is set
+     */
+    public boolean isDirectSuper() {
+        return (flags & DIRECT_SUPER) != 0;
+    }
+
+    /**
+     * Return a new identifier with the direct super flag set.
+     *
+     * @return the new identifier
+     */
+    public IdentNode setIsDirectSuper() {
+        return new IdentNode(this, name, type, flags | DIRECT_SUPER, programPoint, conversion);
+    }
+
+    /**
+     * Checks if this is a rest parameter
+     *
+     * @return true if the rest parameter flag is set
+     */
+    public boolean isRestParameter() {
+        return (flags & REST_PARAMETER) != 0;
+    }
+
+    /**
+     * Return a new identifier with the rest parameter flag set.
+     *
+     * @return the new identifier
+     */
+    public IdentNode setIsRestParameter() {
+        return new IdentNode(this, name, type, flags | REST_PARAMETER, programPoint, conversion);
+    }
+
+    /**
+     * Checks if this is a proto property name.
+     *
+     * @return true if this is the proto property name
+     */
+    public boolean isProtoPropertyName() {
+        return (flags & PROTO_PROPERTY) != 0;
+    }
+
+    /**
+     * Return a new identifier with the proto property name flag set.
+     *
+     * @return the new identifier
+     */
+    public IdentNode setIsProtoPropertyName() {
+        return new IdentNode(this, name, type, flags | PROTO_PROPERTY, programPoint, conversion);
+    }
+
+    /**
+     * Checks whether this is a default parameter.
+     *
+     * @return true if this is a default parameter
+     */
+    public boolean isDefaultParameter() {
+        return (flags & DEFAULT_PARAMETER) != 0;
+    }
+
+    /**
+     * Return a new identifier with the default parameter flag set.
+     *
+     * @return the new identifier
+     */
+    public IdentNode setIsDefaultParameter() {
+        return new IdentNode(this, name, type, flags | DEFAULT_PARAMETER, programPoint, conversion);
+    }
+
+    /**
+     * Checks whether this is a destructured parameter.
+     *
+     * @return true if this is a destructured parameter
+     */
+    public boolean isDestructuredParameter() {
+        return (flags & DESTRUCTURED_PARAMETER) != 0;
+    }
+
+    /**
+     * Return a new identifier with the destructured parameter flag set.
+     *
+     * @return the new identifier
+     */
+    public IdentNode setIsDestructuredParameter() {
+        return new IdentNode(this, name, type, flags | DESTRUCTURED_PARAMETER, programPoint, conversion);
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/IndexNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -47,12 +47,13 @@
      * @param index   index for access
      */
     public IndexNode(final long token, final int finish, final Expression base, final Expression index) {
-        super(token, finish, base, false);
+        super(token, finish, base, false, false);
         this.index = index;
     }
 
-    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) {
-        super(indexNode, base, isFunction, type, programPoint);
+    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction,
+                      final Type type, final int programPoint, final boolean isSuper) {
+        super(indexNode, base, isFunction, type, programPoint, isSuper);
         this.index = index;
     }
 
@@ -101,7 +102,7 @@
         if (this.base == base) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+        return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
     }
 
     /**
@@ -113,7 +114,7 @@
         if(this.index == index) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+        return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
     }
 
     @Override
@@ -121,7 +122,7 @@
         if (this.type == type) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+        return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
     }
 
     @Override
@@ -129,7 +130,7 @@
         if (isFunction()) {
             return this;
         }
-        return new IndexNode(this, base, index, true, type, programPoint);
+        return new IndexNode(this, base, index, true, type, programPoint, isSuper());
     }
 
     @Override
@@ -137,6 +138,14 @@
         if (this.programPoint == programPoint) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+        return new IndexNode(this, base, index, isFunction(), type, programPoint, isSuper());
+    }
+
+    @Override
+    public IndexNode setIsSuper() {
+        if (isSuper()) {
+            return this;
+        }
+        return new IndexNode(this, base, index, isFunction(), type, programPoint, true);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.List;
+
+/**
+ * ES6 Module information.
+ */
+public final class Module {
+
+    /** The synthetic binding name assigned to export default declarations with unnamed expressions. */
+    public static final String DEFAULT_EXPORT_BINDING_NAME = "*default*";
+
+    /** The {@code export default} name. */
+    public static final String DEFAULT_NAME = "default";
+
+    /** The {@code export *} name. */
+    public static final String STAR_NAME = "*";
+
+    /**
+     * A module ExportEntry record.
+     *
+     * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
+     */
+    public static final class ExportEntry {
+        private final String exportName;
+        private final String moduleRequest;
+        private final String importName;
+        private final String localName;
+
+        private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) {
+            this.exportName = exportName;
+            this.moduleRequest = moduleRequest;
+            this.importName = importName;
+            this.localName = localName;
+        }
+
+        /**
+         * Creates a {@code export *} export entry.
+         *
+         * @param moduleRequest the module request
+         * @return the export entry
+         */
+        public static ExportEntry exportStarFrom(final String moduleRequest) {
+            return new ExportEntry(null, moduleRequest, STAR_NAME, null);
+        }
+
+        /**
+         * Creates a {@code export default} export entry.
+         *
+         * @return the export entry
+         */
+        public static ExportEntry exportDefault() {
+            return exportDefault(DEFAULT_EXPORT_BINDING_NAME);
+        }
+
+        /**
+         * Creates a {@code export default} export entry with a local name.
+         *
+         * @param localName the local name
+         * @return the export entry
+         */
+        public static ExportEntry exportDefault(final String localName) {
+            return new ExportEntry(DEFAULT_NAME, null, null, localName);
+        }
+
+        /**
+         * Creates a export entry with a local name and export name.
+         *
+         * @param exportName the export name
+         * @param localName the local name
+         * @return the export entry
+         */
+        public static ExportEntry exportSpecifier(final String exportName, final String localName) {
+            return new ExportEntry(exportName, null, null, localName);
+        }
+
+        /**
+         * Creates a export entry with an export name.
+         *
+         * @param exportName the export name
+         * @return the export entry
+         */
+        public static ExportEntry exportSpecifier(final String exportName) {
+            return exportSpecifier(exportName, exportName);
+        }
+
+        /**
+         * Create a copy of this entry with the specified {@code module request} string.
+         *
+         * @param moduleRequest the module request
+         * @return the new export entry
+         */
+        public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
+            return new ExportEntry(exportName, moduleRequest, localName, null);
+        }
+
+        /**
+         * Returns the entry's export name.
+         *
+         * @return the export name
+         */
+        public String getExportName() {
+            return exportName;
+        }
+
+        /**
+         * Returns the entry's module request.
+         *
+         * @return the module request
+         */
+        public String getModuleRequest() {
+            return moduleRequest;
+        }
+
+        /**
+         * Returns the entry's import name.
+         *
+         * @return the import name
+         */
+        public String getImportName() {
+            return importName;
+        }
+
+        /**
+         * Returns the entry's local name.
+         *
+         * @return the local name
+         */
+        public String getLocalName() {
+            return localName;
+        }
+
+        @Override
+        public String toString() {
+            return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
+        }
+    }
+
+    /**
+     * An ImportEntry record.
+     *
+     * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
+     */
+    public static final class ImportEntry {
+        private final String moduleRequest;
+        private final String importName;
+        private final String localName;
+
+        private ImportEntry(final String moduleRequest, final String importName, final String localName) {
+            this.moduleRequest = moduleRequest;
+            this.importName = importName;
+            this.localName = localName;
+        }
+
+        /**
+         * Creates an import entry with default name.
+         *
+         * @param localName the local name
+         * @return the import entry
+         */
+        public static ImportEntry importDefault(final String localName) {
+            return new ImportEntry(null, DEFAULT_NAME, localName);
+        }
+
+        /**
+         * Creates an import entry with {@code *} import name.
+         *
+         * @param localName the local name
+         * @return the import entry
+         */
+        public static ImportEntry importStarAsNameSpaceFrom(final String localName) {
+            return new ImportEntry(null, STAR_NAME, localName);
+        }
+
+        /**
+         * Creates an import entry with the given import and local names.
+         *
+         * @param importName the import name
+         * @param localName the local name
+         * @return the import entry
+         */
+        public static ImportEntry importSpecifier(final String importName, final String localName) {
+            return new ImportEntry(null, importName, localName);
+        }
+
+        /**
+         * Creates a new import entry with the given import name.
+         *
+         * @param importName the import name
+         * @return the import entry
+         */
+        public static ImportEntry importSpecifier(final String importName) {
+            return importSpecifier(importName, importName);
+        }
+
+        /**
+         * Returns a copy of this import entry with the given module request.
+         *
+         * @param moduleRequest the module request
+         * @return the new import entry
+         */
+        public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
+            return new ImportEntry(moduleRequest, importName, localName);
+        }
+
+        /**
+         * Returns the entry's module request.
+         *
+         * @return the module request
+         */
+        public String getModuleRequest() {
+            return moduleRequest;
+        }
+
+        /**
+         * Returns the entry's import name.
+         *
+         * @return the import name
+         */
+        public String getImportName() {
+            return importName;
+        }
+
+        /**
+         * Returns the entry's local name.
+         *
+         * @return the local name
+         */
+        public String getLocalName() {
+            return localName;
+        }
+
+        @Override
+        public String toString() {
+            return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
+        }
+    }
+
+    private final List<String> requestedModules;
+    private final List<ImportEntry> importEntries;
+    private final List<ExportEntry> localExportEntries;
+    private final List<ExportEntry> indirectExportEntries;
+    private final List<ExportEntry> starExportEntries;
+
+    /**
+     * Creates a module with the specified requested modules and import and export entries.
+     *
+     * @param requestedModules the requested modules
+     * @param importEntries the import entries
+     * @param localExportEntries local export entries
+     * @param indirectExportEntries indirect export entries
+     * @param starExportEntries star export entries
+     */
+    public Module(final List<String> requestedModules, final List<ImportEntry> importEntries, final List<ExportEntry> localExportEntries,
+                  final List<ExportEntry> indirectExportEntries, final List<ExportEntry> starExportEntries) {
+        this.requestedModules = requestedModules;
+        this.importEntries = importEntries;
+        this.localExportEntries = localExportEntries;
+        this.indirectExportEntries = indirectExportEntries;
+        this.starExportEntries = starExportEntries;
+    }
+
+    /**
+     * Returns the list of requested modules.
+     *
+     * @return the requested modules
+     */
+    public List<String> getRequestedModules() {
+        return requestedModules;
+    }
+
+    /**
+     * Returns the list of import entries.
+     *
+     * @return the import entries
+     */
+    public List<ImportEntry> getImportEntries() {
+        return importEntries;
+    }
+
+    /**
+     * Returns the list of local export entries.
+     *
+     * @return the local export entries
+     */
+    public List<ExportEntry> getLocalExportEntries() {
+        return localExportEntries;
+    }
+
+    /**
+     * Returns the list of indirect export entries.
+     *
+     * @return the indirect export entries
+     */
+    public List<ExportEntry> getIndirectExportEntries() {
+        return indirectExportEntries;
+    }
+
+    /**
+     * Returns the list of star export entries.
+     *
+     * @return the star export entries
+     */
+    public List<ExportEntry> getStarExportEntries() {
+        return starExportEntries;
+    }
+
+    @Override
+    public String toString() {
+        return "Module [requestedModules=" + requestedModules + ", importEntries=" + importEntries + ", localExportEntries=" + localExportEntries + ", indirectExportEntries=" +
+                indirectExportEntries + ", starExportEntries=" + starExportEntries + "]";
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/PropertyNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -36,7 +36,7 @@
     private static final long serialVersionUID = 1L;
 
     /** Property key. */
-    private final PropertyKey key;
+    private final Expression key;
 
     /** Property value. */
     private final Expression value;
@@ -47,6 +47,12 @@
     /** Property getter. */
     private final FunctionNode setter;
 
+    /** static property flag */
+    private final boolean isStatic;
+
+    /** Computed property flag */
+    private final boolean computed;
+
     /**
      * Constructor
      *
@@ -56,21 +62,27 @@
      * @param value   the value of this property
      * @param getter  getter function body
      * @param setter  setter function body
+     * @param isStatic is this a static property?
+     * @param computed is this a computed property?
      */
-    public PropertyNode(final long token, final int finish, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
+    public PropertyNode(final long token, final int finish, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
         super(token, finish);
         this.key    = key;
         this.value  = value;
         this.getter = getter;
         this.setter = setter;
+        this.isStatic = isStatic;
+        this.computed = computed;
     }
 
-    private PropertyNode(final PropertyNode propertyNode, final PropertyKey key, final Expression value, final FunctionNode getter, final FunctionNode setter) {
+    private PropertyNode(final PropertyNode propertyNode, final Expression key, final Expression value, final FunctionNode getter, final FunctionNode setter, final boolean isStatic, final boolean computed) {
         super(propertyNode);
         this.key    = key;
         this.value  = value;
         this.getter = getter;
         this.setter = setter;
+        this.isStatic = isStatic;
+        this.computed = computed;
     }
 
     /**
@@ -78,14 +90,14 @@
      * @return key name
      */
     public String getKeyName() {
-        return key.getPropertyName();
+        return key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : null;
     }
 
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterPropertyNode(this)) {
             return visitor.leavePropertyNode(
-                setKey((PropertyKey)((Node)key).accept(visitor)).
+                setKey((Expression) key.accept(visitor)).
                 setValue(value == null ? null : (Expression)value.accept(visitor)).
                 setGetter(getter == null ? null : (FunctionNode)getter.accept(visitor)).
                 setSetter(setter == null ? null : (FunctionNode)setter.accept(visitor)));
@@ -134,7 +146,7 @@
         if (this.getter == getter) {
             return this;
         }
-        return new PropertyNode(this, key, value, getter, setter);
+        return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
     }
 
     /**
@@ -142,14 +154,14 @@
      * @return the key
      */
     public Expression getKey() {
-        return (Expression)key;
+        return key;
     }
 
-    private PropertyNode setKey(final PropertyKey key) {
+    private PropertyNode setKey(final Expression key) {
         if (this.key == key) {
             return this;
         }
-        return new PropertyNode(this, key, value, getter, setter);
+        return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
     }
 
     /**
@@ -169,7 +181,7 @@
         if (this.setter == setter) {
             return this;
         }
-        return new PropertyNode(this, key, value, getter, setter);
+        return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
     }
 
     /**
@@ -189,6 +201,24 @@
         if (this.value == value) {
             return this;
         }
-        return new PropertyNode(this, key, value, getter, setter);
-   }
+        return new PropertyNode(this, key, value, getter, setter, isStatic, computed);
+    }
+
+    /**
+     * Returns true if this is a static property.
+     *
+     * @return true if static flag is set
+     */
+    public boolean isStatic() {
+        return isStatic;
+    }
+
+    /**
+     * Returns true if this is a computed property.
+     *
+     * @return true if the computed flag is set
+     */
+    public boolean isComputed() {
+        return computed;
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java	Wed Jul 05 21:39:33 2017 +0200
@@ -133,8 +133,8 @@
             return enterASSIGN_SHR(binaryNode);
         case ASSIGN_SUB:
             return enterASSIGN_SUB(binaryNode);
-        case BIND:
-            return enterBIND(binaryNode);
+        case ARROW:
+            return enterARROW(binaryNode);
         case BIT_AND:
             return enterBIT_AND(binaryNode);
         case BIT_OR:
@@ -217,8 +217,8 @@
             return leaveASSIGN_SHR(binaryNode);
         case ASSIGN_SUB:
             return leaveASSIGN_SUB(binaryNode);
-        case BIND:
-            return leaveBIND(binaryNode);
+        case ARROW:
+            return leaveARROW(binaryNode);
         case BIT_AND:
             return leaveBIT_AND(binaryNode);
         case BIT_OR:
@@ -735,22 +735,22 @@
     }
 
     /**
-     * Binary enter - callback for entering a bind operator
+     * Binary enter - callback for entering a arrow operator
      *
      * @param  binaryNode the node
      * @return true if traversal should continue and node children be traversed, false otherwise
      */
-    public boolean enterBIND(final BinaryNode binaryNode) {
+    public boolean enterARROW(final BinaryNode binaryNode) {
         return enterDefault(binaryNode);
     }
 
     /**
-     * Binary leave - callback for leaving a bind operator
+     * Binary leave - callback for leaving a arrow operator
      *
      * @param  binaryNode the node
      * @return processed node, which will replace the original one, or the original node
      */
-    public Node leaveBIND(final BinaryNode binaryNode) {
+    public Node leaveARROW(final BinaryNode binaryNode) {
         return leaveDefault(binaryNode);
     }
 
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Wed Jul 05 21:39:33 2017 +0200
@@ -33,6 +33,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;
@@ -897,5 +898,23 @@
         return leaveDefault(withNode);
     }
 
+    /**
+     * Callback for entering a ClassNode
+     *
+     * @param  classNode  the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterClassNode(final ClassNode classNode) {
+        return enterDefault(classNode);
+    }
 
+    /**
+     * Callback for leaving a ClassNode
+     *
+     * @param  classNode  the node
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveClassNode(final ClassNode classNode) {
+        return leaveDefault(classNode);
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Wed Jul 05 21:39:33 2017 +0200
@@ -28,35 +28,55 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
 import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
+import static jdk.nashorn.internal.parser.TokenType.ARROW;
 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
 import static jdk.nashorn.internal.parser.TokenType.CASE;
 import static jdk.nashorn.internal.parser.TokenType.CATCH;
+import static jdk.nashorn.internal.parser.TokenType.CLASS;
 import static jdk.nashorn.internal.parser.TokenType.COLON;
 import static jdk.nashorn.internal.parser.TokenType.COMMARIGHT;
+import static jdk.nashorn.internal.parser.TokenType.COMMENT;
 import static jdk.nashorn.internal.parser.TokenType.CONST;
 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.DECPREFIX;
+import static jdk.nashorn.internal.parser.TokenType.ELLIPSIS;
 import static jdk.nashorn.internal.parser.TokenType.ELSE;
 import static jdk.nashorn.internal.parser.TokenType.EOF;
 import static jdk.nashorn.internal.parser.TokenType.EOL;
+import static jdk.nashorn.internal.parser.TokenType.EQ_STRICT;
+import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
+import static jdk.nashorn.internal.parser.TokenType.EXPORT;
+import static jdk.nashorn.internal.parser.TokenType.EXTENDS;
 import static jdk.nashorn.internal.parser.TokenType.FINALLY;
 import static jdk.nashorn.internal.parser.TokenType.FUNCTION;
 import static jdk.nashorn.internal.parser.TokenType.IDENT;
 import static jdk.nashorn.internal.parser.TokenType.IF;
+import static jdk.nashorn.internal.parser.TokenType.IMPORT;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.LBRACE;
+import static jdk.nashorn.internal.parser.TokenType.LBRACKET;
 import static jdk.nashorn.internal.parser.TokenType.LET;
 import static jdk.nashorn.internal.parser.TokenType.LPAREN;
+import static jdk.nashorn.internal.parser.TokenType.MUL;
+import static jdk.nashorn.internal.parser.TokenType.PERIOD;
 import static jdk.nashorn.internal.parser.TokenType.RBRACE;
 import static jdk.nashorn.internal.parser.TokenType.RBRACKET;
 import static jdk.nashorn.internal.parser.TokenType.RPAREN;
 import static jdk.nashorn.internal.parser.TokenType.SEMICOLON;
+import static jdk.nashorn.internal.parser.TokenType.SPREAD_ARRAY;
+import static jdk.nashorn.internal.parser.TokenType.STATIC;
+import static jdk.nashorn.internal.parser.TokenType.STRING;
+import static jdk.nashorn.internal.parser.TokenType.SUPER;
 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE;
 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_HEAD;
 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_MIDDLE;
 import static jdk.nashorn.internal.parser.TokenType.TEMPLATE_TAIL;
 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
+import static jdk.nashorn.internal.parser.TokenType.VAR;
+import static jdk.nashorn.internal.parser.TokenType.VOID;
 import static jdk.nashorn.internal.parser.TokenType.WHILE;
+import static jdk.nashorn.internal.parser.TokenType.YIELD;
+import static jdk.nashorn.internal.parser.TokenType.YIELD_STAR;
 
 import java.io.Serializable;
 import java.util.ArrayDeque;
@@ -68,6 +88,8 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.Namespace;
 import jdk.nashorn.internal.ir.AccessNode;
@@ -79,11 +101,13 @@
 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;
 import jdk.nashorn.internal.ir.ErrorNode;
 import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionList;
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -92,7 +116,9 @@
 import jdk.nashorn.internal.ir.IndexNode;
 import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.Module;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
 import jdk.nashorn.internal.ir.PropertyKey;
@@ -110,6 +136,7 @@
 import jdk.nashorn.internal.ir.WithNode;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSErrorType;
@@ -254,6 +281,14 @@
     }
 
     /**
+     * Set up first token. Skips opening EOL.
+     */
+    private void scanFirstToken() {
+        k = -1;
+        next();
+    }
+
+    /**
      * Execute parse and return the resulting function node.
      * Errors will be thrown and the error manager will contain information
      * if parsing should fail
@@ -280,9 +315,7 @@
             lexer.line = lexer.pendingLine = lineOffset + 1;
             line = lineOffset;
 
-            // Set up first token (skips opening EOL.)
-            k = -1;
-            next();
+            scanFirstToken();
             // Begin parse.
             return program(scriptName, allowPropertyFunction);
         } catch (final Exception e) {
@@ -301,6 +334,44 @@
     }
 
     /**
+     * Parse and return the resulting module.
+     * Errors will be thrown and the error manager will contain information
+     * if parsing should fail
+     *
+     * @param moduleName name for the module, given to the parsed FunctionNode
+     * @param startPos start position in source
+     * @param len length of parse
+     *
+     * @return function node resulting from successful parse
+     */
+    public FunctionNode parseModule(final String moduleName, final int startPos, final int len) {
+        try {
+            stream = new TokenStream();
+            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions, env._es6, reparsedFunction != null);
+            lexer.line = lexer.pendingLine = lineOffset + 1;
+            line = lineOffset;
+
+            scanFirstToken();
+            // Begin parse.
+            return module(moduleName);
+        } catch (final Exception e) {
+            handleParseException(e);
+
+            return null;
+        }
+    }
+
+    /**
+     * Entry point for parsing a module.
+     *
+     * @param moduleName the module name
+     * @return the parsed module
+     */
+    public FunctionNode parseModule(final String moduleName) {
+        return parseModule(moduleName, 0, source.getLength());
+    }
+
+    /**
      * Parse and return the list of function parameter list. A comma
      * separated list of function parameter identifiers is expected to be parsed.
      * Errors will be thrown and the error manager will contain information
@@ -314,11 +385,9 @@
             stream = new TokenStream();
             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
 
-            // Set up first token (skips opening EOL.)
-            k = -1;
-            next();
-
-            return formalParameterList(TokenType.EOF);
+            scanFirstToken();
+
+            return formalParameterList(TokenType.EOF, false);
         } catch (final Exception e) {
             handleParseException(e);
             return null;
@@ -339,9 +408,7 @@
             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions, env._es6);
             final int functionLine = line;
 
-            // Set up first token (skips opening EOL.)
-            k = -1;
-            next();
+            scanFirstToken();
 
             // Make a fake token for the function.
             final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
@@ -432,7 +499,7 @@
         }
 
         // Skip to a recovery point.
-loop:
+        loop:
         while (true) {
             switch (type) {
             case EOF:
@@ -474,7 +541,7 @@
         sb.append(ident.getName());
 
         final String name = namespace.uniqueName(sb.toString());
-        assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
+        assert parentFunction != null || name.equals(PROGRAM.symbolName()) : "name = " + name;
 
         int flags = 0;
         if (isStrictMode) {
@@ -489,7 +556,8 @@
         return functionNode;
     }
 
-    private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body){
+    private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine, final Block body) {
+        // assert body.isFunctionBody() || body.getFlag(Block.IS_PARAMETER_BLOCK) && ((BlockStatement) body.getLastStatement()).getBlock().isFunctionBody();
         // Start new block.
         final FunctionNode functionNode =
             new FunctionNode(
@@ -506,7 +574,9 @@
                 kind,
                 function.getFlags(),
                 body,
-                function.getEndParserState());
+                function.getEndParserState(),
+                function.getModule(),
+                function.getDebugFlags());
 
         printAST(functionNode);
 
@@ -544,23 +614,39 @@
             expect(RBRACE);
         }
 
-        final int flags = newBlock.getFlags() | (needsBraces? 0 : Block.IS_SYNTHETIC);
+        final int flags = newBlock.getFlags() | (needsBraces ? 0 : Block.IS_SYNTHETIC);
         return new Block(blockToken, finish, flags, newBlock.getStatements());
     }
 
+    /**
+     * Get the statements in a case clause.
+     */
+    private List<Statement> caseStatementList() {
+        final ParserContextBlockNode newBlock = newBlock();
+        try {
+            statementList();
+        } finally {
+            restoreBlock(newBlock);
+        }
+        return newBlock.getStatements();
+    }
 
     /**
      * Get all the statements generated by a single statement.
      * @return Statements.
      */
     private Block getStatement() {
+        return getStatement(false);
+    }
+
+    private Block getStatement(boolean labelledStatement) {
         if (type == LBRACE) {
             return getBlock(true);
         }
         // Set up new block. Captures first token.
         final ParserContextBlockNode newBlock = newBlock();
         try {
-            statement(false, false, true);
+            statement(false, false, true, labelledStatement);
         } finally {
             restoreBlock(newBlock);
         }
@@ -576,6 +662,9 @@
 
         if (EVAL.symbolName().equals(name)) {
             markEval(lc);
+        } else if (SUPER.getName().equals(name)) {
+            assert ident.isDirectSuper();
+            markSuperCall(lc);
         }
     }
 
@@ -585,7 +674,8 @@
      */
     private void detectSpecialProperty(final IdentNode ident) {
         if (isArguments(ident)) {
-            lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS);
+            // skip over arrow functions, e.g. function f() { return (() => arguments.length)(); }
+            getCurrentNonArrowFunction().setFlag(FunctionNode.USES_ARGUMENTS);
         }
     }
 
@@ -593,11 +683,15 @@
         return env._es6;
     }
 
+    private boolean isES6() {
+        return env._es6;
+    }
+
     private static boolean isArguments(final String name) {
         return ARGUMENTS_NAME.equals(name);
     }
 
-    private static boolean isArguments(final IdentNode ident) {
+    static boolean isArguments(final IdentNode ident) {
         return isArguments(ident.getName());
     }
 
@@ -634,20 +728,20 @@
         case ASSIGN_SHL:
         case ASSIGN_SHR:
         case ASSIGN_SUB:
-            if (!(lhs instanceof AccessNode ||
-                  lhs instanceof IndexNode ||
-                  lhs instanceof IdentNode)) {
-                return referenceError(lhs, rhs, env._early_lvalue_error);
-            }
-
             if (lhs instanceof IdentNode) {
                 if (!checkIdentLValue((IdentNode)lhs)) {
                     return referenceError(lhs, rhs, false);
                 }
-                verifyStrictIdent((IdentNode)lhs, "assignment");
+                verifyIdent((IdentNode)lhs, "assignment");
+                break;
+            } else if (lhs instanceof AccessNode || lhs instanceof IndexNode) {
+                break;
+            } else if (opType == ASSIGN && isDestructuringLhs(lhs)) {
+                verifyDestructuringAssignmentPattern(lhs, "assignment");
+                break;
+            } else {
+                return referenceError(lhs, rhs, env._early_lvalue_error);
             }
-            break;
-
         default:
             break;
         }
@@ -659,6 +753,114 @@
         return new BinaryNode(op, lhs, rhs);
     }
 
+    private boolean isDestructuringLhs(Expression lhs) {
+        if (lhs instanceof ObjectNode || lhs instanceof LiteralNode.ArrayLiteralNode) {
+            return isES6();
+        }
+        return false;
+    }
+
+    private void verifyDestructuringAssignmentPattern(Expression pattern, String contextString) {
+        assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
+        pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public boolean enterLiteralNode(LiteralNode<?> literalNode) {
+                if (literalNode.isArray()) {
+                    boolean restElement = false;
+                    for (Expression element : literalNode.getElementExpressions()) {
+                        if (element != null) {
+                            if (restElement) {
+                                throw error(String.format("Unexpected element after rest element"), element.getToken());
+                            }
+                            if (element.isTokenType(SPREAD_ARRAY)) {
+                                restElement = true;
+                                Expression lvalue = ((UnaryNode) element).getExpression();
+                                if (!checkValidLValue(lvalue, contextString)) {
+                                    throw error(AbstractParser.message("invalid.lvalue"), lvalue.getToken());
+                                }
+                            }
+                            element.accept(this);
+                        }
+                    }
+                    return false;
+                } else {
+                    return enterDefault(literalNode);
+                }
+            }
+
+            @Override
+            public boolean enterObjectNode(ObjectNode objectNode) {
+                return true;
+            }
+
+            @Override
+            public boolean enterPropertyNode(PropertyNode propertyNode) {
+                if (propertyNode.getValue() != null) {
+                    propertyNode.getValue().accept(this);
+                    return false;
+                } else {
+                    return enterDefault(propertyNode);
+                }
+            }
+
+            @Override
+            public boolean enterIdentNode(IdentNode identNode) {
+                verifyIdent(identNode, contextString);
+                if (!checkIdentLValue(identNode)) {
+                    referenceError(identNode, null, true);
+                    return false;
+                }
+                return false;
+            }
+
+            @Override
+            public boolean enterAccessNode(AccessNode accessNode) {
+                return false;
+            }
+
+            @Override
+            public boolean enterIndexNode(IndexNode indexNode) {
+                return false;
+            }
+
+            @Override
+            public boolean enterBinaryNode(BinaryNode binaryNode) {
+                if (binaryNode.isTokenType(ASSIGN)) {
+                    binaryNode.lhs().accept(this);
+                    // Initializer(rhs) can be any AssignmentExpression
+                    return false;
+                } else {
+                    return enterDefault(binaryNode);
+                }
+            }
+
+            @Override
+            public boolean enterUnaryNode(UnaryNode unaryNode) {
+                if (unaryNode.isTokenType(SPREAD_ARRAY)) {
+                    // rest element
+                    return true;
+                } else {
+                    return enterDefault(unaryNode);
+                }
+            }
+
+            @Override
+            protected boolean enterDefault(Node node) {
+                throw error(String.format("unexpected node in AssignmentPattern: %s", node));
+            }
+        });
+    }
+
+    private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) {
+        final TokenType opType = Token.descType(op);
+
+        // Build up node.
+        if (BinaryNode.isLogical(opType)) {
+            return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
+        }
+        return new BinaryNode(op, lhs, rhs);
+    }
+
 
     /**
      * Reduce increment/decrement to simpler operations.
@@ -717,7 +919,7 @@
 
         restoreBlock(body);
         body.setFlag(Block.NEEDS_SCOPE);
-        final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC, body.getStatements());
+        final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
         lc.pop(script);
         script.setLastToken(token);
 
@@ -776,7 +978,7 @@
 
                 try {
                     // Get the next element.
-                    statement(true, allowPropertyFunction, false);
+                    statement(true, allowPropertyFunction, false, false);
                     allowPropertyFunction = false;
 
                     // check for directive prologues
@@ -816,16 +1018,16 @@
 
                                     // verify that function name as well as parameter names
                                     // satisfy strict mode restrictions.
-                                    verifyStrictIdent(function.getIdent(), "function name");
+                                    verifyIdent(function.getIdent(), "function name");
                                     for (final IdentNode param : function.getParameters()) {
-                                        verifyStrictIdent(param, "function parameter");
+                                        verifyIdent(param, "function parameter");
                                     }
                                 }
                             } else if (Context.DEBUG) {
-                                final int flag = FunctionNode.getDirectiveFlag(directive);
-                                if (flag != 0) {
+                                final int debugFlag = FunctionNode.getDirectiveFlag(directive);
+                                if (debugFlag != 0) {
                                     final ParserContextFunctionNode function = lc.getCurrentFunction();
-                                    function.setFlag(flag);
+                                    function.setDebugFlag(debugFlag);
                                 }
                             }
                         }
@@ -849,29 +1051,53 @@
     }
 
     /**
+     * Parse any of the basic statement types.
+     *
      * Statement :
-     *      Block
+     *      BlockStatement
      *      VariableStatement
      *      EmptyStatement
      *      ExpressionStatement
      *      IfStatement
-     *      IterationStatement
+     *      BreakableStatement
      *      ContinueStatement
      *      BreakStatement
      *      ReturnStatement
      *      WithStatement
      *      LabelledStatement
-     *      SwitchStatement
      *      ThrowStatement
      *      TryStatement
      *      DebuggerStatement
      *
-     * see 12
+     * BreakableStatement :
+     *      IterationStatement
+     *      SwitchStatement
+     *
+     * BlockStatement :
+     *      Block
+     *
+     * Block :
+     *      { StatementList opt }
      *
-     * Parse any of the basic statement types.
+     * StatementList :
+     *      StatementListItem
+     *      StatementList StatementListItem
+     *
+     * StatementItem :
+     *      Statement
+     *      Declaration
+     *
+     * Declaration :
+     *     HoistableDeclaration
+     *     ClassDeclaration
+     *     LexicalDeclaration
+     *
+     * HoistableDeclaration :
+     *     FunctionDeclaration
+     *     GeneratorDeclaration
      */
     private void statement() {
-        statement(false, false, false);
+        statement(false, false, false, false);
     }
 
     /**
@@ -879,14 +1105,7 @@
      * @param allowPropertyFunction allow property "get" and "set" functions?
      * @param singleStatement are we in a single statement context?
      */
-    private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement) {
-        if (type == FUNCTION) {
-            // As per spec (ECMA section 12), function declarations as arbitrary statement
-            // is not "portable". Implementation can issue a warning or disallow the same.
-            functionExpression(true, topLevel);
-            return;
-        }
-
+    private void statement(final boolean topLevel, final boolean allowPropertyFunction, final boolean singleStatement, final boolean labelledStatement) {
         switch (type) {
         case LBRACE:
             block();
@@ -918,9 +1137,6 @@
         case RETURN:
             returnStatement();
             break;
-        case YIELD:
-            yieldStatement();
-            break;
         case WITH:
             withStatement();
             break;
@@ -941,13 +1157,32 @@
         case EOF:
             expect(SEMICOLON);
             break;
+        case FUNCTION:
+            // As per spec (ECMA section 12), function declarations as arbitrary statement
+            // is not "portable". Implementation can issue a warning or disallow the same.
+            if (singleStatement) {
+                // ES6 B.3.2 Labelled Function Declarations
+                // It is a Syntax Error if any strict mode source code matches this rule:
+                // LabelledItem : FunctionDeclaration.
+                if (!labelledStatement || isStrictMode) {
+                    throw error(AbstractParser.message("expected.stmt", "function declaration"), token);
+                }
+            }
+            functionExpression(true, topLevel || labelledStatement);
+            return;
         default:
-            if (useBlockScope() && (type == LET || type == CONST)) {
+            if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(false) || type == CONST)) {
                 if (singleStatement) {
                     throw error(AbstractParser.message("expected.stmt", type.getName() + " declaration"), token);
                 }
                 variableStatement(type);
                 break;
+            } else if (type == CLASS && isES6()) {
+                if (singleStatement) {
+                    throw error(AbstractParser.message("expected.stmt", "class declaration"), token);
+                }
+                classDeclaration(false);
+                break;
             }
             if (env._const_as_var && type == CONST) {
                 variableStatement(TokenType.VAR);
@@ -963,11 +1198,11 @@
                     final String ident = (String)getValue();
                     final long propertyToken = token;
                     final int propertyLine = line;
-                    if("get".equals(ident)) {
+                    if ("get".equals(ident)) {
                         next();
                         addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
                         return;
-                    } else if("set".equals(ident)) {
+                    } else if ("set".equals(ident)) {
                         next();
                         addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
                         return;
@@ -986,6 +1221,267 @@
     }
 
     /**
+     * ClassDeclaration[Yield, Default] :
+     *   class BindingIdentifier[?Yield] ClassTail[?Yield]
+     *   [+Default] class ClassTail[?Yield]
+     */
+    private ClassNode classDeclaration(boolean isDefault) {
+        int classLineNumber = line;
+
+        ClassNode classExpression = classExpression(!isDefault);
+
+        if (!isDefault) {
+            VarNode classVar = new VarNode(classLineNumber, classExpression.getToken(), classExpression.getIdent().getFinish(), classExpression.getIdent(), classExpression, VarNode.IS_CONST);
+            appendStatement(classVar);
+        }
+        return classExpression;
+    }
+
+    /**
+     * ClassExpression[Yield] :
+     *   class BindingIdentifier[?Yield]opt ClassTail[?Yield]
+     */
+    private ClassNode classExpression(boolean isStatement) {
+        assert type == CLASS;
+        int classLineNumber = line;
+        long classToken = token;
+        next();
+
+        IdentNode className = null;
+        if (isStatement || type == IDENT) {
+            className = getIdent();
+        }
+
+        return classTail(classLineNumber, classToken, className);
+    }
+
+    private static final class ClassElementKey {
+        private final boolean isStatic;
+        private final String propertyName;
+
+        private ClassElementKey(boolean isStatic, String propertyName) {
+            this.isStatic = isStatic;
+            this.propertyName = propertyName;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (isStatic ? 1231 : 1237);
+            result = prime * result + ((propertyName == null) ? 0 : propertyName.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof ClassElementKey) {
+                ClassElementKey other = (ClassElementKey) obj;
+                return this.isStatic == other.isStatic && Objects.equals(this.propertyName, other.propertyName);
+            }
+            return false;
+        }
+    }
+
+    /**
+     * Parse ClassTail and ClassBody.
+     *
+     * ClassTail[Yield] :
+     *   ClassHeritage[?Yield]opt { ClassBody[?Yield]opt }
+     * ClassHeritage[Yield] :
+     *   extends LeftHandSideExpression[?Yield]
+     *
+     * ClassBody[Yield] :
+     *   ClassElementList[?Yield]
+     * ClassElementList[Yield] :
+     *   ClassElement[?Yield]
+     *   ClassElementList[?Yield] ClassElement[?Yield]
+     * ClassElement[Yield] :
+     *   MethodDefinition[?Yield]
+     *   static MethodDefinition[?Yield]
+     *   ;
+     */
+    private ClassNode classTail(final int classLineNumber, final long classToken, final IdentNode className) {
+        final boolean oldStrictMode = isStrictMode;
+        isStrictMode = true;
+        try {
+            Expression classHeritage = null;
+            if (type == EXTENDS) {
+                next();
+                classHeritage = leftHandSideExpression();
+            }
+
+            expect(LBRACE);
+
+            PropertyNode constructor = null;
+            final ArrayList<PropertyNode> classElements = new ArrayList<>();
+            final Map<ClassElementKey, Integer> keyToIndexMap = new HashMap<>();
+            for (;;) {
+                if (type == SEMICOLON) {
+                    next();
+                    continue;
+                }
+                if (type == RBRACE) {
+                    break;
+                }
+                final long classElementToken = token;
+                boolean isStatic = false;
+                if (type == STATIC) {
+                    isStatic = true;
+                    next();
+                }
+                boolean generator = false;
+                if (isES6() && type == MUL) {
+                    generator = true;
+                    next();
+                }
+                final PropertyNode classElement = methodDefinition(isStatic, classHeritage != null, generator);
+                if (classElement.isComputed()) {
+                    classElements.add(classElement);
+                } else if (!classElement.isStatic() && classElement.getKeyName().equals("constructor")) {
+                    if (constructor == null) {
+                        constructor = classElement;
+                    } else {
+                        throw error(AbstractParser.message("multiple.constructors"), classElementToken);
+                    }
+                } else {
+                    // Check for duplicate method definitions and combine accessor methods.
+                    // In ES6, a duplicate is never an error regardless of strict mode (in consequence of computed property names).
+
+                    final ClassElementKey key = new ClassElementKey(classElement.isStatic(), classElement.getKeyName());
+                    final Integer existing = keyToIndexMap.get(key);
+
+                    if (existing == null) {
+                        keyToIndexMap.put(key, classElements.size());
+                        classElements.add(classElement);
+                    } else {
+                        final PropertyNode existingProperty = classElements.get(existing);
+
+                        final Expression   value  = classElement.getValue();
+                        final FunctionNode getter = classElement.getGetter();
+                        final FunctionNode setter = classElement.getSetter();
+
+                        if (value != null || existingProperty.getValue() != null) {
+                            keyToIndexMap.put(key, classElements.size());
+                            classElements.add(classElement);
+                        } else if (getter != null) {
+                            assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
+                            classElements.set(existing, existingProperty.setGetter(getter));
+                        } else if (setter != null) {
+                            assert existingProperty.getGetter() != null || existingProperty.getSetter() != null;
+                            classElements.set(existing, existingProperty.setSetter(setter));
+                        }
+                    }
+                }
+            }
+
+            final long lastToken = token;
+            expect(RBRACE);
+
+            if (constructor == null) {
+                constructor = createDefaultClassConstructor(classLineNumber, classToken, lastToken, className, classHeritage != null);
+            }
+
+            classElements.trimToSize();
+            return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements);
+        } finally {
+            isStrictMode = oldStrictMode;
+        }
+    }
+
+    private PropertyNode createDefaultClassConstructor(int classLineNumber, long classToken, long lastToken, IdentNode className, boolean subclass) {
+        final int ctorFinish = finish;
+        final List<Statement> statements;
+        final List<IdentNode> parameters;
+        final long identToken = Token.recast(classToken, TokenType.IDENT);
+        if (subclass) {
+            final IdentNode superIdent = createIdentNode(identToken, ctorFinish, SUPER.getName()).setIsDirectSuper();
+            final IdentNode argsIdent = createIdentNode(identToken, ctorFinish, "args").setIsRestParameter();
+            final Expression spreadArgs = new UnaryNode(Token.recast(classToken, TokenType.SPREAD_ARGUMENT), argsIdent);
+            final CallNode superCall = new CallNode(classLineNumber, classToken, ctorFinish, superIdent, Collections.singletonList(spreadArgs), false);
+            statements = Collections.singletonList(new ExpressionStatement(classLineNumber, classToken, ctorFinish, superCall));
+            parameters = Collections.singletonList(argsIdent);
+        } else {
+            statements = Collections.emptyList();
+            parameters = Collections.emptyList();
+        }
+
+        final Block body = new Block(classToken, ctorFinish, Block.IS_BODY, statements);
+        final IdentNode ctorName = className != null ? className : createIdentNode(identToken, ctorFinish, "constructor");
+        final ParserContextFunctionNode function = createParserContextFunctionNode(ctorName, classToken, FunctionNode.Kind.NORMAL, classLineNumber, parameters);
+        function.setLastToken(lastToken);
+
+        function.setFlag(FunctionNode.ES6_IS_METHOD);
+        function.setFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR);
+        if (subclass) {
+            function.setFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR);
+            function.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
+        }
+        if (className == null) {
+            function.setFlag(FunctionNode.IS_ANONYMOUS);
+        }
+
+        final PropertyNode constructor = new PropertyNode(classToken, ctorFinish, ctorName, createFunctionNode(
+                        function,
+                        classToken,
+                        ctorName,
+                        parameters,
+                        FunctionNode.Kind.NORMAL,
+                        classLineNumber,
+                        body
+                        ), null, null, false, false);
+        return constructor;
+    }
+
+    private PropertyNode methodDefinition(final boolean isStatic, final boolean subclass, final boolean generator) {
+        final long methodToken = token;
+        final int methodLine = line;
+        final boolean computed = type == LBRACKET;
+        final boolean isIdent = type == IDENT;
+        final Expression propertyName = propertyName();
+        int flags = FunctionNode.ES6_IS_METHOD;
+        if (!computed) {
+            final String name = ((PropertyKey)propertyName).getPropertyName();
+            if (!generator && isIdent && type != LPAREN && name.equals("get")) {
+                final PropertyFunction methodDefinition = propertyGetterFunction(methodToken, methodLine, flags);
+                verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
+                return new PropertyNode(methodToken, finish, methodDefinition.key, null, methodDefinition.functionNode, null, isStatic, methodDefinition.computed);
+            } else if (!generator && isIdent && type != LPAREN && name.equals("set")) {
+                final PropertyFunction methodDefinition = propertySetterFunction(methodToken, methodLine, flags);
+                verifyAllowedMethodName(methodDefinition.key, isStatic, methodDefinition.computed, generator, true);
+                return new PropertyNode(methodToken, finish, methodDefinition.key, null, null, methodDefinition.functionNode, isStatic, methodDefinition.computed);
+            } else {
+                if (!isStatic && !generator && name.equals("constructor")) {
+                    flags |= FunctionNode.ES6_IS_CLASS_CONSTRUCTOR;
+                    if (subclass) {
+                        flags |= FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR;
+                    }
+                }
+                verifyAllowedMethodName(propertyName, isStatic, computed, generator, false);
+            }
+        }
+        final PropertyFunction methodDefinition = propertyMethodFunction(propertyName, methodToken, methodLine, generator, flags, computed);
+        return new PropertyNode(methodToken, finish, methodDefinition.key, methodDefinition.functionNode, null, null, isStatic, computed);
+    }
+
+    /**
+     * ES6 14.5.1 Static Semantics: Early Errors.
+     */
+    private void verifyAllowedMethodName(final Expression key, final boolean isStatic, final boolean computed, final boolean generator, final boolean accessor) {
+        if (!computed) {
+            if (!isStatic && generator && ((PropertyKey) key).getPropertyName().equals("constructor")) {
+                throw error(AbstractParser.message("generator.constructor"), key.getToken());
+            }
+            if (!isStatic && accessor && ((PropertyKey) key).getPropertyName().equals("constructor")) {
+                throw error(AbstractParser.message("accessor.constructor"), key.getToken());
+            }
+            if (isStatic && ((PropertyKey) key).getPropertyName().equals("prototype")) {
+                throw error(AbstractParser.message("static.prototype.method"), key.getToken());
+            }
+        }
+    }
+
+    /**
      * block :
      *      { StatementList? }
      *
@@ -1008,7 +1504,7 @@
      */
     private void statementList() {
         // Accumulate statements until end of list. */
-loop:
+        loop:
         while (type != EOF) {
             switch (type) {
             case EOF:
@@ -1026,6 +1522,22 @@
     }
 
     /**
+     * Make sure that the identifier name used is allowed.
+     *
+     * @param ident         Identifier that is verified
+     * @param contextString String used in error message to give context to the user
+     */
+    private void verifyIdent(final IdentNode ident, final String contextString) {
+        verifyStrictIdent(ident, contextString);
+        if (isES6()) {
+            final TokenType tokenType = TokenLookup.lookupKeyword(ident.getName().toCharArray(), 0, ident.getName().length());
+            if (tokenType != IDENT && tokenType.getKind() != TokenKind.FUTURESTRICT) {
+                throw error(expectMessage(IDENT));
+            }
+        }
+    }
+
+    /**
      * Make sure that in strict mode, the identifier name used is allowed.
      *
      * @param ident         Identifier that is verified
@@ -1066,15 +1578,16 @@
      * Parse a VAR statement.
      * @param isStatement True if a statement (not used in a FOR.)
      */
-    private List<VarNode> variableStatement(final TokenType varType) {
-        return variableStatement(varType, true, -1);
+    private void variableStatement(final TokenType varType) {
+        variableDeclarationList(varType, true, -1);
     }
 
-    private List<VarNode> variableStatement(final TokenType varType, final boolean isStatement, final int sourceOrder) {
+    private List<Expression> variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
         // VAR tested in caller.
+        assert varType == VAR || varType == LET || varType == CONST;
         next();
 
-        final List<VarNode> vars = new ArrayList<>();
+        final List<Expression> bindings = new ArrayList<>();
         int varFlags = 0;
         if (varType == LET) {
             varFlags |= VarNode.IS_LET;
@@ -1082,13 +1595,29 @@
             varFlags |= VarNode.IS_CONST;
         }
 
+        Expression missingAssignment = null;
         while (true) {
             // Get starting token.
             final int  varLine  = line;
             final long varToken = token;
             // Get name of var.
-            final IdentNode name = getIdent();
-            verifyStrictIdent(name, "variable name");
+            if (type == YIELD && inGeneratorFunction()) {
+                expect(IDENT);
+            }
+
+            final String contextString = "variable name";
+            Expression binding = bindingIdentifierOrPattern(contextString);
+            final boolean isDestructuring = !(binding instanceof IdentNode);
+            if (isDestructuring) {
+                final int finalVarFlags = varFlags;
+                verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
+                    public void accept(final IdentNode identNode) {
+                        verifyIdent(identNode, contextString);
+                        final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
+                        appendStatement(var);
+                    }
+                });
+            }
 
             // Assume no init.
             Expression init = null;
@@ -1098,22 +1627,53 @@
                 next();
 
                 // Get initializer expression. Suppress IN if not statement.
-                defaultNames.push(name);
+                if (!isDestructuring) {
+                    defaultNames.push(binding);
+                }
                 try {
                     init = assignmentExpression(!isStatement);
                 } finally {
-                    defaultNames.pop();
+                    if (!isDestructuring) {
+                        defaultNames.pop();
+                    }
                 }
-            } else if (varType == CONST && isStatement) {
-                throw error(AbstractParser.message("missing.const.assignment", name.getName()));
+            } else if (isStatement) {
+                if (isDestructuring) {
+                    throw error(AbstractParser.message("missing.destructuring.assignment"), token);
+                } else if (varType == CONST) {
+                    throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)binding).getName()));
+                }
+                // else, if we are in a for loop, delay checking until we know the kind of loop
             }
 
-            // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
-            final IdentNode actualName = varType == LET || varType == CONST ? name.setIsDeclaredHere() : name;
-            // Allocate var node.
-            final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, actualName, init, varFlags);
-            vars.add(var);
-            appendStatement(var);
+            if (!isDestructuring) {
+                assert init != null || varType != CONST || !isStatement;
+                final IdentNode ident = (IdentNode)binding;
+                if (!isStatement && ident.getName().equals("let")) {
+                    throw error(AbstractParser.message("let.binding.for")); //ES6 13.7.5.1
+                }
+                // Only set declaration flag on lexically scoped let/const as it adds runtime overhead.
+                final IdentNode name = varType == LET || varType == CONST ? ident.setIsDeclaredHere() : ident;
+                binding = name;
+                final VarNode var = new VarNode(varLine, varToken, sourceOrder, finish, name, init, varFlags);
+                appendStatement(var);
+                if (init == null && varType == CONST) {
+                    if (missingAssignment == null) {
+                        missingAssignment = binding;
+                    }
+                }
+            } else {
+                assert init != null || !isStatement;
+                binding = init == null ? binding : verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
+                if (isStatement) {
+                    appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding));
+                } else if (init == null) {
+                    if (missingAssignment == null) {
+                        missingAssignment = binding;
+                    }
+                }
+            }
+            bindings.add(binding);
 
             if (type != COMMARIGHT) {
                 break;
@@ -1124,9 +1684,128 @@
         // If is a statement then handle end of line.
         if (isStatement) {
             endOfLine();
+        } else {
+            if (type == SEMICOLON) {
+                // late check for missing assignment, now we know it's a for (init; test; modify) loop
+                if (missingAssignment != null) {
+                    if (missingAssignment instanceof IdentNode) {
+                        throw error(AbstractParser.message("missing.const.assignment", ((IdentNode)missingAssignment).getName()));
+                    } else {
+                        throw error(AbstractParser.message("missing.destructuring.assignment"), missingAssignment.getToken());
+                    }
+                }
+            }
         }
 
-        return vars;
+        return bindings;
+    }
+
+    private boolean isBindingIdentifier() {
+        return type == IDENT || isNonStrictModeIdent();
+    }
+
+    private IdentNode bindingIdentifier(final String contextString) {
+        final IdentNode name = getIdent();
+        verifyIdent(name, contextString);
+        return name;
+    }
+
+    private Expression bindingPattern() {
+        if (type == LBRACKET) {
+            return arrayLiteral();
+        } else if (type == LBRACE) {
+            return objectLiteral();
+        } else {
+            throw error(AbstractParser.message("expected.binding"));
+        }
+    }
+
+    private Expression bindingIdentifierOrPattern(final String contextString) {
+        if (isBindingIdentifier() || !isES6()) {
+            return bindingIdentifier(contextString);
+        } else {
+            return bindingPattern();
+        }
+    }
+
+    /**
+     * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
+     */
+    private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
+        assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
+        pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+                if (literalNode.isArray()) {
+                    boolean restElement = false;
+                    for (final Expression element : literalNode.getElementExpressions()) {
+                        if (restElement) {
+                            throw error(String.format("Unexpected element after rest element"), element.getToken());
+                        }
+                        if (element != null) {
+                            if (element.isTokenType(SPREAD_ARRAY)) {
+                                restElement = true;
+                                if (!(((UnaryNode) element).getExpression() instanceof IdentNode)) {
+                                    throw error(String.format("Expected a valid binding identifier"), element.getToken());
+
+                                }
+                            }
+                            element.accept(this);
+                        }
+                    }
+                    return false;
+                } else {
+                    return enterDefault(literalNode);
+                }
+            }
+
+            @Override
+            public boolean enterObjectNode(final ObjectNode objectNode) {
+                return true;
+            }
+
+            @Override
+            public boolean enterPropertyNode(final PropertyNode propertyNode) {
+                if (propertyNode.getValue() != null) {
+                    propertyNode.getValue().accept(this);
+                    return false;
+                } else {
+                    return enterDefault(propertyNode);
+                }
+            }
+
+            @Override
+            public boolean enterIdentNode(final IdentNode identNode) {
+                identifierCallback.accept(identNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterBinaryNode(final BinaryNode binaryNode) {
+                if (binaryNode.isTokenType(ASSIGN)) {
+                    binaryNode.lhs().accept(this);
+                    // Initializer(rhs) can be any AssignmentExpression
+                    return false;
+                } else {
+                    return enterDefault(binaryNode);
+                }
+            }
+
+            @Override
+            public boolean enterUnaryNode(final UnaryNode unaryNode) {
+                if (unaryNode.isTokenType(SPREAD_ARRAY)) {
+                    // rest element
+                    return true;
+                } else {
+                    return enterDefault(unaryNode);
+                }
+            }
+
+            @Override
+            protected boolean enterDefault(final Node node) {
+                throw error(String.format("unexpected node in BindingPattern: %s", node));
+            }
+        });
     }
 
     /**
@@ -1230,7 +1909,7 @@
         final ParserContextLoopNode forNode = new ParserContextLoopNode();
         lc.push(forNode);
         Block body = null;
-        List<VarNode> vars = null;
+        List<Expression> vars = null;
         Expression init = null;
         JoinPredecessorExpression test = null;
         JoinPredecessorExpression modify = null;
@@ -1254,20 +1933,20 @@
             switch (type) {
             case VAR:
                 // Var declaration captured in for outer block.
-                vars = variableStatement(type, false, forStart);
+                vars = variableDeclarationList(type, false, forStart);
                 break;
             case SEMICOLON:
                 break;
             default:
-                if (useBlockScope() && (type == LET || type == CONST)) {
+                if (useBlockScope() && (type == LET && lookaheadIsLetDeclaration(true) || type == CONST)) {
                     flags |= ForNode.PER_ITERATION_SCOPE;
                     // LET/CONST declaration captured in container block created above.
-                    vars = variableStatement(type, false, forStart);
+                    vars = variableDeclarationList(type, false, forStart);
                     break;
                 }
                 if (env._const_as_var && type == CONST) {
                     // Var declaration captured in for outer block.
-                    vars = variableStatement(TokenType.VAR, false, forStart);
+                    vars = variableDeclarationList(TokenType.VAR, false, forStart);
                     break;
                 }
 
@@ -1309,7 +1988,11 @@
                 if (vars != null) {
                     // for (var i in obj)
                     if (vars.size() == 1) {
-                        init = new IdentNode(vars.get(0).getName());
+                        init = new IdentNode((IdentNode)vars.get(0));
+                        if (init.isTokenType(ASSIGN)) {
+                            throw error(AbstractParser.message("for.in.loop.initializer"), init.getToken());
+                        }
+                        assert init instanceof IdentNode || isDestructuringLhs(init);
                     } else {
                         // for (var i, j in obj) is invalid
                         throw error(AbstractParser.message("many.vars.in.for.in.loop", isForOf ? "of" : "in"), vars.get(1).getToken());
@@ -1351,10 +2034,9 @@
         } finally {
             lc.pop(forNode);
 
-            if (vars != null) {
-                for (final VarNode var : vars) {
-                    appendStatement(var);
-                }
+            for (final Statement var : forNode.getStatements()) {
+                assert var instanceof VarNode;
+                appendStatement(var);
             }
             if (body != null) {
                 appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify));
@@ -1371,6 +2053,49 @@
         }
     }
 
+    private boolean checkValidLValue(final Expression init, final String contextString) {
+        if (init instanceof IdentNode) {
+            if (!checkIdentLValue((IdentNode)init)) {
+                return false;
+            }
+            verifyIdent((IdentNode)init, contextString);
+            return true;
+        } else if (init instanceof AccessNode || init instanceof IndexNode) {
+            return true;
+        } else if (isDestructuringLhs(init)) {
+            verifyDestructuringAssignmentPattern(init, contextString);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean lookaheadIsLetDeclaration(final boolean ofContextualKeyword) {
+        assert type == LET;
+        for (int i = 1;; i++) {
+            TokenType t = T(k + i);
+            switch (t) {
+            case EOL:
+            case COMMENT:
+                continue;
+            case IDENT:
+                if (ofContextualKeyword && isES6() && "of".equals(getValue(getToken(k + i)))) {
+                    return false;
+                }
+                // fall through
+            case LBRACKET:
+            case LBRACE:
+                return true;
+            default:
+                // accept future strict tokens in non-strict mode (including LET)
+                if (!isStrictMode && t.getKind() == TokenKind.FUTURESTRICT) {
+                    return true;
+                }
+                return false;
+            }
+        }
+    }
+
     /**
      * ...IterationStatement :
      *           ...
@@ -1559,7 +2284,7 @@
      */
     private void returnStatement() {
         // check for return outside function
-        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT) {
+        if (lc.getCurrentFunction().getKind() == FunctionNode.Kind.SCRIPT || lc.getCurrentFunction().getKind() == FunctionNode.Kind.MODULE) {
             throw error(AbstractParser.message("invalid.return"));
         }
 
@@ -1591,39 +2316,61 @@
     }
 
     /**
-     * YieldStatement :
-     *      yield Expression? ; // [no LineTerminator here]
-     *
-     * JavaScript 1.8
+     * Parse YieldExpression.
      *
-     * Parse YIELD statement.
+     * YieldExpression[In] :
+     *   yield
+     *   yield [no LineTerminator here] AssignmentExpression[?In, Yield]
+     *   yield [no LineTerminator here] * AssignmentExpression[?In, Yield]
      */
-    private void yieldStatement() {
+    private Expression yieldExpression(final boolean noIn) {
+        assert inGeneratorFunction();
         // Capture YIELD token.
-        final int  yieldLine  = line;
-        final long yieldToken = token;
+        long yieldToken = token;
         // YIELD tested in caller.
+        assert type == YIELD;
         nextOrEOL();
 
         Expression expression = null;
 
-        // SEMICOLON or expression.
+        boolean yieldAsterisk = false;
+        if (type == MUL) {
+            yieldAsterisk = true;
+            yieldToken = Token.recast(yieldToken, YIELD_STAR);
+            next();
+        }
+
         switch (type) {
         case RBRACE:
         case SEMICOLON:
         case EOL:
         case EOF:
-            break;
+        case COMMARIGHT:
+        case RPAREN:
+        case RBRACKET:
+        case COLON:
+            if (!yieldAsterisk) {
+                // treat (yield) as (yield void 0)
+                expression = newUndefinedLiteral(yieldToken, finish);
+                if (type == EOL) {
+                    next();
+                }
+                break;
+            } else {
+                // AssignmentExpression required, fall through
+            }
 
         default:
-            expression = expression();
+            expression = assignmentExpression(noIn);
             break;
         }
 
-        endOfLine();
-
         // Construct and add YIELD node.
-        appendStatement(new ReturnNode(yieldLine, yieldToken, finish, expression));
+        return new UnaryNode(yieldToken, expression);
+    }
+
+    private static UnaryNode newUndefinedLiteral(final long token, final int finish) {
+        return new UnaryNode(Token.recast(token, VOID), LiteralNode.newInstance(token, finish, 0));
     }
 
     /**
@@ -1679,11 +2426,15 @@
     private void switchStatement() {
         final int  switchLine  = line;
         final long switchToken = token;
+
+        // Block to capture variables declared inside the switch statement.
+        final ParserContextBlockNode switchBlock = newBlock();
+
         // SWITCH tested in caller.
         next();
 
         // Create and add switch statement.
-        final ParserContextSwitchNode switchNode= new ParserContextSwitchNode();
+        final ParserContextSwitchNode switchNode = new ParserContextSwitchNode();
         lc.push(switchNode);
 
         CaseNode defaultCase = null;
@@ -1727,7 +2478,7 @@
                 expect(COLON);
 
                 // Get CASE body.
-                final Block statements = getBlock(false);
+                final Block statements = getBlock(false); // TODO: List<Statement> statements = caseStatementList();
                 final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements);
 
                 if (caseExpression == null) {
@@ -1740,9 +2491,11 @@
             next();
         } finally {
             lc.pop(switchNode);
+            restoreBlock(switchBlock);
         }
 
-        appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase));
+        final SwitchNode switchStatement = new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase);
+        appendStatement(new BlockStatement(switchLine, new Block(switchToken, finish, switchBlock.getFlags() | Block.IS_SYNTHETIC | Block.IS_SWITCH_BLOCK, switchStatement)));
     }
 
     /**
@@ -1769,7 +2522,7 @@
         Block body = null;
         try {
             lc.push(labelNode);
-            body = getStatement();
+            body = getStatement(true);
         } finally {
             assert lc.peek() instanceof ParserContextLabelNode;
             lc.pop(labelNode);
@@ -1935,13 +2688,19 @@
     /**
      * PrimaryExpression :
      *      this
-     *      Identifier
+     *      IdentifierReference
      *      Literal
      *      ArrayLiteral
      *      ObjectLiteral
      *      RegularExpressionLiteral
      *      TemplateLiteral
+     *      CoverParenthesizedExpressionAndArrowParameterList
+     *
+     * CoverParenthesizedExpressionAndArrowParameterList :
      *      ( Expression )
+     *      ( )
+     *      ( ... BindingIdentifier )
+     *      ( Expression , ... BindingIdentifier )
      *
      * Parse primary expression.
      * @return Expression node.
@@ -1956,7 +2715,7 @@
         case THIS:
             final String name = type.getName();
             next();
-            lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS);
+            markThis(lc);
             return new IdentNode(primaryToken, finish, name);
         case IDENT:
             final IdentNode ident = getIdent();
@@ -1997,6 +2756,22 @@
         case LPAREN:
             next();
 
+            if (isES6()) {
+                if (type == RPAREN) {
+                    // ()
+                    nextOrEOL();
+                    expectDontAdvance(ARROW);
+                    return new ExpressionList(primaryToken, finish, Collections.emptyList());
+                } else if (type == ELLIPSIS) {
+                    // (...rest)
+                    final IdentNode restParam = formalParameterList(false).get(0);
+                    expectDontAdvance(RPAREN);
+                    nextOrEOL();
+                    expectDontAdvance(ARROW);
+                    return new ExpressionList(primaryToken, finish, Collections.singletonList(restParam));
+                }
+            }
+
             final Expression expression = expression();
 
             expect(RPAREN);
@@ -2073,8 +2848,9 @@
         final List<Expression> elements = new ArrayList<>();
         // Track elisions.
         boolean elision = true;
-loop:
+        loop:
         while (true) {
+            long spreadToken = 0;
             switch (type) {
             case RBRACKET:
                 next();
@@ -2093,14 +2869,24 @@
 
                 break;
 
+            case ELLIPSIS:
+                if (isES6()) {
+                    spreadToken = token;
+                    next();
+                }
+                // fall through
+
             default:
                 if (!elision) {
                     throw error(AbstractParser.message("expected.comma", type.getNameOrType()));
                 }
+
                 // Add expression element.
-                final Expression expression = assignmentExpression(false);
-
+                Expression expression = assignmentExpression(false);
                 if (expression != null) {
+                    if (spreadToken != 0) {
+                        expression = new UnaryNode(Token.recast(spreadToken, SPREAD_ARRAY), expression);
+                    }
                     elements.add(expression);
                 } else {
                     expect(RBRACKET);
@@ -2141,7 +2927,7 @@
 
         // Create a block for the object literal.
         boolean commaSeen = true;
-loop:
+        loop:
         while (true) {
             switch (type) {
                 case RBRACE:
@@ -2164,6 +2950,12 @@
                     commaSeen = false;
                     // Get and add the next property.
                     final PropertyNode property = propertyAssignment();
+
+                    if (property.isComputed()) {
+                        elements.add(property);
+                        break;
+                    }
+
                     final String key = property.getKeyName();
                     final Integer existing = map.get(key);
 
@@ -2185,36 +2977,23 @@
                     final FunctionNode prevGetter = existingProperty.getGetter();
                     final FunctionNode prevSetter = existingProperty.getSetter();
 
-                    // ECMA 11.1.5 strict mode restrictions
-                    if (isStrictMode && value != null && prevValue != null) {
-                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
-                    }
-
-                    final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
-                    final boolean isAccessor     = getter != null     || setter != null;
-
-                    // data property redefined as accessor property
-                    if (prevValue != null && isAccessor) {
-                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
-                    }
-
-                    // accessor property redefined as data
-                    if (isPrevAccessor && value != null) {
-                        throw error(AbstractParser.message("property.redefinition", key), property.getToken());
-                    }
-
-                    if (isAccessor && isPrevAccessor) {
-                        if (getter != null && prevGetter != null ||
-                                setter != null && prevSetter != null) {
-                            throw error(AbstractParser.message("property.redefinition", key), property.getToken());
+                    if (!isES6()) {
+                        checkPropertyRedefinition(property, value, getter, setter, prevValue, prevGetter, prevSetter);
+                    } else {
+                        if (property.getKey() instanceof IdentNode && ((IdentNode)property.getKey()).isProtoPropertyName() &&
+                                        existingProperty.getKey() instanceof IdentNode && ((IdentNode)existingProperty.getKey()).isProtoPropertyName()) {
+                            throw error(AbstractParser.message("multiple.proto.key"), property.getToken());
                         }
                     }
 
-                    if (value != null) {
+                    if (value != null || prevValue != null) {
+                        map.put(key, elements.size());
                         elements.add(property);
                     } else if (getter != null) {
+                        assert prevGetter != null || prevSetter != null;
                         elements.set(existing, existingProperty.setGetter(getter));
                     } else if (setter != null) {
+                        assert prevGetter != null || prevSetter != null;
                         elements.set(existing, existingProperty.setSetter(setter));
                     }
                     break;
@@ -2224,18 +3003,43 @@
         return new ObjectNode(objectToken, finish, elements);
     }
 
+    private void checkPropertyRedefinition(final PropertyNode property, final Expression value, final FunctionNode getter, final FunctionNode setter, final Expression prevValue, final FunctionNode prevGetter, final FunctionNode prevSetter) {
+        // ECMA 11.1.5 strict mode restrictions
+        if (isStrictMode && value != null && prevValue != null) {
+            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+        }
+
+        final boolean isPrevAccessor = prevGetter != null || prevSetter != null;
+        final boolean isAccessor     = getter != null     || setter != null;
+
+        // data property redefined as accessor property
+        if (prevValue != null && isAccessor) {
+            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+        }
+
+        // accessor property redefined as data
+        if (isPrevAccessor && value != null) {
+            throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+        }
+
+        if (isAccessor && isPrevAccessor) {
+            if (getter != null && prevGetter != null ||
+                    setter != null && prevSetter != null) {
+                throw error(AbstractParser.message("property.redefinition", property.getKeyName()), property.getToken());
+            }
+        }
+    }
+
     /**
-     * PropertyName :
+     * LiteralPropertyName :
      *      IdentifierName
      *      StringLiteral
      *      NumericLiteral
      *
-     * See 11.1.5
-     *
      * @return PropertyName node
      */
     @SuppressWarnings("fallthrough")
-    private PropertyKey propertyName() {
+    private PropertyKey literalPropertyName() {
         switch (type) {
         case IDENT:
             return getIdent().setIsPropertyName();
@@ -2257,6 +3061,34 @@
     }
 
     /**
+     * ComputedPropertyName :
+     *      AssignmentExpression
+     *
+     * @return PropertyName node
+     */
+    private Expression computedPropertyName() {
+        expect(LBRACKET);
+        Expression expression = assignmentExpression(false);
+        expect(RBRACKET);
+        return expression;
+    }
+
+    /**
+     * PropertyName :
+     *      LiteralPropertyName
+     *      ComputedPropertyName
+     *
+     * @return PropertyName node
+     */
+    private Expression propertyName() {
+        if (type == LBRACKET && isES6()) {
+            return computedPropertyName();
+        } else {
+            return (Expression)literalPropertyName();
+        }
+    }
+
+    /**
      * PropertyAssignment :
      *      PropertyName : AssignmentExpression
      *      get PropertyName ( ) { FunctionBody }
@@ -2280,51 +3112,95 @@
         final long propertyToken = token;
         final int  functionLine  = line;
 
-        PropertyKey propertyName;
-
+        final Expression propertyName;
+        final boolean isIdentifier;
+
+        boolean generator = false;
+        if (type == MUL && isES6()) {
+            generator = true;
+            next();
+        }
+
+        final boolean computed = type == LBRACKET;
         if (type == IDENT) {
             // Get IDENT.
             final String ident = (String)expectValue(IDENT);
 
-            if (type != COLON) {
+            if (type != COLON && (type != LPAREN || !isES6())) {
                 final long getSetToken = propertyToken;
 
                 switch (ident) {
                 case "get":
                     final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
-                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
+                    return new PropertyNode(propertyToken, finish, getter.key, null, getter.functionNode, null, false, getter.computed);
 
                 case "set":
                     final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
-                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
+                    return new PropertyNode(propertyToken, finish, setter.key, null, null, setter.functionNode, false, setter.computed);
                 default:
                     break;
                 }
             }
 
-            propertyName = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
+            isIdentifier = true;
+            IdentNode identNode = createIdentNode(propertyToken, finish, ident).setIsPropertyName();
+            if (type == COLON && ident.equals("__proto__")) {
+                identNode = identNode.setIsProtoPropertyName();
+            }
+            propertyName = identNode;
         } else {
+            isIdentifier = isNonStrictModeIdent();
             propertyName = propertyName();
         }
 
-        expect(COLON);
-
-        defaultNames.push(propertyName);
-        try {
-            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
-        } finally {
-            defaultNames.pop();
+        Expression propertyValue;
+
+        if (generator) {
+            expectDontAdvance(LPAREN);
         }
+
+        if (type == LPAREN && isES6()) {
+            propertyValue = propertyMethodFunction(propertyName, propertyToken, functionLine, generator, FunctionNode.ES6_IS_METHOD, computed).functionNode;
+        } else if (isIdentifier && (type == COMMARIGHT || type == RBRACE || type == ASSIGN) && isES6()) {
+            propertyValue = createIdentNode(propertyToken, finish, ((IdentNode) propertyName).getPropertyName());
+            if (type == ASSIGN && isES6()) {
+                // TODO if not destructuring, this is a SyntaxError
+                final long assignToken = token;
+                next();
+                final Expression rhs = assignmentExpression(false);
+                propertyValue = verifyAssignment(assignToken, propertyValue, rhs);
+            }
+        } else {
+            expect(COLON);
+
+            defaultNames.push(propertyName);
+            try {
+                propertyValue = assignmentExpression(false);
+            } finally {
+                defaultNames.pop();
+            }
+        }
+
+        return new PropertyNode(propertyToken, finish, propertyName, propertyValue, null, null, false, computed);
     }
 
     private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
-        final PropertyKey getIdent = propertyName();
-        final String getterName = getIdent.getPropertyName();
-        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
+        return propertyGetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
+    }
+
+    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine, final int flags) {
+        final boolean computed = type == LBRACKET;
+        final Expression propertyName = propertyName();
+        final String getterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
+        final IdentNode getNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("get " + getterName));
         expect(LPAREN);
         expect(RPAREN);
 
         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.<IdentNode>emptyList());
+        functionNode.setFlag(flags);
+        if (computed) {
+            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+        }
         lc.push(functionNode);
 
         Block functionBody;
@@ -2345,20 +3221,25 @@
                 functionLine,
                 functionBody);
 
-        return new PropertyFunction(getIdent, function);
+        return new PropertyFunction(propertyName, function, computed);
     }
 
     private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
-        final PropertyKey setIdent = propertyName();
-        final String setterName = setIdent.getPropertyName();
-        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
+        return propertySetterFunction(getSetToken, functionLine, FunctionNode.ES6_IS_METHOD);
+    }
+
+    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine, final int flags) {
+        final boolean computed = type == LBRACKET;
+        final Expression propertyName = propertyName();
+        final String setterName = propertyName instanceof PropertyKey ? ((PropertyKey) propertyName).getPropertyName() : getDefaultValidFunctionName(functionLine, false);
+        final IdentNode setNameNode = createIdentNode((propertyName).getToken(), finish, NameCodec.encode("set " + setterName));
         expect(LPAREN);
         // be sloppy and allow missing setter parameter even though
         // spec does not permit it!
         final IdentNode argIdent;
-        if (type == IDENT || isNonStrictModeIdent()) {
+        if (isBindingIdentifier()) {
             argIdent = getIdent();
-            verifyStrictIdent(argIdent, "setter argument");
+            verifyIdent(argIdent, "setter argument");
         } else {
             argIdent = null;
         }
@@ -2370,6 +3251,10 @@
 
 
         final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters);
+        functionNode.setFlag(flags);
+        if (computed) {
+            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+        }
         lc.push(functionNode);
 
         Block functionBody;
@@ -2389,33 +3274,81 @@
                 functionLine,
                 functionBody);
 
-        return new PropertyFunction(setIdent, function);
+        return new PropertyFunction(propertyName, function, computed);
+    }
+
+    private PropertyFunction propertyMethodFunction(Expression key, final long methodToken, final int methodLine, final boolean generator, final int flags, boolean computed) {
+        final String methodName = key instanceof PropertyKey ? ((PropertyKey) key).getPropertyName() : getDefaultValidFunctionName(methodLine, false);
+        final IdentNode methodNameNode = createIdentNode(((Node)key).getToken(), finish, methodName);
+
+        FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
+        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(methodNameNode, methodToken, functionKind, methodLine, null);
+        functionNode.setFlag(flags);
+        if (computed) {
+            functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+        }
+        lc.push(functionNode);
+
+        try {
+            final ParserContextBlockNode parameterBlock = newBlock();
+            final List<IdentNode> parameters;
+            try {
+                expect(LPAREN);
+                parameters = formalParameterList(generator);
+                functionNode.setParameters(parameters);
+                expect(RPAREN);
+            } finally {
+                restoreBlock(parameterBlock);
+            }
+
+            Block functionBody = functionBody(functionNode);
+
+            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
+
+            final FunctionNode  function = createFunctionNode(
+                            functionNode,
+                            methodToken,
+                            methodNameNode,
+                            parameters,
+                            functionKind,
+                            methodLine,
+                            functionBody);
+            return new PropertyFunction(key, function, computed);
+        } finally {
+            lc.pop(functionNode);
+        }
     }
 
     private static class PropertyFunction {
-        final PropertyKey ident;
+        final Expression key;
         final FunctionNode functionNode;
-
-        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
-            this.ident = ident;
+        final boolean computed;
+
+        PropertyFunction(final Expression key, final FunctionNode function, final boolean computed) {
+            this.key = key;
             this.functionNode = function;
+            this.computed = computed;
         }
     }
 
     /**
-     * Parse left hand side expression.
-     *
      * LeftHandSideExpression :
      *      NewExpression
      *      CallExpression
      *
      * CallExpression :
      *      MemberExpression Arguments
+     *      SuperCall
      *      CallExpression Arguments
      *      CallExpression [ Expression ]
      *      CallExpression . IdentifierName
-     *      CallExpression TemplateLiteral
+     *
+     * SuperCall :
+     *      super Arguments
      *
+     * See 11.2
+     *
+     * Parse left hand side expression.
      * @return Expression node.
      */
     private Expression leftHandSideExpression() {
@@ -2435,7 +3368,7 @@
             lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
         }
 
-loop:
+        loop:
         while (true) {
             // Capture token.
             callLine  = line;
@@ -2479,6 +3412,7 @@
                 // tagged template literal
                 final List<Expression> arguments = templateLiteralArgumentList();
 
+                // Create call node.
                 lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
 
                 break;
@@ -2506,6 +3440,20 @@
         // NEW is tested in caller.
         next();
 
+        if (type == PERIOD && isES6()) {
+            next();
+            if (type == IDENT && "target".equals(getValue())) {
+                if (lc.getCurrentFunction().isProgram()) {
+                    throw error(AbstractParser.message("new.target.in.function"), token);
+                }
+                next();
+                markNewTarget(lc);
+                return new IdentNode(newToken, finish, "new.target");
+            } else {
+                throw error(AbstractParser.message("expected.target"), token);
+            }
+        }
+
         // Get function base.
         final int  callLine    = line;
         final Expression constructor = memberExpression();
@@ -2541,21 +3489,33 @@
     }
 
     /**
-     * Parse member expression.
-     *
      * MemberExpression :
      *      PrimaryExpression
-     *      FunctionExpression
+     *        FunctionExpression
+     *        ClassExpression
+     *        GeneratorExpression
      *      MemberExpression [ Expression ]
      *      MemberExpression . IdentifierName
      *      MemberExpression TemplateLiteral
+     *      SuperProperty
+     *      MetaProperty
      *      new MemberExpression Arguments
      *
+     * SuperProperty :
+     *      super [ Expression ]
+     *      super . IdentifierName
+     *
+     * MetaProperty :
+     *      NewTarget
+     *
+     * Parse member expression.
      * @return Expression node.
      */
+    @SuppressWarnings("fallthrough")
     private Expression memberExpression() {
         // Prepare to build operation.
         Expression lhs;
+        boolean isSuper = false;
 
         switch (type) {
         case NEW:
@@ -2568,13 +3528,53 @@
             lhs = functionExpression(false, false);
             break;
 
+        case CLASS:
+            if (isES6()) {
+                lhs = classExpression(false);
+                break;
+            } else {
+                // fall through
+            }
+
+        case SUPER:
+            if (isES6()) {
+                final ParserContextFunctionNode currentFunction = getCurrentNonArrowFunction();
+                if (currentFunction.isMethod()) {
+                    long identToken = Token.recast(token, IDENT);
+                    next();
+                    lhs = createIdentNode(identToken, finish, SUPER.getName());
+
+                    switch (type) {
+                        case LBRACKET:
+                        case PERIOD:
+                            getCurrentNonArrowFunction().setFlag(FunctionNode.ES6_USES_SUPER);
+                            isSuper = true;
+                            break;
+                        case LPAREN:
+                            if (currentFunction.isSubclassConstructor()) {
+                                lhs = ((IdentNode)lhs).setIsDirectSuper();
+                                break;
+                            } else {
+                                // fall through to throw error
+                            }
+                        default:
+                            throw error(AbstractParser.message("invalid.super"), identToken);
+                    }
+                    break;
+                } else {
+                    // fall through
+                }
+            } else {
+                // fall through
+            }
+
         default:
             // Get primary expression.
             lhs = primaryExpression();
             break;
         }
 
-loop:
+        loop:
         while (true) {
             // Capture token.
             final long callToken = token;
@@ -2591,6 +3591,11 @@
                 // Create indexing node.
                 lhs = new IndexNode(callToken, finish, lhs, index);
 
+                if (isSuper) {
+                    isSuper = false;
+                    lhs = ((BaseNode) lhs).setIsSuper();
+                }
+
                 break;
             }
             case PERIOD: {
@@ -2605,6 +3610,11 @@
                 // Create property access node.
                 lhs = new AccessNode(callToken, finish, lhs, property.getName());
 
+                if (isSuper) {
+                    isSuper = false;
+                    lhs = ((BaseNode) lhs).setIsSuper();
+                }
+
                 break;
             }
             case TEMPLATE:
@@ -2632,7 +3642,9 @@
      *
      * ArgumentList :
      *      AssignmentExpression
+     *      ... AssignmentExpression
      *      ArgumentList , AssignmentExpression
+     *      ArgumentList , ... AssignmentExpression
      *
      * See 11.2
      *
@@ -2656,8 +3668,18 @@
                 first = false;
             }
 
+            long spreadToken = 0;
+            if (type == ELLIPSIS && isES6()) {
+                spreadToken = token;
+                next();
+            }
+
             // Get argument expression.
-            nodeList.add(assignmentExpression(false));
+            Expression expression = assignmentExpression(false);
+            if (spreadToken != 0) {
+                expression = new UnaryNode(Token.recast(spreadToken, TokenType.SPREAD_ARGUMENT), expression);
+            }
+            nodeList.add(expression);
         }
 
         expect(RPAREN);
@@ -2697,11 +3719,24 @@
         final long functionToken = token;
         final int  functionLine  = line;
         // FUNCTION is tested in caller.
+        assert type == FUNCTION;
         next();
 
+        boolean generator = false;
+        if (type == MUL && isES6()) {
+            generator = true;
+            next();
+        }
+
         IdentNode name = null;
 
-        if (type == IDENT || isNonStrictModeIdent()) {
+        if (isBindingIdentifier()) {
+            if (type == YIELD && ((!isStatement && generator) || (isStatement && inGeneratorFunction()))) {
+                // 12.1.1 Early SyntaxError if:
+                // GeneratorExpression with BindingIdentifier yield
+                // HoistableDeclaration with BindingIdentifier yield in generator function body
+                expect(IDENT);
+            }
             name = getIdent();
             verifyStrictIdent(name, "function name");
         } else if (isStatement) {
@@ -2723,25 +3758,36 @@
             isAnonymous = true;
         }
 
-        expect(LPAREN);
-        final List<IdentNode> parameters = formalParameterList();
-        expect(RPAREN);
-
-        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters);
+        FunctionNode.Kind functionKind = generator ? FunctionNode.Kind.GENERATOR : FunctionNode.Kind.NORMAL;
+        List<IdentNode> parameters = Collections.emptyList();
+        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, functionKind, functionLine, parameters);
         lc.push(functionNode);
+
         Block functionBody = null;
         // Hide the current default name across function boundaries. E.g. "x3 = function x1() { function() {}}"
         // If we didn't hide the current default name, then the innermost anonymous function would receive "x3".
         hideDefaultName();
-        try{
+        try {
+            final ParserContextBlockNode parameterBlock = newBlock();
+            try {
+                expect(LPAREN);
+                parameters = formalParameterList(generator);
+                functionNode.setParameters(parameters);
+                expect(RPAREN);
+            } finally {
+                restoreBlock(parameterBlock);
+            }
+
             functionBody = functionBody(functionNode);
+
+            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
         } finally {
             defaultNames.pop();
             lc.pop(functionNode);
         }
 
         if (isStatement) {
-            if (topLevel || useBlockScope()) {
+            if (topLevel || useBlockScope() || (!isStrictMode && env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ACCEPT)) {
                 functionNode.setFlag(FunctionNode.IS_DECLARED);
             } else if (isStrictMode) {
                 throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken);
@@ -2759,45 +3805,14 @@
             functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
         }
 
-        final int arity = parameters.size();
-
-        final boolean strict = functionNode.isStrict();
-        if (arity > 1) {
-            final HashSet<String> parametersSet = new HashSet<>(arity);
-
-            for (int i = arity - 1; i >= 0; i--) {
-                final IdentNode parameter = parameters.get(i);
-                String parameterName = parameter.getName();
-
-                if (isArguments(parameterName)) {
-                    functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
-                }
-
-                if (parametersSet.contains(parameterName)) {
-                    // redefinition of parameter name
-                    if (strict) {
-                        throw error(AbstractParser.message("strict.param.redefinition", parameterName), parameter.getToken());
-                    }
-                    // rename in non-strict mode
-                    parameterName = functionNode.uniqueName(parameterName);
-                    final long parameterToken = parameter.getToken();
-                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
-                }
-
-                parametersSet.add(parameterName);
-            }
-        } else if (arity == 1) {
-            if (isArguments(parameters.get(0))) {
-                functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS);
-            }
-        }
+        verifyParameterList(parameters, functionNode);
 
         final FunctionNode function = createFunctionNode(
                 functionNode,
                 functionToken,
                 name,
                 parameters,
-                FunctionNode.Kind.NORMAL,
+                functionKind,
                 functionLine,
                 functionBody);
 
@@ -2822,6 +3837,40 @@
         return function;
     }
 
+    private void verifyParameterList(final List<IdentNode> parameters, final ParserContextFunctionNode functionNode) {
+        final IdentNode duplicateParameter = functionNode.getDuplicateParameterBinding();
+        if (duplicateParameter != null) {
+            if (functionNode.isStrict() || functionNode.getKind() == FunctionNode.Kind.ARROW || !functionNode.isSimpleParameterList()) {
+                throw error(AbstractParser.message("strict.param.redefinition", duplicateParameter.getName()), duplicateParameter.getToken());
+            }
+
+            final int arity = parameters.size();
+            final HashSet<String> parametersSet = new HashSet<>(arity);
+
+            for (int i = arity - 1; i >= 0; i--) {
+                final IdentNode parameter = parameters.get(i);
+                String parameterName = parameter.getName();
+
+                if (parametersSet.contains(parameterName)) {
+                    // redefinition of parameter name, rename in non-strict mode
+                    parameterName = functionNode.uniqueName(parameterName);
+                    final long parameterToken = parameter.getToken();
+                    parameters.set(i, new IdentNode(parameterToken, Token.descPosition(parameterToken), functionNode.uniqueName(parameterName)));
+                }
+                parametersSet.add(parameterName);
+            }
+        }
+    }
+
+    private static Block maybeWrapBodyInParameterBlock(Block functionBody, ParserContextBlockNode parameterBlock) {
+        assert functionBody.isFunctionBody();
+        if (!parameterBlock.getStatements().isEmpty()) {
+            parameterBlock.appendStatement(new BlockStatement(functionBody));
+            return new Block(parameterBlock.getToken(), functionBody.getFinish(), (functionBody.getFlags() | Block.IS_PARAMETER_BLOCK) & ~Block.IS_BODY, parameterBlock.getStatements());
+        }
+        return functionBody;
+    }
+
     private String getDefaultValidFunctionName(final int functionLine, final boolean isStatement) {
         final String defaultFunctionName = getDefaultFunctionName();
         if (isValidIdentifier(defaultFunctionName)) {
@@ -2836,14 +3885,14 @@
     }
 
     private static boolean isValidIdentifier(final String name) {
-        if(name == null || name.isEmpty()) {
+        if (name == null || name.isEmpty()) {
             return false;
         }
-        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
+        if (!Character.isJavaIdentifierStart(name.charAt(0))) {
             return false;
         }
-        for(int i = 1; i < name.length(); ++i) {
-            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
+        for (int i = 1; i < name.length(); ++i) {
+            if (!Character.isJavaIdentifierPart(name.charAt(i))) {
                 return false;
             }
         }
@@ -2851,12 +3900,12 @@
     }
 
     private String getDefaultFunctionName() {
-        if(!defaultNames.isEmpty()) {
+        if (!defaultNames.isEmpty()) {
             final Object nameExpr = defaultNames.peek();
-            if(nameExpr instanceof PropertyKey) {
+            if (nameExpr instanceof PropertyKey) {
                 markDefaultNameUsed();
                 return ((PropertyKey)nameExpr).getPropertyName();
-            } else if(nameExpr instanceof AccessNode) {
+            } else if (nameExpr instanceof AccessNode) {
                 markDefaultNameUsed();
                 return ((AccessNode)nameExpr).getProperty();
             }
@@ -2885,8 +3934,8 @@
      * Parse function parameter list.
      * @return List of parameter nodes.
      */
-    private List<IdentNode> formalParameterList() {
-        return formalParameterList(RPAREN);
+    private List<IdentNode> formalParameterList(final boolean yield) {
+        return formalParameterList(RPAREN, yield);
     }
 
     /**
@@ -2902,7 +3951,7 @@
      * Parse function parameter list.
      * @return List of parameter nodes.
      */
-    private List<IdentNode> formalParameterList(final TokenType endType) {
+    private List<IdentNode> formalParameterList(final TokenType endType, final boolean yield) {
         // Prepare to gather parameters.
         final ArrayList<IdentNode> parameters = new ArrayList<>();
         // Track commas.
@@ -2916,12 +3965,84 @@
                 first = false;
             }
 
-            // Get and add parameter.
-            final IdentNode ident = getIdent();
-
-            // ECMA 13.1 strict mode restrictions
-            verifyStrictIdent(ident, "function parameter");
-
+            boolean restParameter = false;
+            if (type == ELLIPSIS && isES6()) {
+                next();
+                restParameter = true;
+            }
+
+            if (type == YIELD && yield) {
+                expect(IDENT);
+            }
+
+            final long paramToken = token;
+            final int paramLine = line;
+            final String contextString = "function parameter";
+            IdentNode ident;
+            if (isBindingIdentifier() || restParameter || !isES6()) {
+                ident = bindingIdentifier(contextString);
+
+                if (restParameter) {
+                    ident = ident.setIsRestParameter();
+                    // rest parameter must be last
+                    expectDontAdvance(endType);
+                    parameters.add(ident);
+                    break;
+                } else if (type == ASSIGN && isES6()) {
+                    next();
+                    ident = ident.setIsDefaultParameter();
+
+                    if (type == YIELD && yield) {
+                        // error: yield in default expression
+                        expect(IDENT);
+                    }
+
+                    // default parameter
+                    Expression initializer = assignmentExpression(false);
+
+                    ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                    if (currentFunction != null) {
+                        // desugar to: param = (param === undefined) ? initializer : param;
+                        // possible alternative: if (param === undefined) param = initializer;
+                        BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                        TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                        BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    }
+                }
+
+                ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                if (currentFunction != null) {
+                    currentFunction.addParameterBinding(ident);
+                    if (ident.isRestParameter() || ident.isDefaultParameter()) {
+                        currentFunction.setSimpleParameterList(false);
+                    }
+                }
+            } else {
+                final Expression pattern = bindingPattern();
+                // Introduce synthetic temporary parameter to capture the object to be destructured.
+                ident = createIdentNode(paramToken, pattern.getFinish(), String.format("arguments[%d]", parameters.size())).setIsDestructuredParameter();
+                verifyDestructuringParameterBindingPattern(pattern, paramToken, paramLine, contextString);
+
+                Expression value = ident;
+                if (type == ASSIGN) {
+                    next();
+                    ident = ident.setIsDefaultParameter();
+
+                    // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
+                    Expression initializer = assignmentExpression(false);
+                    // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
+                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                    value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                }
+
+                ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                if (currentFunction != null) {
+                    // destructuring assignment
+                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
+                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                }
+            }
             parameters.add(ident);
         }
 
@@ -2929,6 +4050,23 @@
         return parameters;
     }
 
+    private void verifyDestructuringParameterBindingPattern(final Expression pattern, final long paramToken, final int paramLine, final String contextString) {
+        verifyDestructuringBindingPattern(pattern, new Consumer<IdentNode>() {
+            public void accept(IdentNode identNode) {
+                verifyIdent(identNode, contextString);
+
+                ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                if (currentFunction != null) {
+                    // declare function-scope variables for destructuring bindings
+                    lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
+                    // detect duplicate bounds names in parameter list
+                    currentFunction.addParameterBinding(identNode);
+                    currentFunction.setSimpleParameterList(false);
+                }
+            }
+        });
+    }
+
     /**
      * FunctionBody :
      *      SourceElements?
@@ -2958,7 +4096,7 @@
             final int functionId = functionNode.getId();
             parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId();
             // Nashorn extension: expression closures
-            if (!env._no_syntax_extensions && type != LBRACE) {
+            if ((!env._no_syntax_extensions || functionNode.getKind() == FunctionNode.Kind.ARROW) && type != LBRACE) {
                 /*
                  * Example:
                  *
@@ -2967,7 +4105,7 @@
                  */
 
                 // just expression as function body
-                final Expression expr = assignmentExpression(true);
+                final Expression expr = assignmentExpression(false);
                 lastToken = previousToken;
                 functionNode.setLastToken(previousToken);
                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
@@ -2982,6 +4120,7 @@
                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
                     appendStatement(returnNode);
                 }
+                // bodyFinish = finish;
             } else {
                 expectDontAdvance(LBRACE);
                 if (parseBody || !skipFunctionBody(functionNode)) {
@@ -3054,7 +4193,7 @@
                 }
             }
         }
-        functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements());
+        functionBody = new Block(bodyToken, bodyFinish, body.getFlags() | Block.IS_BODY, body.getStatements());
         return functionBody;
     }
 
@@ -3095,8 +4234,7 @@
         // Doesn't really matter, but it's safe to treat it as if there were a semicolon before
         // the RBRACE.
         type = SEMICOLON;
-        k = -1;
-        next();
+        scanFirstToken();
 
         return true;
     }
@@ -3126,11 +4264,11 @@
     }
 
     private void printAST(final FunctionNode functionNode) {
-        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+        if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
             env.getErr().println(new ASTWriter(functionNode));
         }
 
-        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+        if (functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
             env.getErr().println(new PrintVisitor(functionNode, true, false));
         }
     }
@@ -3222,20 +4360,7 @@
                 throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
             }
 
-            if (!(lhs instanceof AccessNode ||
-                  lhs instanceof IndexNode ||
-                  lhs instanceof IdentNode)) {
-                return referenceError(lhs, null, env._early_lvalue_error);
-            }
-
-            if (lhs instanceof IdentNode) {
-                if (!checkIdentLValue((IdentNode)lhs)) {
-                    return referenceError(lhs, null, false);
-                }
-                verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
-            }
-
-            return incDecExpression(unaryToken, opType, lhs, false);
+            return verifyIncDecExpression(unaryToken, opType, lhs, false);
 
         default:
             break;
@@ -3247,29 +4372,16 @@
             switch (type) {
             case INCPREFIX:
             case DECPREFIX:
+                final long opToken = token;
                 final TokenType opType = type;
                 final Expression lhs = expression;
                 // ++, -- without operand..
                 if (lhs == null) {
                     throw error(AbstractParser.message("expected.lvalue", type.getNameOrType()));
                 }
-
-                if (!(lhs instanceof AccessNode ||
-                   lhs instanceof IndexNode ||
-                   lhs instanceof IdentNode)) {
-                    next();
-                    return referenceError(lhs, null, env._early_lvalue_error);
-                }
-                if (lhs instanceof IdentNode) {
-                    if (!checkIdentLValue((IdentNode)lhs)) {
-                        next();
-                        return referenceError(lhs, null, false);
-                    }
-                    verifyStrictIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
-                }
-                expression = incDecExpression(token, type, expression, true);
                 next();
-                break;
+
+                return verifyIncDecExpression(opToken, opType, lhs, true);
             default:
                 break;
             }
@@ -3282,6 +4394,25 @@
         return expression;
     }
 
+    private Expression verifyIncDecExpression(final long unaryToken, final TokenType opType, final Expression lhs, final boolean isPostfix) {
+        assert lhs != null;
+
+        if (!(lhs instanceof AccessNode ||
+              lhs instanceof IndexNode ||
+              lhs instanceof IdentNode)) {
+            return referenceError(lhs, null, env._early_lvalue_error);
+        }
+
+        if (lhs instanceof IdentNode) {
+            if (!checkIdentLValue((IdentNode)lhs)) {
+                return referenceError(lhs, null, false);
+            }
+            verifyIdent((IdentNode)lhs, "operand for " + opType.getName() + " operator");
+        }
+
+        return incDecExpression(unaryToken, opType, lhs, isPostfix);
+    }
+
     /**
      * {@code
      * MultiplicativeExpression :
@@ -3380,7 +4511,42 @@
         // at expression start point!
 
         // Include commas in expression parsing.
-        return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
+        return expression(false);
+    }
+
+    private Expression expression(final boolean noIn) {
+        Expression assignmentExpression = assignmentExpression(noIn);
+        while (type == COMMARIGHT) {
+            long commaToken = token;
+            next();
+
+            boolean rhsRestParameter = false;
+            if (type == ELLIPSIS && isES6()) {
+                // (a, b, ...rest) is not a valid expression, unless we're parsing the parameter list of an arrow function (we need to throw the right error).
+                // But since the rest parameter is always last, at least we know that the expression has to end here and be followed by RPAREN and ARROW, so peek ahead.
+                if (isRestParameterEndOfArrowFunctionParameterList()) {
+                    next();
+                    rhsRestParameter = true;
+                }
+            }
+
+            Expression rhs = assignmentExpression(noIn);
+
+            if (rhsRestParameter) {
+                rhs = ((IdentNode)rhs).setIsRestParameter();
+                // Our only valid move is to end Expression here and continue with ArrowFunction.
+                // We've already checked that this is the parameter list of an arrow function (see above).
+                // RPAREN is next, so we'll finish the binary expression and drop out of the loop.
+                assert type == RPAREN;
+            }
+
+            assignmentExpression = new BinaryNode(commaToken, assignmentExpression, rhs);
+        }
+        return assignmentExpression;
+    }
+
+    private Expression expression(final int minPrecedence, final boolean noIn) {
+        return expression(unaryExpression(), minPrecedence, noIn);
     }
 
     private JoinPredecessorExpression joinPredecessorExpression() {
@@ -3448,12 +4614,316 @@
         return lhs;
     }
 
+    /**
+     * AssignmentExpression.
+     *
+     * AssignmentExpression[In, Yield] :
+     *   ConditionalExpression[?In, ?Yield]
+     *   [+Yield] YieldExpression[?In]
+     *   ArrowFunction[?In, ?Yield]
+     *   LeftHandSideExpression[?Yield] = AssignmentExpression[?In, ?Yield]
+     *   LeftHandSideExpression[?Yield] AssignmentOperator AssignmentExpression[?In, ?Yield]
+     */
     protected Expression assignmentExpression(final boolean noIn) {
         // This method is protected so that subclass can get details
         // at assignment expression start point!
 
-        // Exclude commas in expression parsing.
-        return expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
+        if (type == YIELD && inGeneratorFunction() && isES6()) {
+            return yieldExpression(noIn);
+        }
+
+        final long startToken = token;
+        final int startLine = line;
+        final Expression exprLhs = conditionalExpression(noIn);
+
+        if (type == ARROW && isES6()) {
+            if (checkNoLineTerminator()) {
+                final Expression paramListExpr;
+                if (exprLhs instanceof ExpressionList) {
+                    paramListExpr = (((ExpressionList)exprLhs).getExpressions().isEmpty() ? null : ((ExpressionList)exprLhs).getExpressions().get(0));
+                } else {
+                    paramListExpr = exprLhs;
+                }
+                return arrowFunction(startToken, startLine, paramListExpr);
+            }
+        }
+        assert !(exprLhs instanceof ExpressionList);
+
+        if (isAssignmentOperator(type)) {
+            final boolean isAssign = type == ASSIGN;
+            if (isAssign) {
+                defaultNames.push(exprLhs);
+            }
+            try {
+                final long assignToken = token;
+                next();
+                final Expression exprRhs = assignmentExpression(noIn);
+                return verifyAssignment(assignToken, exprLhs, exprRhs);
+            } finally {
+                if (isAssign) {
+                    defaultNames.pop();
+                }
+            }
+        } else {
+            return exprLhs;
+        }
+    }
+
+    /**
+     * Is type one of {@code = *= /= %= += -= <<= >>= >>>= &= ^= |=}?
+     */
+    private static boolean isAssignmentOperator(TokenType type) {
+        switch (type) {
+        case ASSIGN:
+        case ASSIGN_ADD:
+        case ASSIGN_BIT_AND:
+        case ASSIGN_BIT_OR:
+        case ASSIGN_BIT_XOR:
+        case ASSIGN_DIV:
+        case ASSIGN_MOD:
+        case ASSIGN_MUL:
+        case ASSIGN_SAR:
+        case ASSIGN_SHL:
+        case ASSIGN_SHR:
+        case ASSIGN_SUB:
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * ConditionalExpression.
+     */
+    private Expression conditionalExpression(boolean noIn) {
+        return expression(TERNARY.getPrecedence(), noIn);
+    }
+
+    /**
+     * ArrowFunction.
+     *
+     * @param startToken start token of the ArrowParameters expression
+     * @param functionLine start line of the arrow function
+     * @param paramListExpr ArrowParameters expression or {@code null} for {@code ()} (empty list)
+     */
+    private Expression arrowFunction(final long startToken, final int functionLine, final Expression paramListExpr) {
+        // caller needs to check that there's no LineTerminator between parameter list and arrow
+        assert type != ARROW || checkNoLineTerminator();
+        expect(ARROW);
+
+        final long functionToken = Token.recast(startToken, ARROW);
+        final IdentNode name = new IdentNode(functionToken, Token.descPosition(functionToken), "=>:" + functionLine);
+        final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.ARROW, functionLine, null);
+        functionNode.setFlag(FunctionNode.IS_ANONYMOUS);
+
+        lc.push(functionNode);
+        try {
+            ParserContextBlockNode parameterBlock = newBlock();
+            final List<IdentNode> parameters;
+            try {
+                parameters = convertArrowFunctionParameterList(paramListExpr, functionLine);
+                functionNode.setParameters(parameters);
+
+                if (!functionNode.isSimpleParameterList()) {
+                    markEvalInArrowParameterList(parameterBlock);
+                }
+            } finally {
+                restoreBlock(parameterBlock);
+            }
+            Block functionBody = functionBody(functionNode);
+
+            functionBody = maybeWrapBodyInParameterBlock(functionBody, parameterBlock);
+
+            verifyParameterList(parameters, functionNode);
+
+            final FunctionNode function = createFunctionNode(
+                            functionNode,
+                            functionToken,
+                            name,
+                            parameters,
+                            FunctionNode.Kind.ARROW,
+                            functionLine,
+                            functionBody);
+            return function;
+        } finally {
+            lc.pop(functionNode);
+        }
+    }
+
+    private void markEvalInArrowParameterList(final ParserContextBlockNode parameterBlock) {
+        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+        final ParserContextFunctionNode current = iter.next();
+        final ParserContextFunctionNode parent = iter.next();
+
+        if (parent.getFlag(FunctionNode.HAS_EVAL) != 0) {
+            // we might have flagged has-eval in the parent function during parsing the parameter list,
+            // if the parameter list contains eval; must tag arrow function as has-eval.
+            for (final Statement st : parameterBlock.getStatements()) {
+                st.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                    @Override
+                    public boolean enterCallNode(final CallNode callNode) {
+                        if (callNode.getFunction() instanceof IdentNode && ((IdentNode) callNode.getFunction()).getName().equals("eval")) {
+                            current.setFlag(FunctionNode.HAS_EVAL);
+                        }
+                        return true;
+                    }
+                });
+            }
+            // TODO: function containing the arrow function should not be flagged has-eval
+        }
+    }
+
+    private List<IdentNode> convertArrowFunctionParameterList(final Expression paramListExpr, final int functionLine) {
+        final List<IdentNode> parameters;
+        if (paramListExpr == null) {
+            // empty parameter list, i.e. () =>
+            parameters = Collections.emptyList();
+        } else if (paramListExpr instanceof IdentNode || paramListExpr.isTokenType(ASSIGN) || isDestructuringLhs(paramListExpr)) {
+            parameters = Collections.singletonList(verifyArrowParameter(paramListExpr, 0, functionLine));
+        } else if (paramListExpr instanceof BinaryNode && Token.descType(paramListExpr.getToken()) == COMMARIGHT) {
+            parameters = new ArrayList<>();
+            Expression car = paramListExpr;
+            do {
+                final Expression cdr = ((BinaryNode) car).rhs();
+                parameters.add(0, verifyArrowParameter(cdr, parameters.size(), functionLine));
+                car = ((BinaryNode) car).lhs();
+            } while (car instanceof BinaryNode && Token.descType(car.getToken()) == COMMARIGHT);
+            parameters.add(0, verifyArrowParameter(car, parameters.size(), functionLine));
+        } else {
+            throw error(AbstractParser.message("expected.arrow.parameter"), paramListExpr.getToken());
+        }
+        return parameters;
+    }
+
+    private IdentNode verifyArrowParameter(Expression param, int index, int paramLine) {
+        final String contextString = "function parameter";
+        if (param instanceof IdentNode) {
+            IdentNode ident = (IdentNode)param;
+            verifyStrictIdent(ident, contextString);
+            ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+            if (currentFunction != null) {
+                currentFunction.addParameterBinding(ident);
+            }
+            return ident;
+        }
+
+        if (param.isTokenType(ASSIGN)) {
+            Expression lhs = ((BinaryNode) param).lhs();
+            long paramToken = lhs.getToken();
+            Expression initializer = ((BinaryNode) param).rhs();
+            if (lhs instanceof IdentNode) {
+                // default parameter
+                IdentNode ident = (IdentNode) lhs;
+
+                ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                if (currentFunction != null) {
+                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                    TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+
+                    currentFunction.addParameterBinding(ident);
+                    currentFunction.setSimpleParameterList(false);
+                }
+                return ident;
+            } else if (isDestructuringLhs(lhs)) {
+                // binding pattern with initializer
+                // Introduce synthetic temporary parameter to capture the object to be destructured.
+                IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter().setIsDefaultParameter();
+                verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
+
+                ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+                if (currentFunction != null) {
+                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                    TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
+                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                }
+                return ident;
+            }
+        } else if (isDestructuringLhs(param)) {
+            // binding pattern
+            long paramToken = param.getToken();
+
+            // Introduce synthetic temporary parameter to capture the object to be destructured.
+            IdentNode ident = createIdentNode(paramToken, param.getFinish(), String.format("arguments[%d]", index)).setIsDestructuredParameter();
+            verifyDestructuringParameterBindingPattern(param, paramToken, paramLine, contextString);
+
+            ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
+            if (currentFunction != null) {
+                BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
+                lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+            }
+            return ident;
+        }
+        throw error(AbstractParser.message("invalid.arrow.parameter"), param.getToken());
+    }
+
+    private boolean checkNoLineTerminator() {
+        assert type == ARROW;
+        if (last == RPAREN) {
+            return true;
+        } else if (last == IDENT) {
+            return true;
+        }
+        for (int i = k - 1; i >= 0; i--) {
+            TokenType t = T(i);
+            switch (t) {
+            case RPAREN:
+            case IDENT:
+                return true;
+            case EOL:
+                return false;
+            case COMMENT:
+                continue;
+            default:
+                if (t.getKind() == TokenKind.FUTURESTRICT) {
+                    return true;
+                }
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Peek ahead to see if what follows after the ellipsis is a rest parameter
+     * at the end of an arrow function parameter list.
+     */
+    private boolean isRestParameterEndOfArrowFunctionParameterList() {
+        assert type == ELLIPSIS;
+        // find IDENT, RPAREN, ARROW, in that order, skipping over EOL (where allowed) and COMMENT
+        int i = 1;
+        for (;;) {
+            TokenType t = T(k + i++);
+            if (t == IDENT) {
+                break;
+            } else if (t == EOL || t == COMMENT) {
+                continue;
+            } else {
+                return false;
+            }
+        }
+        for (;;) {
+            TokenType t = T(k + i++);
+            if (t == RPAREN) {
+                break;
+            } else if (t == EOL || t == COMMENT) {
+                continue;
+            } else {
+                return false;
+            }
+        }
+        for (;;) {
+            TokenType t = T(k + i++);
+            if (t == ARROW) {
+                break;
+            } else if (t == COMMENT) {
+                continue;
+            } else {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
@@ -3551,6 +5021,380 @@
         cookedStrings.add(LiteralNode.newInstance(stringToken, finish, cookedString));
     }
 
+
+    /**
+     * Parse a module.
+     *
+     * Module :
+     *      ModuleBody?
+     *
+     * ModuleBody :
+     *      ModuleItemList
+     */
+    private FunctionNode module(final String moduleName) {
+        boolean oldStrictMode = isStrictMode;
+        try {
+            isStrictMode = true; // Module code is always strict mode code. (ES6 10.2.1)
+
+            // Make a pseudo-token for the script holding its start and length.
+            int functionStart = Math.min(Token.descPosition(Token.withDelimiter(token)), finish);
+            final long functionToken = Token.toDesc(FUNCTION, functionStart, source.getLength() - functionStart);
+            final int  functionLine  = line;
+
+            final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), moduleName);
+            final ParserContextFunctionNode script = createParserContextFunctionNode(
+                            ident,
+                            functionToken,
+                            FunctionNode.Kind.MODULE,
+                            functionLine,
+                            Collections.<IdentNode>emptyList());
+            lc.push(script);
+
+            final ParserContextModuleNode module = new ParserContextModuleNode(moduleName);
+            lc.push(module);
+
+            final ParserContextBlockNode body = newBlock();
+
+            functionDeclarations = new ArrayList<>();
+            moduleBody();
+            addFunctionDeclarations(script);
+            functionDeclarations = null;
+
+            restoreBlock(body);
+            body.setFlag(Block.NEEDS_SCOPE);
+            final Block programBody = new Block(functionToken, finish, body.getFlags() | Block.IS_SYNTHETIC | Block.IS_BODY, body.getStatements());
+            lc.pop(module);
+            lc.pop(script);
+            script.setLastToken(token);
+
+            expect(EOF);
+
+            script.setModule(module.createModule());
+            return createFunctionNode(script, functionToken, ident, Collections.<IdentNode>emptyList(), FunctionNode.Kind.MODULE, functionLine, programBody);
+        } finally {
+            isStrictMode = oldStrictMode;
+        }
+    }
+
+    /**
+     * Parse module body.
+     *
+     * ModuleBody :
+     *      ModuleItemList
+     *
+     * ModuleItemList :
+     *      ModuleItem
+     *      ModuleItemList ModuleItem
+     *
+     * ModuleItem :
+     *      ImportDeclaration
+     *      ExportDeclaration
+     *      StatementListItem
+     */
+    private void moduleBody() {
+        loop:
+        while (type != EOF) {
+            switch (type) {
+            case EOF:
+                break loop;
+            case IMPORT:
+                importDeclaration();
+                break;
+            case EXPORT:
+                exportDeclaration();
+                break;
+            default:
+                // StatementListItem
+                statement(true, false, false, false);
+                break;
+            }
+        }
+    }
+
+
+    /**
+     * Parse import declaration.
+     *
+     * ImportDeclaration :
+     *     import ImportClause FromClause ;
+     *     import ModuleSpecifier ;
+     * ImportClause :
+     *     ImportedDefaultBinding
+     *     NameSpaceImport
+     *     NamedImports
+     *     ImportedDefaultBinding , NameSpaceImport
+     *     ImportedDefaultBinding , NamedImports
+     * ImportedDefaultBinding :
+     *     ImportedBinding
+     * ModuleSpecifier :
+     *     StringLiteral
+     * ImportedBinding :
+     *     BindingIdentifier
+     */
+    private void importDeclaration() {
+        expect(IMPORT);
+        final ParserContextModuleNode module = lc.getCurrentModule();
+        if (type == STRING || type == ESCSTRING) {
+            // import ModuleSpecifier ;
+            final String moduleSpecifier = (String) getValue();
+            next();
+            module.addModuleRequest(moduleSpecifier);
+        } else {
+            // import ImportClause FromClause ;
+            List<Module.ImportEntry> importEntries;
+            if (type == MUL) {
+                importEntries = Collections.singletonList(nameSpaceImport());
+            } else if (type == LBRACE) {
+                importEntries = namedImports();
+            } else if (isBindingIdentifier()) {
+                // ImportedDefaultBinding
+                final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
+                Module.ImportEntry defaultImport = Module.ImportEntry.importDefault(importedDefaultBinding.getName());
+
+                if (type == COMMARIGHT) {
+                    next();
+                    importEntries = new ArrayList<>();
+                    if (type == MUL) {
+                        importEntries.add(nameSpaceImport());
+                    } else if (type == LBRACE) {
+                        importEntries.addAll(namedImports());
+                    } else {
+                        throw error(AbstractParser.message("expected.named.import"));
+                    }
+                } else {
+                    importEntries = Collections.singletonList(defaultImport);
+                }
+            } else {
+                throw error(AbstractParser.message("expected.import"));
+            }
+
+            final String moduleSpecifier = fromClause();
+            module.addModuleRequest(moduleSpecifier);
+            for (int i = 0; i < importEntries.size(); i++) {
+                module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier));
+            }
+        }
+        expect(SEMICOLON);
+    }
+
+    /**
+     * NameSpaceImport :
+     *     * as ImportedBinding
+     *
+     * @return imported binding identifier
+     */
+    private Module.ImportEntry nameSpaceImport() {
+        assert type == MUL;
+        next();
+        final long asToken = token;
+        final String as = (String) expectValue(IDENT);
+        if (!"as".equals(as)) {
+            throw error(AbstractParser.message("expected.as"), asToken);
+        }
+        final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
+        return Module.ImportEntry.importStarAsNameSpaceFrom(localNameSpace.getName());
+    }
+
+    /**
+     * NamedImports :
+     *     { }
+     *     { ImportsList }
+     *     { ImportsList , }
+     * ImportsList :
+     *     ImportSpecifier
+     *     ImportsList , ImportSpecifier
+     * ImportSpecifier :
+     *     ImportedBinding
+     *     IdentifierName as ImportedBinding
+     * ImportedBinding :
+     *     BindingIdentifier
+     */
+    private List<Module.ImportEntry> namedImports() {
+        assert type == LBRACE;
+        next();
+        List<Module.ImportEntry> importEntries = new ArrayList<>();
+        while (type != RBRACE) {
+            final boolean bindingIdentifier = isBindingIdentifier();
+            final long nameToken = token;
+            final IdentNode importName = getIdentifierName();
+            if (type == IDENT && "as".equals(getValue())) {
+                next();
+                final IdentNode localName = bindingIdentifier("ImportedBinding");
+                importEntries.add(Module.ImportEntry.importSpecifier(importName.getName(), localName.getName()));
+            } else if (!bindingIdentifier) {
+                throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
+            } else {
+                importEntries.add(Module.ImportEntry.importSpecifier(importName.getName()));
+            }
+            if (type == COMMARIGHT) {
+                next();
+            } else {
+                break;
+            }
+        }
+        expect(RBRACE);
+        return importEntries;
+    }
+
+    /**
+     * FromClause :
+     *     from ModuleSpecifier
+     */
+    private String fromClause() {
+        final long fromToken = token;
+        final String name = (String) expectValue(IDENT);
+        if (!"from".equals(name)) {
+            throw error(AbstractParser.message("expected.from"), fromToken);
+        }
+        if (type == STRING || type == ESCSTRING) {
+            final String moduleSpecifier = (String) getValue();
+            next();
+            return moduleSpecifier;
+        } else {
+            throw error(expectMessage(STRING));
+        }
+    }
+
+    /**
+     * Parse export declaration.
+     *
+     * ExportDeclaration :
+     *     export * FromClause ;
+     *     export ExportClause FromClause ;
+     *     export ExportClause ;
+     *     export VariableStatement
+     *     export Declaration
+     *     export default HoistableDeclaration[Default]
+     *     export default ClassDeclaration[Default]
+     *     export default [lookahead !in {function, class}] AssignmentExpression[In] ;
+     */
+    private void exportDeclaration() {
+        expect(EXPORT);
+        final ParserContextModuleNode module = lc.getCurrentModule();
+        switch (type) {
+            case MUL: {
+                next();
+                final String moduleRequest = fromClause();
+                expect(SEMICOLON);
+                module.addModuleRequest(moduleRequest);
+                module.addStarExportEntry(Module.ExportEntry.exportStarFrom(moduleRequest));
+                break;
+            }
+            case LBRACE: {
+                final List<Module.ExportEntry> exportEntries = exportClause();
+                if (type == IDENT && "from".equals(getValue())) {
+                    final String moduleRequest = fromClause();
+                    module.addModuleRequest(moduleRequest);
+                    for (Module.ExportEntry exportEntry : exportEntries) {
+                        module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest));
+                    }
+                } else {
+                    for (Module.ExportEntry exportEntry : exportEntries) {
+                        module.addLocalExportEntry(exportEntry);
+                    }
+                }
+                expect(SEMICOLON);
+                break;
+            }
+            case DEFAULT:
+                next();
+                final Expression assignmentExpression;
+                IdentNode ident;
+                final int lineNumber = line;
+                final long rhsToken = token;
+                final boolean declaration;
+                switch (type) {
+                    case FUNCTION:
+                        assignmentExpression = functionExpression(false, true);
+                        ident = ((FunctionNode) assignmentExpression).getIdent();
+                        declaration = true;
+                        break;
+                    case CLASS:
+                        assignmentExpression = classDeclaration(true);
+                        ident = ((ClassNode) assignmentExpression).getIdent();
+                        declaration = true;
+                        break;
+                    default:
+                        assignmentExpression = assignmentExpression(false);
+                        ident = null;
+                        declaration = false;
+                        break;
+                }
+                if (ident != null) {
+                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(ident.getName()));
+                } else {
+                    ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
+                    lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
+                    if (!declaration) {
+                        expect(SEMICOLON);
+                    }
+                    module.addLocalExportEntry(Module.ExportEntry.exportDefault());
+                }
+                break;
+            case VAR:
+            case LET:
+            case CONST:
+                final List<Statement> statements = lc.getCurrentBlock().getStatements();
+                final int previousEnd = statements.size();
+                variableStatement(type);
+                for (final Statement statement : statements.subList(previousEnd, statements.size())) {
+                    if (statement instanceof VarNode) {
+                        module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName().getName()));
+                    }
+                }
+                break;
+            case CLASS: {
+                final ClassNode classDeclaration = classDeclaration(false);
+                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent().getName()));
+                break;
+            }
+            case FUNCTION: {
+                final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
+                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent().getName()));
+                break;
+            }
+            default:
+                throw error(AbstractParser.message("invalid.export"), token);
+        }
+    }
+
+    /**
+     * ExportClause :
+     *     { }
+     *     { ExportsList }
+     *     { ExportsList , }
+     * ExportsList :
+     *     ExportSpecifier
+     *     ExportsList , ExportSpecifier
+     * ExportSpecifier :
+     *     IdentifierName
+     *     IdentifierName as IdentifierName
+     *
+     * @return a list of ExportSpecifiers
+     */
+    private List<Module.ExportEntry> exportClause() {
+        assert type == LBRACE;
+        next();
+        List<Module.ExportEntry> exports = new ArrayList<>();
+        while (type != RBRACE) {
+            final IdentNode localName = getIdentifierName();
+            if (type == IDENT && "as".equals(getValue())) {
+                next();
+                final IdentNode exportName = getIdentifierName();
+                exports.add(Module.ExportEntry.exportSpecifier(exportName.getName(), localName.getName()));
+            } else {
+                exports.add(Module.ExportEntry.exportSpecifier(localName.getName()));
+            }
+            if (type == COMMARIGHT) {
+                next();
+            } else {
+                break;
+            }
+        }
+        expect(RBRACE);
+        return exports;
+    }
+
     @Override
     public String toString() {
         return "'JavaScript Parsing'";
@@ -3564,6 +5408,12 @@
             if (!flaggedCurrentFn) {
                 fn.setFlag(FunctionNode.HAS_EVAL);
                 flaggedCurrentFn = true;
+                if (fn.getKind() == FunctionNode.Kind.ARROW) {
+                    // possible use of this in an eval that's nested in an arrow function, e.g.:
+                    // function fun(){ return (() => eval("this"))(); };
+                    markThis(lc);
+                    markNewTarget(lc);
+                }
             } else {
                 fn.setFlag(FunctionNode.HAS_NESTED_EVAL);
             }
@@ -3583,4 +5433,55 @@
     private void appendStatement(final Statement statement) {
         lc.appendStatementToCurrentNode(statement);
     }
+
+    private static void markSuperCall(final ParserContext lc) {
+        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+        while (iter.hasNext()) {
+            final ParserContextFunctionNode fn = iter.next();
+            if (fn.getKind() != FunctionNode.Kind.ARROW) {
+                assert fn.isSubclassConstructor();
+                fn.setFlag(FunctionNode.ES6_HAS_DIRECT_SUPER);
+                break;
+            }
+        }
+    }
+
+    private ParserContextFunctionNode getCurrentNonArrowFunction() {
+        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+        while (iter.hasNext()) {
+            final ParserContextFunctionNode fn = iter.next();
+            if (fn.getKind() != FunctionNode.Kind.ARROW) {
+                return fn;
+            }
+        }
+        return null;
+    }
+
+    private static void markThis(final ParserContext lc) {
+        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+        while (iter.hasNext()) {
+            final ParserContextFunctionNode fn = iter.next();
+            fn.setFlag(FunctionNode.USES_THIS);
+            if (fn.getKind() != FunctionNode.Kind.ARROW) {
+                break;
+            }
+        }
+    }
+
+    private static void markNewTarget(final ParserContext lc) {
+        final Iterator<ParserContextFunctionNode> iter = lc.getFunctions();
+        while (iter.hasNext()) {
+            final ParserContextFunctionNode fn = iter.next();
+            if (fn.getKind() != FunctionNode.Kind.ARROW) {
+                if (!fn.isProgram()) {
+                    fn.setFlag(FunctionNode.ES6_USES_NEW_TARGET);
+                }
+                break;
+            }
+        }
+    }
+
+    private boolean inGeneratorFunction() {
+        return lc.getCurrentFunction().getKind() == FunctionNode.Kind.GENERATOR;
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java	Wed Jul 05 21:39:33 2017 +0200
@@ -278,7 +278,12 @@
         return new NodeIterator<>(ParserContextFunctionNode.class);
     }
 
-    private class NodeIterator <T extends ParserContextNode> implements Iterator<T> {
+    public ParserContextModuleNode getCurrentModule() {
+        final Iterator<ParserContextModuleNode> iter = new NodeIterator<>(ParserContextModuleNode.class, getCurrentFunction());
+        return iter.hasNext() ? iter.next() : null;
+    }
+
+    private class NodeIterator<T extends ParserContextNode> implements Iterator<T> {
         private int index;
         private T next;
         private final Class<T> clazz;
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -24,10 +24,12 @@
  */
 package jdk.nashorn.internal.parser;
 
+import java.util.HashSet;
 import java.util.List;
 import jdk.nashorn.internal.codegen.Namespace;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
 
 /**
  * ParserContextNode that represents a function that is currently being parsed
@@ -46,11 +48,11 @@
     /** Line number for function declaration */
     private final int line;
 
-    /** Function node kind, see {@link FunctionNode#Kind} */
+    /** Function node kind, see {@link FunctionNode.Kind} */
     private final FunctionNode.Kind kind;
 
     /** List of parameter identifiers for function */
-    private final List<IdentNode> parameters;
+    private List<IdentNode> parameters;
 
     /** Token for function start */
     private final long token;
@@ -61,6 +63,14 @@
     /** Opaque node for parser end state, see {@link Parser} */
     private Object endParserState;
 
+    private HashSet<String> parameterBoundNames;
+    private IdentNode duplicateParameterBinding;
+    private boolean simpleParameterList = true;
+
+    private Module module;
+
+    private int debugFlags;
+
     /**
      * @param token The token for the function
      * @param ident External function name
@@ -155,6 +165,10 @@
         return parameters;
     }
 
+    void setParameters(List<IdentNode> parameters) {
+        this.parameters = parameters;
+    }
+
     /**
      * Set last token
      * @param token New last token
@@ -194,4 +208,70 @@
     public int getId() {
         return isProgram() ? -1 : Token.descPosition(token);
     }
+
+    /**
+     * Returns the debug flags for this function.
+     *
+     * @return the debug flags
+     */
+    int getDebugFlags() {
+        return debugFlags;
+    }
+
+    /**
+     * Sets a debug flag for this function.
+     *
+     * @param debugFlag the debug flag
+     */
+    void setDebugFlag(final int debugFlag) {
+        debugFlags |= debugFlag;
+    }
+
+    public boolean isMethod() {
+        return getFlag(FunctionNode.ES6_IS_METHOD) != 0;
+    }
+
+    public boolean isClassConstructor() {
+        return getFlag(FunctionNode.ES6_IS_CLASS_CONSTRUCTOR) != 0;
+    }
+
+    public boolean isSubclassConstructor() {
+        return getFlag(FunctionNode.ES6_IS_SUBCLASS_CONSTRUCTOR) != 0;
+    }
+
+    boolean addParameterBinding(final IdentNode bindingIdentifier) {
+        if (Parser.isArguments(bindingIdentifier)) {
+            setFlag(FunctionNode.DEFINES_ARGUMENTS);
+        }
+
+        if (parameterBoundNames == null) {
+            parameterBoundNames = new HashSet<>();
+        }
+        if (parameterBoundNames.add(bindingIdentifier.getName())) {
+            return true;
+        } else {
+            duplicateParameterBinding = bindingIdentifier;
+            return false;
+        }
+    }
+
+    public IdentNode getDuplicateParameterBinding() {
+        return duplicateParameterBinding;
+    }
+
+    public boolean isSimpleParameterList() {
+        return simpleParameterList;
+    }
+
+    public void setSimpleParameterList(final boolean simpleParameterList) {
+        this.simpleParameterList = simpleParameterList;
+    }
+
+    public Module getModule() {
+        return module;
+    }
+
+    public void setModule(final Module module) {
+        this.module = module;
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,90 @@
+/*
+ * 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.nashorn.internal.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.nashorn.internal.ir.Module;
+import jdk.nashorn.internal.ir.Module.ExportEntry;
+import jdk.nashorn.internal.ir.Module.ImportEntry;
+
+/**
+ * ParserContextNode that represents a module.
+ */
+class ParserContextModuleNode extends ParserContextBaseNode {
+
+    /** Module name. */
+    private final String name;
+
+    private List<String> requestedModules = new ArrayList<>();
+    private List<ImportEntry> importEntries = new ArrayList<>();
+    private List<ExportEntry> localExportEntries = new ArrayList<>();
+    private List<ExportEntry> indirectExportEntries = new ArrayList<>();
+    private List<ExportEntry> starExportEntries = new ArrayList<>();
+
+    /**
+     * Constructor.
+     *
+     * @param name name of the module
+     */
+    ParserContextModuleNode(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Returns the name of the module.
+     *
+     * @return name of the module
+     */
+    public String getModuleName() {
+        return name;
+    }
+
+    public void addModuleRequest(final String moduleRequest) {
+        requestedModules.add(moduleRequest);
+    }
+
+    public void addImportEntry(final ImportEntry importEntry) {
+        importEntries.add(importEntry);
+    }
+
+    public void addLocalExportEntry(final ExportEntry exportEntry) {
+        localExportEntries.add(exportEntry);
+    }
+
+    public void addIndirectExportEntry(final ExportEntry exportEntry) {
+        indirectExportEntries.add(exportEntry);
+    }
+
+    public void addStarExportEntry(final ExportEntry exportEntry) {
+        starExportEntries.add(exportEntry);
+    }
+
+    public Module createModule() {
+        return new Module(requestedModules, importEntries, localExportEntries, indirectExportEntries, starExportEntries);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/TokenType.java	Wed Jul 05 21:39:33 2017 +0200
@@ -82,7 +82,7 @@
     ASSIGN         (BINARY,  "=",     2, false),
     EQ             (BINARY,  "==",    9, true),
     EQ_STRICT      (BINARY,  "===",   9, true),
-    BIND           (BINARY,  "=>",    9, true),
+    ARROW          (BINARY,  "=>",    2, true),
     GT             (BINARY,  ">",    10, true),
     GE             (BINARY,  ">=",   10, true),
     SAR            (BINARY,  ">>",   11, true),
@@ -100,6 +100,7 @@
     OR             (BINARY,  "||",    4, true),
     RBRACE         (BRACKET, "}"),
     BIT_NOT        (UNARY,   "~",     14, false),
+    ELLIPSIS       (UNARY,   "..."),
 
     // ECMA 7.6.1.1 Keywords, 7.6.1.2 Future Reserved Words.
     // All other Java keywords are commented out.
@@ -190,7 +191,10 @@
 
     COMMALEFT      (IR,       null),
     DECPOSTFIX     (IR,       null),
-    INCPOSTFIX     (IR,       null);
+    INCPOSTFIX     (IR,       null),
+    SPREAD_ARGUMENT(IR,       null),
+    SPREAD_ARRAY   (IR,       null),
+    YIELD_STAR     (IR,       null);
 
     /** Next token kind in token lookup table. */
     private TokenType next;
@@ -251,7 +255,6 @@
         return kind == BINARY && (!noIn || this != IN) && precedence != 0;
     }
 
-
     public int getLength() {
         assert name != null : "Token name not set";
         return name.length();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java	Wed Jul 05 21:39:33 2017 +0200
@@ -1403,11 +1403,11 @@
                 return null;
             }
 
-            if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+            if (env._print_ast || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_AST)) {
                 getErr().println(new ASTWriter(functionNode));
             }
 
-            if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+            if (env._print_parse || functionNode.getDebugFlag(FunctionNode.DEBUG_PRINT_PARSE)) {
                 getErr().println(new PrintVisitor(functionNode, true, false));
             }
         }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/doubleconv/DtoaBuffer.java	Wed Jul 05 21:39:33 2017 +0200
@@ -176,6 +176,8 @@
                     buffer.append('0');
                 }
                 buffer.append(chars, 0, length);
+            } else {
+                decimalPoint = 1;
             }
         } else if (decimalPoint >= length) {
             // large integer, add trailing zeroes
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties	Wed Jul 05 21:39:33 2017 +0200
@@ -63,6 +63,27 @@
 parser.error.missing.const.assignment=Missing assignment to constant "{0}"
 parser.error.unterminated.template.expression=Expected } after expression in template literal
 
+# ES6 mode error messages
+parser.error.multiple.constructors=Class contains more than one constructor
+parser.error.generator.constructor=Class constructor must not be a generator
+parser.error.accessor.constructor=Class constructor must not be an accessor
+parser.error.static.prototype.method=Static class method must not be named 'prototype'
+parser.error.missing.destructuring.assignment=Missing assignment in destructuring declaration
+parser.error.let.binding.for='let' is not a valid binding name in a for loop
+parser.error.invalid.export=invalid export declaration
+parser.error.expected.binding=expected BindingIdentifier or BindingPattern
+parser.error.multiple.proto.key=property name __proto__ appears more than once in object literal
+parser.error.new.target.in.function=new.target expression is only allowed in functions
+parser.error.expected.target=expected 'target'
+parser.error.invalid.super=invalid use of keyword super
+parser.error.expected.arrow.parameter=expected arrow function parameter list
+parser.error.invalid.arrow.parameter=invalid arrow function parameter
+parser.error.expected.named.import=expected NameSpaceImport or NamedImports
+parser.error.expected.import=expected ImportClause or ModuleSpecifier
+parser.error.expected.as=expected 'as'
+parser.error.expected.binding.identifier=expected BindingIdentifier
+parser.error.expected.from=expected 'from'
+
 # strict mode error messages
 parser.error.strict.no.with="with" statement cannot be used in strict mode
 parser.error.strict.name="{0}" cannot be used as {1} in strict mode
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java	Wed Jul 05 21:39:33 2017 +0200
@@ -438,6 +438,9 @@
                 final File file = new File(fileName);
                 final ScriptFunction script = context.compileScript(sourceFor(fileName, file), global);
                 if (script == null || errors.getNumberOfErrors() != 0) {
+                    if (context.getEnv()._parse_only && !errors.hasErrors()) {
+                        continue; // No error, continue to consume all files in list
+                    }
                     return COMPILATION_ERROR;
                 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8155025.js	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8155025: 0.001.toFixed(2) should return "0.00" not "0"
+ *
+ * @test
+ * @run
+ */
+
+for (var i = 0, zeros=""; i <= 9; i++, zeros += "0") {
+    var n = Number("0." + zeros + "1");
+    for (var j = 1; j <= i + 3; j++) {
+        print(n + ".toFixed(" + j + ")=" + n.toFixed(j));
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8155025.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,75 @@
+0.1.toFixed(1)=0.1
+0.1.toFixed(2)=0.10
+0.1.toFixed(3)=0.100
+0.01.toFixed(1)=0.0
+0.01.toFixed(2)=0.01
+0.01.toFixed(3)=0.010
+0.01.toFixed(4)=0.0100
+0.001.toFixed(1)=0.0
+0.001.toFixed(2)=0.00
+0.001.toFixed(3)=0.001
+0.001.toFixed(4)=0.0010
+0.001.toFixed(5)=0.00100
+0.0001.toFixed(1)=0.0
+0.0001.toFixed(2)=0.00
+0.0001.toFixed(3)=0.000
+0.0001.toFixed(4)=0.0001
+0.0001.toFixed(5)=0.00010
+0.0001.toFixed(6)=0.000100
+0.00001.toFixed(1)=0.0
+0.00001.toFixed(2)=0.00
+0.00001.toFixed(3)=0.000
+0.00001.toFixed(4)=0.0000
+0.00001.toFixed(5)=0.00001
+0.00001.toFixed(6)=0.000010
+0.00001.toFixed(7)=0.0000100
+0.000001.toFixed(1)=0.0
+0.000001.toFixed(2)=0.00
+0.000001.toFixed(3)=0.000
+0.000001.toFixed(4)=0.0000
+0.000001.toFixed(5)=0.00000
+0.000001.toFixed(6)=0.000001
+0.000001.toFixed(7)=0.0000010
+0.000001.toFixed(8)=0.00000100
+1e-7.toFixed(1)=0.0
+1e-7.toFixed(2)=0.00
+1e-7.toFixed(3)=0.000
+1e-7.toFixed(4)=0.0000
+1e-7.toFixed(5)=0.00000
+1e-7.toFixed(6)=0.000000
+1e-7.toFixed(7)=0.0000001
+1e-7.toFixed(8)=0.00000010
+1e-7.toFixed(9)=0.000000100
+1e-8.toFixed(1)=0.0
+1e-8.toFixed(2)=0.00
+1e-8.toFixed(3)=0.000
+1e-8.toFixed(4)=0.0000
+1e-8.toFixed(5)=0.00000
+1e-8.toFixed(6)=0.000000
+1e-8.toFixed(7)=0.0000000
+1e-8.toFixed(8)=0.00000001
+1e-8.toFixed(9)=0.000000010
+1e-8.toFixed(10)=0.0000000100
+1e-9.toFixed(1)=0.0
+1e-9.toFixed(2)=0.00
+1e-9.toFixed(3)=0.000
+1e-9.toFixed(4)=0.0000
+1e-9.toFixed(5)=0.00000
+1e-9.toFixed(6)=0.000000
+1e-9.toFixed(7)=0.0000000
+1e-9.toFixed(8)=0.00000000
+1e-9.toFixed(9)=0.000000001
+1e-9.toFixed(10)=0.0000000010
+1e-9.toFixed(11)=0.00000000100
+1e-10.toFixed(1)=0.0
+1e-10.toFixed(2)=0.00
+1e-10.toFixed(3)=0.000
+1e-10.toFixed(4)=0.0000
+1e-10.toFixed(5)=0.00000
+1e-10.toFixed(6)=0.000000
+1e-10.toFixed(7)=0.0000000
+1e-10.toFixed(8)=0.00000000
+1e-10.toFixed(9)=0.000000000
+1e-10.toFixed(10)=0.0000000001
+1e-10.toFixed(11)=0.00000000010
+1e-10.toFixed(12)=0.000000000100
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/es6/parser-es6.js	Wed Jul 05 21:39:33 2017 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8134503: support ES6 parsing in Nashorn
+ *
+ * @test
+ * @option --language=es6
+ * @option --parse-only
+ */
+
+
+[].map(v => v + 1);
+
+class A extends B.C {
+    constructor(a, b) {
+        super(a, b);
+    }
+    someMethod(c) {
+        super.someMethod();
+    }
+    get g() {
+        return this.g;
+    }
+    set s(t) {
+        this.t = t;
+    }
+    static m() {
+        return k;
+    }
+}
+
+var obj = {
+    __proto__: theProtoObj,
+    handler,
+    r() {
+        return super.m();
+    },
+    [ '__' + (() => 'x')() ]: 1,
+    *q (x, y) {
+       yield 1;
+    }
+};
+
+var [a, , b] = [1, 2, 3];
+
+var { x: a, y: { z: b }, w: c } = abc();
+
+var {a, b, c} = abc();
+
+var o = { x, y };
+
+function g({name: x}) {
+  return x;
+}
+
+foo(a, ...b);
+
+var c = [ ...s ];
+
+var [a] = [];
+
+var [a = 1] = [];
+
+
+var f = {
+    [Symbol.iterator]: function*() {
+        var cur = 1;
+        for (;;) {
+            yield cur;
+        }
+    }
+};
+
--- a/nashorn/test/script/basic/yield.js	Wed Jul 05 21:38:13 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-/**
- * Check yield keyword is parsed and yield statement does nothing (yet).
- *
- * @test
- * @run
- */
-
-function func() {
-    yield 2;
-}
--- a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -1,3 +1,3 @@
-test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:14 strict mode function cannot have duplicate parameter name "x"
+test/script/error/NASHORN-154/function_mult_params_in_strict.js:38:17 strict mode function cannot have duplicate parameter name "x"
 function func(x, x) {}
-              ^
+                 ^
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -100,7 +100,7 @@
             "startPosition": "1181",
             "properties": [
               {
-                "endPosition": "1185",
+                "endPosition": "1187",
                 "kind": "PROPERTY",
                 "value": {
                   "endPosition": "1187",
@@ -2386,7 +2386,7 @@
           "startPosition": "1139",
           "properties": [
             {
-              "endPosition": "1143",
+              "endPosition": "1146",
               "kind": "PROPERTY",
               "value": {
                 "endPosition": "1146",
@@ -2403,7 +2403,7 @@
               }
             },
             {
-              "endPosition": "1150",
+              "endPosition": "1152",
               "kind": "PROPERTY",
               "value": {
                 "endPosition": "1152",
@@ -2443,7 +2443,7 @@
           "startPosition": "1160",
           "properties": [
             {
-              "endPosition": "1166",
+              "endPosition": "1169",
               "kind": "PROPERTY",
               "value": {
                 "endPosition": "1169",
@@ -2460,7 +2460,7 @@
               }
             },
             {
-              "endPosition": "1175",
+              "endPosition": "1177",
               "kind": "PROPERTY",
               "value": {
                 "endPosition": "1177",
@@ -2914,7 +2914,7 @@
         "startPosition": "1178",
         "properties": [
           {
-            "endPosition": "1182",
+            "endPosition": "1184",
             "kind": "PROPERTY",
             "value": {
               "endPosition": "1184",
@@ -3395,7 +3395,7 @@
         "startPosition": "1200",
         "properties": [
           {
-            "endPosition": "1206",
+            "endPosition": "1214",
             "kind": "PROPERTY",
             "value": {
               "endPosition": "1214",
@@ -4709,11 +4709,11 @@
 ,
 {
   "fileName": "parsernegativetests/strict_repeatparam.js",
-  "code": "ident (1119, 1)",
-  "columnNumber": "14",
+  "code": "ident (1122, 1)",
+  "columnNumber": "17",
   "kind": "ERROR",
-  "position": "1119",
-  "message": "parsernegativetests/strict_repeatparam.js:31:14 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n              ^",
+  "position": "1122",
+  "message": "parsernegativetests/strict_repeatparam.js:31:17 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n                 ^",
   "lineNumber": "31"
 }
 ,
--- a/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/parserapi_strict.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -6,10 +6,10 @@
 
 with({}) {}
        ^
-repeat_param.js:2:15 strict mode function cannot have duplicate parameter name "x"
+repeat_param.js:2:18 strict mode function cannot have duplicate parameter name "x"
 
 function func(x, x) {}
-               ^
+                  ^
 repeat_prop.js:2:22 Property "foo" already defined
 
 var obj = { foo: 34, foo: 'hello' };
--- a/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/treeapi/array_literal.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -74,7 +74,7 @@
         "properties": [
           {
             "getter": "null",
-            "endPosition": "74",
+            "endPosition": "76",
             "kind": "PROPERTY",
             "setter": "null",
             "value": {
--- a/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -6,7 +6,7 @@
     "properties": [
       {
         "getter": "null",
-        "endPosition": "8",
+        "endPosition": "12",
         "kind": "PROPERTY",
         "setter": "null",
         "value": {
@@ -38,7 +38,7 @@
     "properties": [
       {
         "getter": "null",
-        "endPosition": "34",
+        "endPosition": "37",
         "kind": "PROPERTY",
         "setter": "null",
         "value": {
@@ -57,7 +57,7 @@
       },
       {
         "getter": "null",
-        "endPosition": "41",
+        "endPosition": "43",
         "kind": "PROPERTY",
         "setter": "null",
         "value": {
@@ -83,7 +83,7 @@
     "properties": [
       {
         "getter": "null",
-        "endPosition": "57",
+        "endPosition": "60",
         "kind": "PROPERTY",
         "setter": "null",
         "value": {
@@ -102,7 +102,7 @@
       },
       {
         "getter": "null",
-        "endPosition": "66",
+        "endPosition": "68",
         "kind": "PROPERTY",
         "setter": "null",
         "value": {
--- a/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -1,7 +1,7 @@
 [
   {
     "getter": "null",
-    "endPosition": "17",
+    "endPosition": "22",
     "kind": "PROPERTY",
     "setter": "null",
     "value": {
@@ -20,7 +20,7 @@
   },
   {
     "getter": "null",
-    "endPosition": "31",
+    "endPosition": "38",
     "kind": "PROPERTY",
     "setter": "null",
     "value": {
@@ -45,7 +45,7 @@
   },
   {
     "getter": "null",
-    "endPosition": "46",
+    "endPosition": "61",
     "kind": "PROPERTY",
     "setter": "null",
     "value": {
@@ -72,7 +72,7 @@
   },
   {
     "getter": "null",
-    "endPosition": "69",
+    "endPosition": "72",
     "kind": "PROPERTY",
     "setter": "null",
     "value": {
--- a/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/treeapi/throw.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -80,7 +80,7 @@
       "properties": [
         {
           "getter": "null",
-          "endPosition": "97",
+          "endPosition": "105",
           "kind": "PROPERTY",
           "setter": "null",
           "value": {
--- a/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED	Wed Jul 05 21:39:33 2017 +0200
@@ -49,7 +49,7 @@
       "properties": [
         {
           "getter": "null",
-          "endPosition": "34",
+          "endPosition": "39",
           "kind": "PROPERTY",
           "setter": "null",
           "value": {
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java	Wed Jul 05 21:38:13 2017 +0200
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java	Wed Jul 05 21:39:33 2017 +0200
@@ -194,9 +194,9 @@
             pb.redirectError(errorFileHandle);
             final Process process = pb.start();
 
-            process.waitFor();
+            final int exitCode = process.waitFor();
 
-            if (errorFileHandle.length() > 0) {
+            if (exitCode != 0 || errorFileHandle.length() > 0) {
                 if (expectRunFailure) {
                     return;
                 }