OpenJDK / zgc / zgc
changeset 38788:684b1c77a66f
Merge
author | vlivanov |
---|---|
date | Wed, 11 May 2016 00:38:26 +0300 |
parents | eec42f06c93a fd9b36598481 |
children | 178dd1b12732 |
files | jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java jdk/src/java.desktop/share/classes/sun/swing/UIClientPropertyKey.java jdk/src/java.desktop/unix/native/common/awt/extutil.h jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.c jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingArea.h jdk/src/java.desktop/unix/native/libawt_headless/awt/VDrawingAreaP.h jdk/test/javax/transaction/testng/TEST.properties jdk/test/tools/jlink/hashes/HashesTest.java jdk/test/tools/jlink/hashes/newsrc/m2/module-info.java jdk/test/tools/jlink/hashes/newsrc/m2/org/m2/Util.java jdk/test/tools/jlink/hashes/newsrc/not_matched/module-info.java jdk/test/tools/jlink/hashes/newsrc/not_matched/org/not_matched/Name.java jdk/test/tools/jlink/hashes/src/m1/module-info.java jdk/test/tools/jlink/hashes/src/m1/org/m1/Main.java jdk/test/tools/jlink/hashes/src/m2/module-info.java jdk/test/tools/jlink/hashes/src/m2/org/m2/Util.java jdk/test/tools/jlink/hashes/src/not_matched/module-info.java jdk/test/tools/jlink/hashes/src/not_matched/org/not_matched/Name.java jdk/test/tools/launcher/modules/addmods/src/app/Main.java jdk/test/tools/launcher/modules/addmods/src/lib/jdk/lib/Util.java jdk/test/tools/launcher/modules/addmods/src/lib/module-info.java nashorn/test/script/basic/yield.js |
diffstat | 772 files changed, 29650 insertions(+), 7337 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri May 06 19:35:34 2016 +0300 +++ b/.hgtags Wed May 11 00:38:26 2016 +0300 @@ -358,3 +358,4 @@ 6072af7a98be3922f26bdce71b53bb3646cb2ac9 jdk-9+113 c84d0cce090e161d736de69e941830adf8c2f87a jdk-9+114 8d78fb40648dd221ce4ef19f9d5aa41ee1a3a884 jdk-9+115 +84aba7335005a3a47751dcf1f37935f97df9f99a jdk-9+116
--- a/.hgtags-top-repo Fri May 06 19:35:34 2016 +0300 +++ b/.hgtags-top-repo Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/common/autoconf/boot-jdk.m4 Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/common/autoconf/compare.sh.in Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/common/autoconf/generated-configure.sh Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/common/autoconf/platform.m4 Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/common/conf/jib-profiles.js Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/corba/.hgtags Wed May 11 00:38:26 2016 +0300 @@ -358,3 +358,4 @@ cc30faa2da498c478e89ab062ff160653ca1b170 jdk-9+113 10d175b0368c30f54350fc648adc41b94ce357ee jdk-9+114 7bab1b1b36824924b1c657a8419369ba93d198d3 jdk-9+115 +7dfa7377a5e601b8f740741a9a80e04c72dd04d6 jdk-9+116
--- a/hotspot/.hgtags Fri May 06 19:35:34 2016 +0300 +++ b/hotspot/.hgtags Wed May 11 00:38:26 2016 +0300 @@ -518,3 +518,4 @@ c569f8d89269fb6205b90f727581eb8cc04132f9 jdk-9+113 b64432bae5271735fd53300b2005b713e98ef411 jdk-9+114 88dd08d7be0fe7fb9f1914b1628f0aae9bf56e25 jdk-9+115 +61a214186dae6811dd989e9165e42f7dbf02acde jdk-9+116
--- a/jaxp/.hgtags Fri May 06 19:35:34 2016 +0300 +++ b/jaxp/.hgtags Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/TestPolicy.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java Wed May 11 00:38:26 2016 +0300 @@ -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 May 11 00:38:26 2016 +0300 @@ -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 May 11 00:38:26 2016 +0300 @@ -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 May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jaxws/.hgtags Wed May 11 00:38:26 2016 +0300 @@ -361,3 +361,4 @@ e980062475c10d21137051045bf95ee229db9b27 jdk-9+113 b314bb02182b9ca94708a91f312c377f5435f740 jdk-9+114 4ff86e5489e4c0513dadfa69def8601c110ca5cd jdk-9+115 +529f0bf896e58525614d863e283ad155531941cb jdk-9+116
--- a/jdk/make/Tools.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/Tools.gmk Wed May 11 00:38:26 2016 +0300 @@ -96,7 +96,13 @@ TOOL_SPP = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes build.tools.spp.Spp # Nimbus is used somewhere in the swing build. + +ifeq ($(BOOT_JDK_MODULAR), true) + COMPILENIMBUS_ADD_MODS := -addmods java.xml.bind +endif + TOOL_GENERATENIMBUS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ + $(COMPILENIMBUS_ADD_MODS) \ build.tools.generatenimbus.Generator TOOL_WRAPPERGENERATOR = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
--- a/jdk/make/gendata/Gendata-java.base.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/gendata/Gendata-java.base.gmk Wed May 11 00:38:26 2016 +0300 @@ -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 $@
--- a/jdk/make/gendata/GendataBreakIterator.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/gendata/GendataBreakIterator.gmk Wed May 11 00:38:26 2016 +0300 @@ -62,10 +62,13 @@ BIN := $(BREAK_ITERATOR_CLASSES)/jdk.localedata)) ifeq ($(BOOT_JDK_MODULAR), true) - BREAK_ITERATOR_BOOTCLASSPATH := -Xpatch:$(BREAK_ITERATOR_CLASSES) \ - -XaddExports:java.base/sun.text=ALL-UNNAMED \ - -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \ - -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED + BREAK_ITERATOR_BOOTCLASSPATH := \ + -Xpatch:java.base=$(BREAK_ITERATOR_CLASSES)/java.base \ + -Xpatch:jdk.localedata=$(BREAK_ITERATOR_CLASSES)/jdk.localedata \ + -XaddExports:java.base/sun.text=ALL-UNNAMED \ + -XaddExports:java.base/sun.text.resources=ALL-UNNAMED \ + -XaddExports:jdk.localedata/sun.text.resources.ext=ALL-UNNAMED \ + # else BREAK_ITERATOR_BOOTCLASSPATH := -Xbootclasspath/p:$(call PathList, \ $(BREAK_ITERATOR_CLASSES)/java.base \
--- a/jdk/make/launcher/Launcher-java.desktop.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-java.desktop.gmk Wed May 11 00:38:26 2016 +0300 @@ -31,7 +31,7 @@ ifndef BUILD_HEADLESS_ONLY $(eval $(call SetupBuildLauncher, appletviewer, \ MAIN_CLASS := sun.applet.Main, \ - JAVA_ARGS := -addmods ALL-SYSTEM, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ LIBS_unix := $(X_LIBS), \ )) endif
--- a/jdk/make/launcher/Launcher-java.scripting.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-java.scripting.gmk Wed May 11 00:38:26 2016 +0300 @@ -27,4 +27,5 @@ $(eval $(call SetupBuildLauncher, jrunscript, \ MAIN_CLASS := com.sun.tools.script.shell.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ ))
--- a/jdk/make/launcher/Launcher-jdk.compiler.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-jdk.compiler.gmk Wed May 11 00:38:26 2016 +0300 @@ -27,7 +27,8 @@ $(eval $(call SetupBuildLauncher, javac, \ MAIN_CLASS := com.sun.tools.javac.Main, \ - CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ + CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ ))
--- a/jdk/make/launcher/Launcher-jdk.javadoc.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-jdk.javadoc.gmk Wed May 11 00:38:26 2016 +0300 @@ -27,6 +27,7 @@ $(eval $(call SetupBuildLauncher, javadoc, \ MAIN_CLASS := jdk.javadoc.internal.tool.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \ ))
--- a/jdk/make/launcher/Launcher-jdk.jlink.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-jdk.jlink.gmk Wed May 11 00:38:26 2016 +0300 @@ -32,6 +32,7 @@ $(eval $(call SetupBuildLauncher, jlink,\ MAIN_CLASS := jdk.tools.jlink.internal.Main, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DENABLE_ARG_FILES \ -DEXPAND_CLASSPATH_WILDCARDS \ -DNEVER_ACT_AS_SERVER_CLASS_MACHINE, \
--- a/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/launcher/Launcher-jdk.scripting.nashorn.shell.gmk Wed May 11 00:38:26 2016 +0300 @@ -27,6 +27,6 @@ $(eval $(call SetupBuildLauncher, jjs, \ MAIN_CLASS := jdk.nashorn.tools.jjs.Main, \ - JAVA_ARGS := -addmods ALL-SYSTEM, \ + JAVA_ARGS := -addmods ALL-DEFAULT, \ CFLAGS := -DENABLE_ARG_FILES, \ ))
--- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers Wed May 11 00:38:26 2016 +0300 @@ -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;
--- a/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/make/src/classes/build/tools/generatenimbus/UIProperty.java Wed May 11 00:38:26 2016 +0300 @@ -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/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java Wed May 11 00:38:26 2016 +0300 @@ -102,7 +102,7 @@ @Override FileTypeDetector getFileTypeDetector() { - String userHome = GetPropertyAction.getProperty("user.home"); + String userHome = GetPropertyAction.privilegedGetProperty("user.home"); Path userMimeTypes = Paths.get(userHome, ".mime.types"); Path etcMimeTypes = Paths.get("/etc/mime.types");
--- a/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c Wed May 11 00:38:26 2016 +0300 @@ -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 @@ -53,7 +53,7 @@ start = t.tv_sec * 1000 + t.tv_usec / 1000; for (;;) { - int res = epoll_wait(epfd, events, numfds, timeout); + int res = epoll_wait(epfd, events, numfds, remaining); if (res < 0 && errno == EINTR) { if (remaining >= 0) { gettimeofday(&t, NULL);
--- a/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java Wed May 11 00:38:26 2016 +0300 @@ -84,7 +84,8 @@ static { IOUtil.load(); initStructSizes(); - String datamodel = GetPropertyAction.getProperty("sun.arch.data.model"); + String datamodel = + GetPropertyAction.privilegedGetProperty("sun.arch.data.model"); is64bit = "64".equals(datamodel); }
--- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystem.java Wed May 11 00:38:26 2016 +0300 @@ -29,8 +29,6 @@ import java.io.IOException; import java.util.*; import java.util.regex.Pattern; -import java.security.AccessController; -import sun.security.action.GetPropertyAction; import static sun.nio.fs.MacOSXNativeDispatcher.*;
--- a/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java Wed May 11 00:38:26 2016 +0300 @@ -46,8 +46,8 @@ @Override FileTypeDetector getFileTypeDetector() { - Path userMimeTypes = Paths.get( - GetPropertyAction.getProperty("user.home"), ".mime.types"); + Path userMimeTypes = Paths.get(GetPropertyAction + .privilegedGetProperty("user.home"), ".mime.types"); return chain(new MimeTypesFileTypeDetector(userMimeTypes), new UTIFileTypeDetector());
--- a/jdk/src/java.base/share/classes/java/io/File.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/io/File.java Wed May 11 00:38:26 2016 +0300 @@ -1896,7 +1896,7 @@ // temporary directory location private static final File tmpdir = new File( - GetPropertyAction.getProperty("java.io.tmpdir")); + GetPropertyAction.privilegedGetProperty("java.io.tmpdir")); static File location() { return tmpdir; }
--- a/jdk/src/java.base/share/classes/java/lang/Class.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/Class.java Wed May 11 00:38:26 2016 +0300 @@ -470,7 +470,7 @@ * expression with an empty argument list. The class is initialized if it * has not already been initialized. * - * <p>Note that this method propagates any exception thrown by the + * @deprecated This method propagates any exception thrown by the * nullary constructor, including a checked exception. Use of * this method effectively bypasses the compile-time exception * checking that would otherwise be performed by the compiler. @@ -500,6 +500,7 @@ * of this class. */ @CallerSensitive + @Deprecated(since="9") public T newInstance() throws InstantiationException, IllegalAccessException {
--- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java Wed May 11 00:38:26 2016 +0300 @@ -2615,7 +2615,7 @@ ServicesCatalog createOrGetServicesCatalog() { ServicesCatalog catalog = servicesCatalog; if (catalog == null) { - catalog = new ServicesCatalog(); + catalog = ServicesCatalog.create(); boolean set = trySetObjectField("servicesCatalog", catalog); if (!set) { // beaten by someone else
--- a/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/ProcessBuilder.java Wed May 11 00:38:26 2016 +0300 @@ -468,7 +468,7 @@ */ public abstract static class Redirect { private static final File NULL_FILE = new File( - (GetPropertyAction.getProperty("os.name") + (GetPropertyAction.privilegedGetProperty("os.name") .startsWith("Windows") ? "NUL" : "/dev/null") );
--- a/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/StackStreamFactory.java Wed May 11 00:38:26 2016 +0300 @@ -78,7 +78,8 @@ * Performance work and extensive testing is needed to replace the * VM built-in backtrace filled in Throwable with the StackWalker. */ - final static boolean isDebug = getProperty("stackwalk.debug", false); + final static boolean isDebug = + "true".equals(GetPropertyAction.privilegedGetProperty("stackwalk.debug")); static <T> StackFrameTraverser<T> makeStackTraverser(StackWalker walker, Function<? super Stream<StackFrame>, ? extends T> function) @@ -988,11 +989,4 @@ c.getName().startsWith("java.lang.invoke.LambdaForm"); } - private static boolean getProperty(String key, boolean value) { - String s = GetPropertyAction.getProperty(key); - if (s != null) { - return Boolean.parseBoolean(s); - } - return value; - } }
--- a/jdk/src/java.base/share/classes/java/lang/String.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/String.java Wed May 11 00:38:26 2016 +0300 @@ -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 ( + ), 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™ 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™ 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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/System.java Wed May 11 00:38:26 2016 +0300 @@ -69,7 +69,6 @@ import jdk.internal.logger.LocalizedLoggerWrapper; import jdk.internal.module.ModuleBootstrap; -import jdk.internal.module.Modules; import jdk.internal.module.ServicesCatalog; /** @@ -1924,10 +1923,6 @@ // initialize the module system System.bootLayer = ModuleBootstrap.boot(); - // base module needs to be loose (CODETOOLS-7901619) - Module base = Object.class.getModule(); - Modules.addReads(base, null); - // module system initialized VM.initLevel(2); }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java Wed May 11 00:38:26 2016 +0300 @@ -88,7 +88,7 @@ static { final String key = "jdk.internal.lambda.dumpProxyClasses"; - String path = GetPropertyAction.getProperty(key); + String path = GetPropertyAction.privilegedGetProperty(key); dumper = (null == path) ? null : ProxyClassesDumper.getInstance(path); }
--- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java Wed May 11 00:38:26 2016 +0300 @@ -53,7 +53,7 @@ static final boolean VAR_HANDLE_GUARDS; static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); DEBUG_METHOD_HANDLE_NAMES = Boolean.parseBoolean( props.getProperty("java.lang.invoke.MethodHandle.DEBUG_NAMES")); DUMP_CLASS_FILES = Boolean.parseBoolean(
--- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java Wed May 11 00:38:26 2016 +0300 @@ -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,7 +187,17 @@ private static final ProxyClassesDumper DUMPER; static { - Properties props = GetPropertyAction.getProperties(); + // 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.privilegedGetProperties(); final String strategy = props.getProperty("java.lang.invoke.stringConcat"); CACHE_ENABLE = Boolean.parseBoolean(
--- a/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/VarHandle.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandle.java.template Wed May 11 00:38:26 2016 +0300 @@ -157,6 +157,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, @@ -321,6 +330,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, @@ -537,6 +555,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) Preconditions.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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template Wed May 11 00:38:26 2016 +0300 @@ -229,6 +229,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( @@ -445,6 +455,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/lang/module/Configuration.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/Configuration.java Wed May 11 00:38:26 2016 +0300 @@ -25,6 +25,7 @@ package java.lang.module; +import java.io.PrintStream; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -183,17 +184,20 @@ this.nameToModule = Collections.emptyMap(); } - private Configuration(Configuration parent, Resolver resolver) { - Map<ResolvedModule, Set<ResolvedModule>> graph = resolver.finish(this); + private Configuration(Configuration parent, + Resolver resolver, + boolean check) + { + Map<ResolvedModule, Set<ResolvedModule>> g = resolver.finish(this, check); Map<String, ResolvedModule> nameToModule = new HashMap<>(); - for (ResolvedModule resolvedModule : graph.keySet()) { + for (ResolvedModule resolvedModule : g.keySet()) { nameToModule.put(resolvedModule.name(), resolvedModule); } this.parent = parent; - this.graph = graph; - this.modules = Collections.unmodifiableSet(graph.keySet()); + this.graph = g; + this.modules = Collections.unmodifiableSet(g.keySet()); this.nameToModule = Collections.unmodifiableMap(nameToModule); } @@ -283,10 +287,10 @@ Objects.requireNonNull(after); Objects.requireNonNull(roots); - Resolver resolver = new Resolver(before, this, after); + Resolver resolver = new Resolver(before, this, after, null); resolver.resolveRequires(roots); - return new Configuration(this, resolver); + return new Configuration(this, resolver, true); } @@ -340,10 +344,32 @@ Objects.requireNonNull(after); Objects.requireNonNull(roots); - Resolver resolver = new Resolver(before, this, after); + Resolver resolver = new Resolver(before, this, after, null); resolver.resolveRequires(roots).resolveUses(); - return new Configuration(this, resolver); + return new Configuration(this, resolver, true); + } + + + /** + * Resolves a collection of root modules, with service binding, and with + * the empty configuration as its parent. The post resolution checks + * are optionally run. + * + * This method is used to create the configuration for the boot layer. + */ + static Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection<String> roots, + boolean check, + PrintStream traceOutput) + { + Configuration parent = empty(); + + Resolver resolver + = new Resolver(finder, parent, ModuleFinder.empty(), traceOutput); + resolver.resolveRequires(roots).resolveUses(); + + return new Configuration(parent, resolver, check); }
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleDescriptor.java Wed May 11 00:38:26 2016 +0300 @@ -27,13 +27,17 @@ import java.io.InputStream; import java.io.IOException; +import java.io.PrintStream; import java.io.UncheckedIOException; +import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; @@ -45,7 +49,7 @@ import static java.util.Objects.*; import jdk.internal.module.Checks; -import jdk.internal.module.Hasher.DependencyHashes; +import jdk.internal.module.ModuleHashes; /** @@ -372,8 +376,9 @@ private Provides(String service, Set<String> providers, boolean check) { this.service = check ? requireServiceTypeName(service) : service; - providers = check ? Collections.unmodifiableSet(new HashSet<>(providers)) - : Collections.unmodifiableSet(providers); + providers = check + ? Collections.unmodifiableSet(new LinkedHashSet<>(providers)) + : Collections.unmodifiableSet(providers); if (providers.isEmpty()) throw new IllegalArgumentException("Empty providers set"); if (check) @@ -787,7 +792,7 @@ private final String osVersion; private final Set<String> conceals; private final Set<String> packages; - private final DependencyHashes hashes; + private final ModuleHashes hashes; private ModuleDescriptor(String name, boolean automatic, @@ -802,7 +807,7 @@ String osArch, String osVersion, Set<String> conceals, - DependencyHashes hashes) + ModuleHashes hashes) { this.name = name; @@ -878,7 +883,8 @@ String osArch, String osVersion, Set<String> conceals, - Set<String> packages) { + Set<String> packages, + ModuleHashes hashes) { this.name = name; this.automatic = automatic; this.synthetic = synthetic; @@ -894,7 +900,7 @@ this.osName = osName; this.osArch = osArch; this.osVersion = osVersion; - this.hashes = null; + this.hashes = hashes; } /** @@ -1063,9 +1069,9 @@ } /** - * Returns the object with the hashes of the dependences. + * Returns the object with the hashes of other modules */ - Optional<DependencyHashes> hashes() { + Optional<ModuleHashes> hashes() { return Optional.ofNullable(hashes); } @@ -1103,7 +1109,7 @@ String osArch; String osVersion; String mainClass; - DependencyHashes hashes; + ModuleHashes hashes; /** * Initializes a new builder with the given module name. @@ -1580,7 +1586,7 @@ return this; } - /* package */ Builder hashes(DependencyHashes hashes) { + /* package */ Builder hashes(ModuleHashes hashes) { this.hashes = hashes; return this; } @@ -1719,7 +1725,9 @@ hc = hc * 43 + Objects.hashCode(osVersion); hc = hc * 43 + Objects.hashCode(conceals); hc = hc * 43 + Objects.hashCode(hashes); - if (hc != 0) hash = hc; + if (hc == 0) + hc = -1; + hash = hc; } return hc; } @@ -1925,11 +1933,12 @@ static { /** - * Setup the shared secret to allow code in other packages create - * ModuleDescriptor and associated objects directly. + * Setup the shared secret to allow code in other packages access + * private package methods in java.lang.module. */ jdk.internal.misc.SharedSecrets .setJavaLangModuleAccess(new jdk.internal.misc.JavaLangModuleAccess() { + @Override public Requires newRequires(Set<Requires.Modifier> ms, String mn) { return new Requires(ms, mn, false); @@ -1974,7 +1983,8 @@ String osArch, String osVersion, Set<String> conceals, - Set<String> packages) { + Set<String> packages, + ModuleHashes hashes) { return new ModuleDescriptor(name, automatic, synthetic, @@ -1988,7 +1998,29 @@ osArch, osVersion, conceals, - packages); + packages, + hashes); + } + + @Override + public Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection<String> roots, + boolean check, + PrintStream traceOutput) + { + return Configuration.resolveRequiresAndUses(finder, roots, check, traceOutput); + } + + @Override + public ModuleReference newPatchedModule(ModuleDescriptor descriptor, + URI location, + Supplier<ModuleReader> s) { + return new ModuleReference(descriptor, location, s, true, null); + } + + @Override + public Optional<ModuleHashes> hashes(ModuleDescriptor descriptor) { + return descriptor.hashes(); } }); }
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleInfo.java Wed May 11 00:38:26 2016 +0300 @@ -37,11 +37,12 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import jdk.internal.module.Hasher.DependencyHashes; +import jdk.internal.module.ModuleHashes; import static jdk.internal.module.ClassFileConstants.*; @@ -337,7 +338,7 @@ // computeIfAbsent Set<String> providers = pm.get(sn); if (providers == null) { - providers = new HashSet<>(); + providers = new LinkedHashSet<>(); // preserve order pm.put(sn, providers); } providers.add(cn); @@ -425,7 +426,7 @@ map.put(dn, hash); } - builder.hashes(new DependencyHashes(algorithm, map)); + builder.hashes(new ModuleHashes(algorithm, map)); }
--- a/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModulePath.java Wed May 11 00:38:26 2016 +0300 @@ -40,7 +40,7 @@ import java.nio.file.attribute.BasicFileAttributes; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -52,7 +52,6 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.stream.Stream; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; @@ -190,18 +189,16 @@ } } - if (attrs.isRegularFile() || attrs.isDirectory()) { - // packaged or exploded module - ModuleReference mref = readModule(entry, attrs); - if (mref != null) { - String name = mref.descriptor().name(); - return Collections.singletonMap(name, mref); - } + // packaged or exploded module + ModuleReference mref = readModule(entry, attrs); + if (mref != null) { + String name = mref.descriptor().name(); + return Collections.singletonMap(name, mref); + } else { + // skipped + return Collections.emptyMap(); } - // not recognized - throw new FindException("Unrecognized module: " + entry); - } catch (IOException ioe) { throw new FindException(ioe); } @@ -238,16 +235,13 @@ // module found if (mref != null) { - // can have at most one version of a module in the directory String name = mref.descriptor().name(); if (nameToReference.put(name, mref) != null) { throw new FindException("Two versions of module " - + name + " found in " + dir); + + name + " found in " + dir); } - } - } } @@ -257,28 +251,40 @@ /** * Locates a packaged or exploded module, returning a {@code ModuleReference} - * to the module. Returns {@code null} if the module is not recognized - * as a packaged or exploded module. + * to the module. Returns {@code null} if the entry is skipped because it is + * to a directory that does not contain a module-info.class or it's a hidden + * file. * * @throws IOException if an I/O error occurs - * @throws FindException if an error occurs parsing the module descriptor + * @throws FindException if the file is not recognized as a module or an + * error occurs parsing its module descriptor */ private ModuleReference readModule(Path entry, BasicFileAttributes attrs) throws IOException { try { - ModuleReference mref = null; if (attrs.isDirectory()) { - mref = readExplodedModule(entry); - } if (attrs.isRegularFile()) { - if (entry.toString().endsWith(".jar")) { - mref = readJar(entry); - } else if (isLinkPhase && entry.toString().endsWith(".jmod")) { - mref = readJMod(entry); + return readExplodedModule(entry); // may return null + } + + String fn = entry.getFileName().toString(); + if (attrs.isRegularFile()) { + if (fn.endsWith(".jar")) { + return readJar(entry); + } else if (fn.endsWith(".jmod")) { + if (isLinkPhase) + return readJMod(entry); + throw new FindException("JMOD files not supported: " + entry); } } - return mref; + + // skip hidden files + if (fn.startsWith(".") || Files.isHidden(entry)) { + return null; + } else { + throw new FindException("Unrecognized module: " + entry); + } } catch (InvalidModuleDescriptorException e) { throw new FindException("Error reading module: " + entry, e); @@ -292,15 +298,17 @@ return zf.stream() .filter(e -> e.getName().startsWith("classes/") && e.getName().endsWith(".class")) - .map(e -> toPackageName(e)) + .map(e -> toPackageName(e.getName().substring(8))) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } /** * Returns a {@code ModuleReference} to a module in jmod file on the * file system. + * + * @throws IOException + * @throws InvalidModuleDescriptorException */ private ModuleReference readJMod(Path file) throws IOException { try (ZipFile zf = new ZipFile(file.toString())) { @@ -419,13 +427,12 @@ // scan the entries in the JAR file to locate the .class and service // configuration file - Stream<String> stream = jf.stream() - .map(e -> e.getName()) - .filter(e -> (e.endsWith(".class") || e.startsWith(SERVICES_PREFIX))) - .distinct(); - Map<Boolean, Set<String>> map - = stream.collect(Collectors.partitioningBy(s -> s.endsWith(".class"), - Collectors.toSet())); + Map<Boolean, Set<String>> map = + jf.stream() + .map(JarEntry::getName) + .filter(s -> (s.endsWith(".class") ^ s.startsWith(SERVICES_PREFIX))) + .collect(Collectors.partitioningBy(s -> s.endsWith(".class"), + Collectors.toSet())); Set<String> classFiles = map.get(Boolean.TRUE); Set<String> configFiles = map.get(Boolean.FALSE); @@ -433,19 +440,18 @@ classFiles.stream() .map(c -> toPackageName(c)) .distinct() - .forEach(p -> builder.exports(p)); + .forEach(builder::exports); // map names of service configuration files to service names Set<String> serviceNames = configFiles.stream() .map(this::toServiceName) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(Optional::stream) .collect(Collectors.toSet()); // parse each service configuration file for (String sn : serviceNames) { JarEntry entry = jf.getJarEntry(SERVICES_PREFIX + sn); - Set<String> providerClasses = new HashSet<>(); + Set<String> providerClasses = new LinkedHashSet<>(); try (InputStream in = jf.getInputStream(entry)) { BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); @@ -475,19 +481,25 @@ private Set<String> jarPackages(JarFile jf) { return jf.stream() .filter(e -> e.getName().endsWith(".class")) - .map(e -> toPackageName(e)) + .map(e -> toPackageName(e.getName())) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } /** * Returns a {@code ModuleReference} to a module in modular JAR file on * the file system. + * + * @throws IOException + * @throws FindException + * @throws InvalidModuleDescriptorException */ private ModuleReference readJar(Path file) throws IOException { - try (JarFile jf = new JarFile(file.toString())) { - + try (JarFile jf = new JarFile(file.toFile(), + true, // verify + ZipFile.OPEN_READ, + JarFile.Release.RUNTIME)) + { ModuleDescriptor md; JarEntry entry = jf.getJarEntry(MODULE_INFO); if (entry == null) { @@ -520,7 +532,6 @@ path.toString().endsWith(".class"))) .map(path -> toPackageName(dir.relativize(path))) .filter(pkg -> pkg.length() > 0) // module-info - .distinct() .collect(Collectors.toSet()); } catch (IOException x) { throw new UncheckedIOException(x); @@ -530,6 +541,9 @@ /** * Returns a {@code ModuleReference} to an exploded module on the file * system or {@code null} if {@code module-info.class} not found. + * + * @throws IOException + * @throws InvalidModuleDescriptorException */ private ModuleReference readExplodedModule(Path dir) throws IOException { Path mi = dir.resolve(MODULE_INFO); @@ -559,19 +573,6 @@ } } - private String toPackageName(ZipEntry entry) { - String name = entry.getName(); - assert name.endsWith(".class"); - // jmod classes in classes/, jar in / - int start = name.startsWith("classes/") ? 8 : 0; - int index = name.lastIndexOf("/"); - if (index > start) { - return name.substring(start, index).replace('/', '.'); - } else { - return ""; - } - } - private String toPackageName(Path path) { String name = path.toString(); assert name.endsWith(".class");
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReader.java Wed May 11 00:38:26 2016 +0300 @@ -142,10 +142,11 @@ * @see ClassLoader#defineClass(String, ByteBuffer, java.security.ProtectionDomain) */ default Optional<ByteBuffer> read(String name) throws IOException { - Optional<InputStream> in = open(name); - if (in.isPresent()) { - byte[] bytes = in.get().readAllBytes(); - return Optional.of(ByteBuffer.wrap(bytes)); + Optional<InputStream> oin = open(name); + if (oin.isPresent()) { + try (InputStream in = oin.get()) { + return Optional.of(ByteBuffer.wrap(in.readAllBytes())); + } } else { return Optional.empty(); }
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReference.java Wed May 11 00:38:26 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import java.util.Optional; import java.util.function.Supplier; -import jdk.internal.module.Hasher.HashSupplier; +import jdk.internal.module.ModuleHashes.HashSupplier; /** @@ -54,12 +54,33 @@ private final URI location; private final Supplier<ModuleReader> readerSupplier; + // true if this is a reference to a patched module + private boolean patched; + // the function that computes the hash of this module reference private final HashSupplier hasher; // cached hash string to avoid needing to compute it many times private String cachedHash; + + /** + * Constructs a new instance of this class. + */ + ModuleReference(ModuleDescriptor descriptor, + URI location, + Supplier<ModuleReader> readerSupplier, + boolean patched, + HashSupplier hasher) + + { + this.descriptor = Objects.requireNonNull(descriptor); + this.location = location; + this.readerSupplier = Objects.requireNonNull(readerSupplier); + this.patched = patched; + this.hasher = hasher; + } + /** * Constructs a new instance of this class. */ @@ -67,11 +88,9 @@ URI location, Supplier<ModuleReader> readerSupplier, HashSupplier hasher) + { - this.descriptor = Objects.requireNonNull(descriptor); - this.location = location; - this.readerSupplier = Objects.requireNonNull(readerSupplier); - this.hasher = hasher; + this(descriptor, location, readerSupplier, false, hasher); } @@ -96,10 +115,9 @@ URI location, Supplier<ModuleReader> readerSupplier) { - this(descriptor, location, readerSupplier, null); + this(descriptor, location, readerSupplier, false, null); } - /** * Returns the module descriptor. * @@ -151,6 +169,20 @@ /** + * Returns {@code true} if this module has been patched via -Xpatch. + */ + boolean isPatched() { + return patched; + } + + /** + * Returns the hash supplier for this module. + */ + HashSupplier hasher() { + return hasher; + } + + /** * Computes the hash of this module, returning it as a hex string. * Returns {@code null} if the hash cannot be computed. * @@ -166,8 +198,6 @@ return result; } - private int hash; - /** * Computes a hash code for this module reference. * @@ -181,12 +211,17 @@ public int hashCode() { int hc = hash; if (hc == 0) { - hc = Objects.hash(descriptor, location, readerSupplier, hasher); - if (hc != 0) hash = hc; + hc = Objects.hash(descriptor, location, readerSupplier, hasher, + Boolean.valueOf(patched)); + if (hc == 0) + hc = -1; + hash = hc; } return hc; } + private int hash; + /** * Tests this module reference for equality with the given object. * @@ -214,7 +249,8 @@ return Objects.equals(this.descriptor, that.descriptor) && Objects.equals(this.location, that.location) && Objects.equals(this.readerSupplier, that.readerSupplier) - && Objects.equals(this.hasher, that.hasher); + && Objects.equals(this.hasher, that.hasher) + && this.patched == that.patched; } /**
--- a/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/ModuleReferences.java Wed May 11 00:38:26 2016 +0300 @@ -48,8 +48,8 @@ import jdk.internal.misc.JavaLangAccess; import jdk.internal.misc.SharedSecrets; -import jdk.internal.module.Hasher; -import jdk.internal.module.Hasher.HashSupplier; +import jdk.internal.module.ModuleHashes; +import jdk.internal.module.ModuleHashes.HashSupplier; import jdk.internal.module.ModulePatcher; import sun.net.www.ParseUtil; @@ -89,7 +89,7 @@ static ModuleReference newJarModule(ModuleDescriptor md, Path file) { URI uri = file.toUri(); Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri); - HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm); + HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a); return newModule(md, uri, supplier, hasher); } @@ -99,7 +99,7 @@ static ModuleReference newJModModule(ModuleDescriptor md, Path file) { URI uri = file.toUri(); Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri); - HashSupplier hasher = (algorithm) -> Hasher.generate(file, algorithm); + HashSupplier hasher = (a) -> ModuleHashes.computeHashAsString(file, a); return newModule(md, file.toUri(), supplier, hasher); } @@ -122,7 +122,7 @@ private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); - private volatile boolean closed; + private boolean closed; SafeCloseModuleReader() { } @@ -198,7 +198,10 @@ static JarFile newJarFile(Path path) { try { - return new JarFile(path.toFile()); + return new JarFile(path.toFile(), + true, // verify + ZipFile.OPEN_READ, + JarFile.Release.RUNTIME); } catch (IOException ioe) { throw new UncheckedIOException(ioe); } @@ -219,6 +222,8 @@ if (je != null) { String encodedPath = ParseUtil.encodePath(name, false); String uris = "jar:" + uri + "!/" + encodedPath; + if (jf.isMultiRelease()) + uris += "#runtime"; return Optional.of(URI.create(uris)); } else { return Optional.empty();
--- a/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/Resolver.java Wed May 11 00:38:26 2016 +0300 @@ -25,8 +25,8 @@ package java.lang.module; +import java.io.PrintStream; import java.lang.module.ModuleDescriptor.Requires.Modifier; -import java.lang.reflect.Layer; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; @@ -43,7 +43,7 @@ import java.util.StringJoiner; import java.util.stream.Collectors; -import jdk.internal.module.Hasher; +import jdk.internal.module.ModuleHashes; /** * The resolver used by {@link Configuration#resolveRequires} and @@ -55,6 +55,7 @@ private final ModuleFinder beforeFinder; private final Configuration parent; private final ModuleFinder afterFinder; + private final PrintStream traceOutput; // maps module name to module reference private final Map<String, ModuleReference> nameToReference = new HashMap<>(); @@ -62,10 +63,12 @@ Resolver(ModuleFinder beforeFinder, Configuration parent, - ModuleFinder afterFinder) { + ModuleFinder afterFinder, + PrintStream traceOutput) { this.beforeFinder = beforeFinder; this.parent = parent; this.afterFinder = afterFinder; + this.traceOutput = traceOutput; } @@ -76,8 +79,6 @@ */ Resolver resolveRequires(Collection<String> roots) { - long start = trace_start("Resolve"); - // create the visit stack to get us started Deque<ModuleDescriptor> q = new ArrayDeque<>(); for (String root : roots) { @@ -95,10 +96,9 @@ } } - if (TRACE) { + if (isTracing()) { trace("Root module %s located", root); - if (mref.location().isPresent()) - trace(" (%s)", mref.location().get()); + mref.location().ifPresent(uri -> trace(" (%s)", uri)); } assert mref.descriptor().name().equals(root); @@ -108,13 +108,6 @@ resolve(q); - if (TRACE) { - long duration = System.currentTimeMillis() - start; - Set<String> names = nameToReference.keySet(); - trace("Resolver completed in %s ms", duration); - names.stream().sorted().forEach(name -> trace(" %s", name)); - } - return this; } @@ -153,11 +146,10 @@ q.offer(mref.descriptor()); resolved.add(mref.descriptor()); - if (TRACE) { + if (isTracing()) { trace("Module %s located, required by %s", dn, descriptor.name()); - if (mref.location().isPresent()) - trace(" (%s)", mref.location().get()); + mref.location().ifPresent(uri -> trace(" (%s)", uri)); } } @@ -175,8 +167,6 @@ */ Resolver resolveUses() { - long start = trace_start("Bind"); - // Scan the finders for all available service provider modules. As // java.base uses services then then module finders will be scanned // anyway. @@ -230,10 +220,10 @@ String pn = provider.name(); if (!nameToReference.containsKey(pn)) { - - if (TRACE && mref.location().isPresent()) - trace(" (%s)", mref.location().get()); - + if (isTracing()) { + mref.location() + .ifPresent(uri -> trace(" (%s)", uri)); + } nameToReference.put(pn, mref); q.push(provider); } @@ -248,14 +238,6 @@ } while (!candidateConsumers.isEmpty()); - - if (TRACE) { - long duration = System.currentTimeMillis() - start; - Set<String> names = nameToReference.keySet(); - trace("Bind completed in %s ms", duration); - names.stream().sorted().forEach(name -> trace(" %s", name)); - } - return this; } @@ -264,23 +246,33 @@ * Execute post-resolution checks and returns the module graph of resolved * modules as {@code Map}. The resolved modules will be in the given * configuration. + * + * @param check {@true} to execute the post resolution checks */ - Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf) { + Map<ResolvedModule, Set<ResolvedModule>> finish(Configuration cf, + boolean check) + { + if (isTracing()) { + trace("Result:"); + Set<String> names = nameToReference.keySet(); + names.stream().sorted().forEach(name -> trace(" %s", name)); + } - detectCycles(); - - checkPlatformConstraints(); - - checkHashes(); + if (check) { + detectCycles(); + checkPlatformConstraints(); + checkHashes(); + } Map<ResolvedModule, Set<ResolvedModule>> graph = makeGraph(cf); - checkExportSuppliers(graph); + if (check) { + checkExportSuppliers(graph); + } return graph; } - /** * Checks the given module graph for cycles. * @@ -420,52 +412,44 @@ } - /** * Checks the hashes in the module descriptor to ensure that they match - * the hash of the dependency's module reference. + * any recorded hashes. */ private void checkHashes() { - for (ModuleReference mref : nameToReference.values()) { ModuleDescriptor descriptor = mref.descriptor(); - // get map of module names to hash - Optional<Hasher.DependencyHashes> ohashes = descriptor.hashes(); + // get map of module hashes + Optional<ModuleHashes> ohashes = descriptor.hashes(); if (!ohashes.isPresent()) continue; - Hasher.DependencyHashes hashes = ohashes.get(); + ModuleHashes hashes = ohashes.get(); - // check dependences - for (ModuleDescriptor.Requires d : descriptor.requires()) { - String dn = d.name(); - String recordedHash = hashes.hashFor(dn); + String algorithm = hashes.algorithm(); + for (String dn : hashes.names()) { + ModuleReference other = nameToReference.get(dn); + if (other == null) { + other = parent.findModule(dn) + .map(ResolvedModule::reference) + .orElse(null); + } - if (recordedHash != null) { - - ModuleReference other = nameToReference.get(dn); - if (other == null) { - other = parent.findModule(dn) - .map(ResolvedModule::reference) - .orElse(null); - } - if (other == null) - throw new InternalError(dn + " not found"); - - String actualHash = other.computeHash(hashes.algorithm()); + // skip checking the hash if the module has been patched + if (other != null && !other.isPatched()) { + String recordedHash = hashes.hashFor(dn); + String actualHash = other.computeHash(algorithm); if (actualHash == null) fail("Unable to compute the hash of module %s", dn); + if (!recordedHash.equals(actualHash)) { + fail("Hash of %s (%s) differs to expected hash (%s)" + + " recorded in %s", dn, actualHash, recordedHash, + descriptor.name()); + } + } + } - if (!recordedHash.equals(actualHash)) { - fail("Hash of %s (%s) differs to expected hash (%s)", - dn, actualHash, recordedHash); - } - - } - - } } - } @@ -666,7 +650,7 @@ // source is exported to descriptor2 String source = export.source(); ModuleDescriptor other - = packageToExporter.put(source, descriptor2); + = packageToExporter.put(source, descriptor2); if (other != null && other != descriptor2) { // package might be local to descriptor1 @@ -690,33 +674,38 @@ } } - // uses S - for (String service : descriptor1.uses()) { - String pn = packageName(service); - if (!packageToExporter.containsKey(pn)) { - fail("Module %s does not read a module that exports %s", - descriptor1.name(), pn); - } - } + // uses/provides checks not applicable to automatic modules + if (!descriptor1.isAutomatic()) { - // provides S - for (Map.Entry<String, ModuleDescriptor.Provides> entry : - descriptor1.provides().entrySet()) { - String service = entry.getKey(); - ModuleDescriptor.Provides provides = entry.getValue(); - - String pn = packageName(service); - if (!packageToExporter.containsKey(pn)) { - fail("Module %s does not read a module that exports %s", - descriptor1.name(), pn); + // uses S + for (String service : descriptor1.uses()) { + String pn = packageName(service); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); + } } - for (String provider : provides.providers()) { - if (!packages.contains(packageName(provider))) { - fail("Provider %s not in module %s", - provider, descriptor1.name()); + // provides S + for (Map.Entry<String, ModuleDescriptor.Provides> entry : + descriptor1.provides().entrySet()) { + String service = entry.getKey(); + ModuleDescriptor.Provides provides = entry.getValue(); + + String pn = packageName(service); + if (!packageToExporter.containsKey(pn)) { + fail("Module %s does not read a module that exports %s", + descriptor1.name(), pn); + } + + for (String provider : provides.providers()) { + if (!packages.contains(packageName(provider))) { + fail("Provider %s not in module %s", + provider, descriptor1.name()); + } } } + } } @@ -796,27 +785,18 @@ throw new ResolutionException(msg); } - /** - * Tracing support, limited to boot layer for now. + * Tracing support */ - private final static boolean TRACE - = Boolean.getBoolean("jdk.launcher.traceResolver") - && (Layer.boot() == null); - - private String op; - - private long trace_start(String op) { - this.op = op; - return System.currentTimeMillis(); + private boolean isTracing() { + return traceOutput != null; } private void trace(String fmt, Object ... args) { - if (TRACE) { - System.out.print("[" + op + "] "); - System.out.format(fmt, args); - System.out.println(); + if (traceOutput != null) { + traceOutput.format("[Resolver] " + fmt, args); + traceOutput.println(); } }
--- a/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/module/SystemModuleFinder.java Wed May 11 00:38:26 2016 +0300 @@ -44,6 +44,7 @@ import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; import jdk.internal.jimage.ImageReaderFactory; +import jdk.internal.module.ModuleHashes; import jdk.internal.module.SystemModules; import jdk.internal.module.ModulePatcher; import jdk.internal.perf.PerfCounter; @@ -101,13 +102,16 @@ for (int i = 0; i < n; i++) { String mn = moduleNames[i]; ModuleDescriptor md; + String hash; if (fastLoad) { md = descriptors[i]; + hash = SystemModules.MODULES_TO_HASH[i]; } else { // fallback to read module-info.class // if fast loading of ModuleDescriptors is disabled ImageLocation location = imageReader.findLocation(mn, "module-info.class"); md = ModuleDescriptor.read(imageReader.getResourceBuffer(location)); + hash = null; } if (!md.name().equals(mn)) throw new InternalError(); @@ -123,7 +127,8 @@ } }; - ModuleReference mref = new ModuleReference(md, uri, readerSupplier); + ModuleReference mref = + new ModuleReference(md, uri, readerSupplier, hashSupplier(hash)); // may need a reference to a patched module if -Xpatch specified mref = ModulePatcher.interposeIfNeeded(mref); @@ -142,6 +147,18 @@ initTime.addElapsedTimeFrom(t0); } + private static ModuleHashes.HashSupplier hashSupplier(String hash) { + if (hash == null) + return null; + + return new ModuleHashes.HashSupplier() { + @Override + public String generate(String algorithm) { + return hash; + } + }; + } + SystemModuleFinder() { } @Override
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Wed May 11 00:38:26 2016 +0300 @@ -27,6 +27,7 @@ import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ResolvedModule; import java.util.Collections; import java.util.HashMap; @@ -41,6 +42,8 @@ import jdk.internal.loader.Loader; import jdk.internal.loader.LoaderPool; import jdk.internal.misc.SharedSecrets; +import jdk.internal.module.ServicesCatalog; +import jdk.internal.module.ServicesCatalog.ServiceProvider; import sun.security.util.SecurityConstants; @@ -549,4 +552,55 @@ public static Layer boot() { return SharedSecrets.getJavaLangAccess().getBootLayer(); } + + + /** + * Returns the ServicesCatalog for this Layer, creating it if not + * already created. + */ + ServicesCatalog getServicesCatalog() { + ServicesCatalog servicesCatalog = this.servicesCatalog; + if (servicesCatalog != null) + return servicesCatalog; + + Map<String, Set<ServiceProvider>> map = new HashMap<>(); + for (Module m : nameToModule.values()) { + ModuleDescriptor descriptor = m.getDescriptor(); + for (Provides provides : descriptor.provides().values()) { + String service = provides.service(); + Set<ServiceProvider> providers + = map.computeIfAbsent(service, k -> new HashSet<>()); + for (String pn : provides.providers()) { + providers.add(new ServiceProvider(m, pn)); + } + } + } + + ServicesCatalog catalog = new ServicesCatalog() { + @Override + public void register(Module module) { + throw new UnsupportedOperationException(); + } + @Override + public Set<ServiceProvider> findServices(String service) { + Set<ServiceProvider> providers = map.get(service); + if (providers == null) { + return Collections.emptySet(); + } else { + return Collections.unmodifiableSet(providers); + } + } + }; + + synchronized (this) { + servicesCatalog = this.servicesCatalog; + if (servicesCatalog == null) { + this.servicesCatalog = servicesCatalog = catalog; + } + } + + return servicesCatalog; + } + + private volatile ServicesCatalog servicesCatalog; }
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Wed May 11 00:38:26 2016 +0300 @@ -43,11 +43,7 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Stream; @@ -142,9 +138,6 @@ this.name = null; this.loader = loader; this.descriptor = null; - - // unnamed modules are loose - this.loose = true; } @@ -245,17 +238,27 @@ } + // -- + + // the special Module to mean reads or exported to "all unnamed modules" + private static final Module ALL_UNNAMED_MODULE = new Module(null); + + // special Module to mean exported to "everyone" + private static final Module EVERYONE_MODULE = new Module(null); + + // exported to all modules + private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE); + + // -- readability -- - // true if this module reads all unnamed modules (a.k.a. loose module) - private volatile boolean loose; - // the modules that this module permanently reads // (will be final when the modules are defined in reverse topology order) private volatile Set<Module> reads; - // created lazily, additional modules that this module reflectively reads - private volatile WeakSet<Module> transientReads; + // additional module (2nd key) that some module (1st key) reflectively reads + private static final WeakPairMap<Module, Module, Boolean> transientReads + = new WeakPairMap<>(); /** @@ -284,22 +287,19 @@ // check if this module reads other if (other.isNamed()) { - Set<Module> reads = this.reads; // volatile read if (reads != null && reads.contains(other)) return true; - - } else { - - // loose modules read all unnamed modules - if (this.loose) - return true; - } // check if this module reads the other module reflectively - WeakSet<Module> tr = this.transientReads; // volatile read - if (tr != null && tr.contains(other)) + if (transientReads.containsKeyPair(this, other)) + return true; + + // if other is an unnamed module then check if this module reads + // all unnamed modules + if (!other.isNamed() + && transientReads.containsKeyPair(this, ALL_UNNAMED_MODULE)) return true; return false; @@ -346,8 +346,7 @@ } /** - * Makes the given {@code Module} readable to this module without - * notifying the VM. + * Updates this module to read another module without notifying the VM. * * @apiNote This method is for VM white-box testing. */ @@ -361,40 +360,28 @@ * If {@code syncVM} is {@code true} then the VM is notified. */ private void implAddReads(Module other, boolean syncVM) { + Objects.requireNonNull(other); // nothing to do if (other == this || !this.isNamed()) return; - // if the other is null then change this module to be loose. - if (other == null) { - if (syncVM) - addReads0(this, null); - this.loose = true; - return; - } - // check if we already read this module Set<Module> reads = this.reads; if (reads != null && reads.contains(other)) return; // update VM first, just in case it fails - if (syncVM) - addReads0(this, other); + if (syncVM) { + if (other == ALL_UNNAMED_MODULE) { + addReads0(this, null); + } else { + addReads0(this, other); + } + } // add reflective read - WeakSet<Module> tr = this.transientReads; - if (tr == null) { - synchronized (this) { - tr = this.transientReads; - if (tr == null) { - tr = new WeakSet<>(); - this.transientReads = tr; - } - } - } - tr.add(other); + transientReads.putIfAbsent(this, other, Boolean.TRUE); } @@ -404,15 +391,10 @@ // (will be final when the modules are defined in reverse topology order) private volatile Map<String, Set<Module>> exports; - // created lazily, additional exports added at run-time - private volatile Map<String, WeakSet<Module>> transientExports; - - // the special Module to mean exported to all modules - private static final Module EVERYONE_MODULE = new Module(null); - private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE); - - // the special Module to mean exported to all unnamed modules - private static final Module ALL_UNNAMED_MODULE = new Module(null); + // additional exports added at run-time + // this module (1st key), other module (2nd key), exported packages (value) + private static final WeakPairMap<Module, Module, Map<String, Boolean>> + transientExports = new WeakPairMap<>(); /** @@ -489,23 +471,9 @@ if (exports != null) { Set<Module> targets = exports.get(pn); - if (targets != null) { - - // exported to all modules - if (targets.contains(EVERYONE_MODULE)) - return true; - - if (other != EVERYONE_MODULE) { - // exported to other - if (targets.contains(other)) - return true; - - // other is an unnamed module && exported to all unnamed - if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE)) - return true; - } - - } + if ((targets != null) + && (targets.contains(other) || targets.contains(EVERYONE_MODULE))) + return true; } return false; } @@ -515,29 +483,27 @@ * package package to the given module. */ private boolean isExportedReflectively(String pn, Module other) { - Map<String, WeakSet<Module>> te = this.transientExports; - if (te != null) { - WeakSet<Module> targets = te.get(pn); + // exported to all modules + Map<String, ?> exports = transientExports.get(this, EVERYONE_MODULE); + if (exports != null && exports.containsKey(pn)) + return true; - if (targets != null) { + if (other != EVERYONE_MODULE) { - // exported to all modules - if (targets.contains(EVERYONE_MODULE)) + // exported to other + exports = transientExports.get(this, other); + if (exports != null && exports.containsKey(pn)) + return true; + + // other is an unnamed module && exported to all unnamed + if (!other.isNamed()) { + exports = transientExports.get(this, ALL_UNNAMED_MODULE); + if (exports != null && exports.containsKey(pn)) return true; - - if (other != EVERYONE_MODULE) { - - // exported to other - if (targets.contains(other)) - return true; - - // other is an unnamed module && exported to all unnamed - if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE)) - return true; - } } } + return false; } @@ -638,34 +604,19 @@ } } - // create transientExports if needed - Map<String, WeakSet<Module>> te = this.transientExports; // read - if (te == null) { - synchronized (this) { - te = this.transientExports; - if (te == null) { - te = new ConcurrentHashMap<>(); - this.transientExports = te; // volatile write - } - } - } - // add package name to transientExports if absent - WeakSet<Module> s = te.get(pn); - if (s == null) { - s = new WeakSet<>(); - WeakSet<Module> prev = te.putIfAbsent(pn, s); - if (prev != null) - s = prev; - } - s.add(other); + transientExports + .computeIfAbsent(this, other, + (_this, _other) -> new ConcurrentHashMap<>()) + .putIfAbsent(pn, Boolean.TRUE); } // -- services -- - // created lazily, additional service types that this module uses - private volatile WeakSet<Class<?>> transientUses; + // additional service type (2nd key) that some module (1st key) uses + private static final WeakPairMap<Module, Class<?>, Boolean> transientUses + = new WeakPairMap<>(); /** * If the caller's module is this module then update this module to add a @@ -702,17 +653,7 @@ } if (!canUse(st)) { - WeakSet<Class<?>> uses = this.transientUses; - if (uses == null) { - synchronized (this) { - uses = this.transientUses; - if (uses == null) { - uses = new WeakSet<>(); - this.transientUses = uses; - } - } - } - uses.add(st); + transientUses.putIfAbsent(this, st, Boolean.TRUE); } } @@ -746,11 +687,7 @@ return true; // uses added via addUses - WeakSet<Class<?>> uses = this.transientUses; - if (uses != null && uses.contains(st)) - return true; - - return false; + return transientUses.containsKeyPair(this, st); } @@ -885,7 +822,7 @@ // -- creating Module objects -- /** - * Find the runtime Module corresponding to the given ReadDependence + * Find the runtime Module corresponding to the given ResolvedModule * in the given parent Layer (or its parents). */ private static Module find(ResolvedModule resolvedModule, Layer layer) { @@ -969,7 +906,7 @@ // automatic modules reads all unnamed modules if (descriptor.isAutomatic()) { - m.implAddReads(null, true); + m.implAddReads(ALL_UNNAMED_MODULE, true); } // exports @@ -1097,7 +1034,7 @@ * the representation is the string {@code "module"}, followed by a space, * and then the module name. For an unnamed module, the representation is * the string {@code "unnamed module"}, followed by a space, and then an - * implementation specific identifier for the unnamed module. + * implementation specific string that identifies the unnamed module. * * @return The string representation of this module */ @@ -1112,46 +1049,6 @@ } - // -- supporting classes -- - - - /** - * A "not-a-Set" set of weakly referenced objects that supports concurrent - * access. - */ - private static class WeakSet<E> { - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Lock readLock = lock.readLock(); - private final Lock writeLock = lock.writeLock(); - - private final WeakHashMap<E, Boolean> map = new WeakHashMap<>(); - - /** - * Adds the specified element to the set. - */ - void add(E e) { - writeLock.lock(); - try { - map.put(e, Boolean.TRUE); - } finally { - writeLock.unlock(); - } - } - - /** - * Returns {@code true} if this set contains the specified element. - */ - boolean contains(E e) { - readLock.lock(); - try { - return map.containsKey(e); - } finally { - readLock.unlock(); - } - } - } - - // -- native methods -- // JVM_DefineModule @@ -1196,8 +1093,12 @@ m1.implAddReads(m2, true); } @Override + public void addReadsAllUnnamed(Module m) { + m.implAddReads(Module.ALL_UNNAMED_MODULE); + } + @Override public void addExports(Module m, String pn, Module other) { - m.implAddExports(pn, Objects.requireNonNull(other), true); + m.implAddExports(pn, other, true); } @Override public void addExportsToAll(Module m, String pn) { @@ -1211,6 +1112,10 @@ public void addPackage(Module m, String pn) { m.implAddPackage(pn, true); } + @Override + public ServicesCatalog getServicesCatalog(Layer layer) { + return layer.getServicesCatalog(); + } }); } }
--- a/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Proxy.java Wed May 11 00:38:26 2016 +0300 @@ -582,7 +582,7 @@ } private static final String DEBUG = - GetPropertyAction.getProperty("jdk.proxy.debug", ""); + GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", ""); private static boolean isDebug() { return !DEBUG.isEmpty();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/WeakPairMap.java Wed May 11 00:38:26 2016 +0300 @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.lang.reflect; + +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Collection; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiFunction; + +/** + * A WeakHashMap-like data structure that uses a pair of weakly-referenced keys + * with identity equality semantics to associate a strongly-referenced value. + * Unlike WeakHashMap, this data structure is thread-safe. + * + * @param <K1> the type of 1st key in key pair + * @param <K2> the type of 2nd key in key pair + * @param <V> the type of value + * @author Peter Levart + */ +final class WeakPairMap<K1, K2, V> { + + private final ConcurrentHashMap<Pair<K1, K2>, V> map = new ConcurrentHashMap<>(); + private final ReferenceQueue<Object> queue = new ReferenceQueue<>(); + + /** + * Tests if the specified pair of keys are associated with a value + * in the WeakPairMap. + * + * @param k1 the 1st of the pair of keys + * @param k2 the 2nd of the pair of keys + * @return true if and only if the specified key pair is in this WeakPairMap, + * as determined by the identity comparison; false otherwise + * @throws NullPointerException if any of the specified keys is null + */ + public boolean containsKeyPair(K1 k1, K2 k2) { + expungeStaleAssociations(); + return map.containsKey(Pair.lookup(k1, k2)); + } + + /** + * Returns the value to which the specified pair of keys is mapped, or null + * if this WeakPairMap contains no mapping for the key pair. + * <p>More formally, if this WeakPairMap contains a mapping from a key pair + * {@code (_k1, _k2)} to a value {@code v} such that + * {@code k1 == _k1 && k2 == _k2}, then this method returns {@code v}; + * otherwise it returns {@code null}. + * (There can be at most one such mapping.) + * + * @param k1 the 1st of the pair of keys for which the mapped value is to + * be returned + * @param k2 the 2nd of the pair of keys for which the mapped value is to + * be returned + * @return the value to which the specified key pair is mapped, or null if + * this map contains no mapping for the key pair + * @throws NullPointerException if any of the specified keys is null + */ + public V get(K1 k1, K2 k2) { + expungeStaleAssociations(); + return map.get(Pair.lookup(k1, k2)); + } + + /** + * Maps the specified key pair to the specified value in this WeakPairMap. + * Neither the keys nor the value can be null. + * <p>The value can be retrieved by calling the {@link #get} method + * with the the same keys (compared by identity). + * + * @param k1 the 1st of the pair of keys with which the specified value is to + * be associated + * @param k2 the 2nd of the pair of keys with which the specified value is to + * be associated + * @param v value to be associated with the specified key pair + * @return the previous value associated with key pair, or {@code null} if + * there was no mapping for key pair + * @throws NullPointerException if any of the specified keys or value is null + */ + public V put(K1 k1, K2 k2, V v) { + expungeStaleAssociations(); + return map.put(Pair.weak(k1, k2, queue), v); + } + + /** + * If the specified key pair is not already associated with a value, + * associates it with the given value and returns {@code null}, else does + * nothing and returns the currently associated value. + * + * @param k1 the 1st of the pair of keys with which the specified value is to + * be associated + * @param k2 the 2nd of the pair of keys with which the specified value is to + * be associated + * @param v value to be associated with the specified key pair + * @return the previous value associated with key pair, or {@code null} if + * there was no mapping for key pair + * @throws NullPointerException if any of the specified keys or value is null + */ + public V putIfAbsent(K1 k1, K2 k2, V v) { + expungeStaleAssociations(); + return map.putIfAbsent(Pair.weak(k1, k2, queue), v); + } + + /** + * If the specified key pair is not already associated with a value, + * attempts to compute its value using the given mapping function + * and enters it into this WeakPairMap unless {@code null}. The entire + * method invocation is performed atomically, so the function is + * applied at most once per key pair. Some attempted update operations + * on this WeakPairMap by other threads may be blocked while computation + * is in progress, so the computation should be short and simple, + * and must not attempt to update any other mappings of this WeakPairMap. + * + * @param k1 the 1st of the pair of keys with which the + * computed value is to be associated + * @param k2 the 2nd of the pair of keys with which the + * computed value is to be associated + * @param mappingFunction the function to compute a value + * @return the current (existing or computed) value associated with + * the specified key pair, or null if the computed value is null + * @throws NullPointerException if any of the specified keys or + * mappingFunction is null + * @throws IllegalStateException if the computation detectably + * attempts a recursive update to this map + * that would otherwise never complete + * @throws RuntimeException or Error if the mappingFunction does so, in + * which case the mapping is left unestablished + */ + public V computeIfAbsent(K1 k1, K2 k2, + BiFunction<? super K1, ? super K2, ? extends V> + mappingFunction) { + expungeStaleAssociations(); + try { + return map.computeIfAbsent( + Pair.weak(k1, k2, queue), + pair -> mappingFunction.apply(pair.first(), pair.second())); + } finally { + Reference.reachabilityFence(k1); + Reference.reachabilityFence(k2); + } + } + + /** + * Returns a {@link Collection} view of the values contained in this + * WeakPairMap. The collection is backed by the WeakPairMap, so changes to + * the map are reflected in the collection, and vice-versa. The collection + * supports element removal, which removes the corresponding + * mapping from this map, via the {@code Iterator.remove}, + * {@code Collection.remove}, {@code removeAll}, + * {@code retainAll}, and {@code clear} operations. It does not + * support the {@code add} or {@code addAll} operations. + * + * @return the collection view + */ + public Collection<V> values() { + expungeStaleAssociations(); + return map.values(); + } + + /** + * Removes associations from this WeakPairMap for which at least one of the + * keys in key pair has been found weakly-reachable and corresponding + * WeakRefPeer(s) enqueued. Called as part of each public operation. + */ + private void expungeStaleAssociations() { + WeakRefPeer<?> peer; + while ((peer = (WeakRefPeer<?>) queue.poll()) != null) { + map.remove(peer.weakPair()); + } + } + + /** + * Common interface of both {@link Weak} and {@link Lookup} key pairs. + */ + private interface Pair<K1, K2> { + + static <K1, K2> Pair<K1, K2> weak(K1 k1, K2 k2, + ReferenceQueue<Object> queue) { + return new Weak<>(k1, k2, queue); + } + + static <K1, K2> Pair<K1, K2> lookup(K1 k1, K2 k2) { + return new Lookup<>(k1, k2); + } + + /** + * @return The 1st of the pair of keys (may be null for {@link Weak} + * when it gets cleared) + */ + K1 first(); + + /** + * @return The 2nd of the pair of keys (may be null for {@link Weak} + * when it gets cleared) + */ + K2 second(); + + static int hashCode(Object first, Object second) { + // assert first != null && second != null; + return System.identityHashCode(first) ^ + System.identityHashCode(second); + } + + static boolean equals(Object first, Object second, Pair<?, ?> p) { + return first != null && second != null && + first == p.first() && second == p.second(); + } + + /** + * A Pair where both keys are weakly-referenced. + * It is composed of two instances of {@link WeakRefPeer}s: + * <pre>{@code + * + * +-referent-> [K1] +-referent-> [K2] + * | | + * +----------------+ +----------------+ + * | Pair.Weak <: |-----peer----->| (anonymous) <: | + * | WeakRefPeer, | | WeakRefPeer | + * | Pair |<--weakPair()--| | + * +----------------+ +----------------+ + * | ^ + * | | + * +-weakPair()-+ + * + * }</pre> + * <p> + * Pair.Weak is used for CHM keys. Both peers are associated with the + * same {@link ReferenceQueue} so when either of their referents + * becomes weakly-reachable, the corresponding entries can be + * {@link #expungeStaleAssociations() expunged} from the map. + */ + final class Weak<K1, K2> extends WeakRefPeer<K1> implements Pair<K1, K2> { + + // saved hash so it can be retrieved after the reference is cleared + private final int hash; + // link to <K2> peer + private final WeakRefPeer<K2> peer; + + Weak(K1 k1, K2 k2, ReferenceQueue<Object> queue) { + super(k1, queue); + hash = Pair.hashCode(k1, k2); + peer = new WeakRefPeer<>(k2, queue) { + // link back to <K1> peer + @Override + Weak<?, ?> weakPair() { return Weak.this; } + }; + } + + @Override + Weak<?, ?> weakPair() { + return this; + } + + @Override + public K1 first() { + return get(); + } + + @Override + public K2 second() { + return peer.get(); + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public boolean equals(Object obj) { + return this == obj || + (obj instanceof Pair && + Pair.equals(first(), second(), (Pair<?, ?>) obj)); + } + } + + /** + * Optimized lookup Pair, used as lookup key in methods like + * {@link java.util.Map#get(Object)} or + * {@link java.util.Map#containsKey(Object)}) where + * there is a great chance its allocation is eliminated + * by escape analysis when such lookups are inlined by JIT. + * All its methods are purposely designed so that 'this' is never + * passed to any other method or used as identity. + */ + final class Lookup<K1, K2> implements Pair<K1, K2> { + private final K1 k1; + private final K2 k2; + + Lookup(K1 k1, K2 k2) { + this.k1 = Objects.requireNonNull(k1); + this.k2 = Objects.requireNonNull(k2); + } + + @Override + public K1 first() { + return k1; + } + + @Override + public K2 second() { + return k2; + } + + @Override + public int hashCode() { + return Pair.hashCode(k1, k2); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Pair && + Pair.equals(k1, k2, (Pair<?, ?>) obj); + } + } + } + + /** + * Common abstract supertype of a pair of WeakReference peers. + */ + private static abstract class WeakRefPeer<K> extends WeakReference<K> { + + WeakRefPeer(K k, ReferenceQueue<Object> queue) { + super(Objects.requireNonNull(k), queue); + } + + /** + * @return the {@link Pair.Weak} side of the pair of peers. + */ + abstract Pair.Weak<?, ?> weakPair(); + } +}
--- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java Wed May 11 00:38:26 2016 +0300 @@ -1536,7 +1536,7 @@ * be performed to generate a result with the specified scale, the * specified rounding mode is applied. * - * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method + * @deprecated The method {@link #divide(BigDecimal, int, RoundingMode)} * should be used in preference to this legacy method. * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -1558,6 +1558,7 @@ * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) { if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode"); @@ -1602,7 +1603,7 @@ * rounding must be performed to generate a result with the given * scale, the specified rounding mode is applied. * - * <p>The new {@link #divide(BigDecimal, RoundingMode)} method + * @deprecated The method {@link #divide(BigDecimal, RoundingMode)} * should be used in preference to this legacy method. * * @param divisor value by which this {@code BigDecimal} is to be divided. @@ -1623,6 +1624,7 @@ * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal divide(BigDecimal divisor, int roundingMode) { return this.divide(divisor, scale, roundingMode); } @@ -2267,14 +2269,20 @@ * Rounding mode to round away from zero. Always increments the * digit prior to a nonzero discarded fraction. Note that this rounding * mode never decreases the magnitude of the calculated value. + * + * @deprecated Use {@link RoundingMode#UP} instead. */ + @Deprecated(since="9") public static final int ROUND_UP = 0; /** * Rounding mode to round towards zero. Never increments the digit * prior to a discarded fraction (i.e., truncates). Note that this * rounding mode never increases the magnitude of the calculated value. + * + * @deprecated Use {@link RoundingMode#DOWN} instead. */ + @Deprecated(since="9") public static final int ROUND_DOWN = 1; /** @@ -2283,7 +2291,10 @@ * {@code ROUND_UP}; if negative, behaves as for * {@code ROUND_DOWN}. Note that this rounding mode never * decreases the calculated value. + * + * @deprecated Use {@link RoundingMode#CEILING} instead. */ + @Deprecated(since="9") public static final int ROUND_CEILING = 2; /** @@ -2292,7 +2303,10 @@ * {@code ROUND_DOWN}; if negative, behave as for * {@code ROUND_UP}. Note that this rounding mode never * increases the calculated value. + * + * @deprecated Use {@link RoundingMode#FLOOR} instead. */ + @Deprecated(since="9") public static final int ROUND_FLOOR = 3; /** @@ -2302,7 +2316,10 @@ * ≥ 0.5; otherwise, behaves as for {@code ROUND_DOWN}. Note * that this is the rounding mode that most of us were taught in * grade school. + * + * @deprecated Use {@link RoundingMode#HALF_UP} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_UP = 4; /** @@ -2311,7 +2328,10 @@ * down. Behaves as for {@code ROUND_UP} if the discarded * fraction is {@literal >} 0.5; otherwise, behaves as for * {@code ROUND_DOWN}. + * + * @deprecated Use {@link RoundingMode#HALF_DOWN} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_DOWN = 5; /** @@ -2323,7 +2343,10 @@ * {@code ROUND_HALF_DOWN} if it's even. Note that this is the * rounding mode that minimizes cumulative error when applied * repeatedly over a sequence of calculations. + * + * @deprecated Use {@link RoundingMode#HALF_EVEN} instead. */ + @Deprecated(since="9") public static final int ROUND_HALF_EVEN = 6; /** @@ -2331,7 +2354,10 @@ * result, hence no rounding is necessary. If this rounding mode is * specified on an operation that yields an inexact result, an * {@code ArithmeticException} is thrown. + * + * @deprecated Use {@link RoundingMode#UNNECESSARY} instead. */ + @Deprecated(since="9") public static final int ROUND_UNNECESSARY = 7; @@ -2408,7 +2434,7 @@ * Instead, {@code setScale} returns an object with the proper * scale; the returned object may or may not be newly allocated. * - * <p>The new {@link #setScale(int, RoundingMode)} method should + * @deprecated The method {@link #setScale(int, RoundingMode)} should * be used in preference to this legacy method. * * @param newScale scale of the {@code BigDecimal} value to be returned. @@ -2431,6 +2457,7 @@ * @see #ROUND_HALF_EVEN * @see #ROUND_UNNECESSARY */ + @Deprecated(since="9") public BigDecimal setScale(int newScale, int roundingMode) { if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY) throw new IllegalArgumentException("Invalid rounding mode");
--- a/jdk/src/java.base/share/classes/java/math/RoundingMode.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/math/RoundingMode.java Wed May 11 00:38:26 2016 +0300 @@ -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 @@ -90,6 +90,7 @@ * @author Joseph D. Darcy * @since 1.5 */ +@SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal public enum RoundingMode { /**
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed May 11 00:38:26 2016 +0300 @@ -52,7 +52,8 @@ protected InetAddress connectedAddress = null; private int connectedPort = -1; - private static final String os = GetPropertyAction.getProperty("os.name"); + private static final String os = + GetPropertyAction.privilegedGetProperty("os.name"); /** * flag set if the native connect() call not to be used
--- a/jdk/src/java.base/share/classes/java/net/InetAddress.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java Wed May 11 00:38:26 2016 +0300 @@ -1124,7 +1124,7 @@ private static NameService createNameService() { String hostsFileName = - GetPropertyAction.getProperty("jdk.net.hosts.file"); + GetPropertyAction.privilegedGetProperty("jdk.net.hosts.file"); NameService theNameService; if (hostsFileName != null) { theNameService = new HostsFileNameService(hostsFileName); @@ -1643,9 +1643,11 @@ * property can vary across implementations of the java. * classes. The default is an empty String "". */ - String prefix = GetPropertyAction.getProperty("impl.prefix", ""); + String prefix = GetPropertyAction.privilegedGetProperty("impl.prefix", ""); try { - impl = Class.forName("java.net." + prefix + implName).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName("java.net." + prefix + implName).newInstance(); + impl = tmp; } catch (ClassNotFoundException e) { System.err.println("Class not found: java.net." + prefix + implName + ":\ncheck impl.prefix property " + @@ -1662,7 +1664,9 @@ if (impl == null) { try { - impl = Class.forName(implName).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(implName).newInstance(); + impl = tmp; } catch (Exception e) { throw new Error("System property impl.prefix incorrect"); }
--- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java Wed May 11 00:38:26 2016 +0300 @@ -71,7 +71,9 @@ try { Class<?> c = Class.forName("sun.net.spi.DefaultProxySelector"); if (c != null && ProxySelector.class.isAssignableFrom(c)) { - theProxySelector = (ProxySelector) c.newInstance(); + @SuppressWarnings("deprecation") + ProxySelector tmp = (ProxySelector) c.newInstance(); + theProxySelector = tmp; } } catch (Exception e) { theProxySelector = null;
--- a/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/SocksSocketImpl.java Wed May 11 00:38:26 2016 +0300 @@ -178,7 +178,7 @@ userName = pw.getUserName(); password = new String(pw.getPassword()); } else { - userName = GetPropertyAction.getProperty("user.name"); + userName = GetPropertyAction.privilegedGetProperty("user.name"); } if (userName == null) return false; @@ -1088,7 +1088,7 @@ userName = System.getProperty("user.name"); } catch (SecurityException se) { /* swallow Exception */ } } else { - userName = GetPropertyAction.getProperty("user.name"); + userName = GetPropertyAction.privilegedGetProperty("user.name"); } return userName; }
--- a/jdk/src/java.base/share/classes/java/net/URL.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/URL.java Wed May 11 00:38:26 2016 +0300 @@ -1198,8 +1198,9 @@ public URLStreamHandler createURLStreamHandler(String protocol) { String name = PREFIX + "." + protocol + ".Handler"; try { - Class<?> c = Class.forName(name); - return (URLStreamHandler)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(name).newInstance(); + return (URLStreamHandler)o; } catch (ClassNotFoundException x) { // ignore } catch (Exception e) { @@ -1212,7 +1213,7 @@ private static URLStreamHandler lookupViaProperty(String protocol) { String packagePrefixList = - GetPropertyAction.getProperty(protocolPathProp); + GetPropertyAction.privilegedGetProperty(protocolPathProp); if (packagePrefixList == null) { // not set return null; @@ -1234,7 +1235,9 @@ } } if (cls != null) { - handler = (URLStreamHandler)cls.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = cls.newInstance(); + handler = (URLStreamHandler)tmp; } } catch (Exception e) { // any number of exceptions can get thrown here
--- a/jdk/src/java.base/share/classes/java/net/URLConnection.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/URLConnection.java Wed May 11 00:38:26 2016 +0300 @@ -1323,7 +1323,9 @@ } } if (cls != null) { - return (ContentHandler) cls.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = cls.newInstance(); + return (ContentHandler) tmp; } } catch(Exception ignored) { } } @@ -1397,7 +1399,7 @@ */ private String getContentHandlerPkgPrefixes() { String packagePrefixList = - GetPropertyAction.getProperty(contentPathProp, ""); + GetPropertyAction.privilegedGetProperty(contentPathProp, ""); if (packagePrefixList != "") { packagePrefixList += "|";
--- a/jdk/src/java.base/share/classes/java/net/URLEncoder.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/net/URLEncoder.java Wed May 11 00:38:26 2016 +0300 @@ -133,7 +133,7 @@ dontNeedEncoding.set('.'); dontNeedEncoding.set('*'); - dfltEncName = GetPropertyAction.getProperty("file.encoding"); + dfltEncName = GetPropertyAction.privilegedGetProperty("file.encoding"); } /**
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/AsynchronousChannelProvider.java Wed May 11 00:38:26 2016 +0300 @@ -94,9 +94,10 @@ if (cn == null) return null; try { - Class<?> c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); - return (AsynchronousChannelProvider)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()).newInstance(); + return (AsynchronousChannelProvider)tmp; } catch (ClassNotFoundException x) { throw new ServiceConfigurationError(null, x); } catch (IllegalAccessException x) {
--- a/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/nio/channels/spi/SelectorProvider.java Wed May 11 00:38:26 2016 +0300 @@ -95,9 +95,10 @@ if (cn == null) return false; try { - Class<?> c = Class.forName(cn, true, - ClassLoader.getSystemClassLoader()); - provider = (SelectorProvider)c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(cn, true, + ClassLoader.getSystemClassLoader()).newInstance(); + provider = (SelectorProvider)tmp; return true; } catch (ClassNotFoundException x) { throw new ServiceConfigurationError(null, x);
--- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java Wed May 11 00:38:26 2016 +0300 @@ -283,8 +283,8 @@ if (level == null) { if (!VM.isBooted()) return false; - bugLevel = level = - GetPropertyAction.getProperty("sun.nio.cs.bugLevel", ""); + bugLevel = level = GetPropertyAction + .privilegedGetProperty("sun.nio.cs.bugLevel", ""); } return level.equals(bl); } @@ -609,7 +609,8 @@ public static Charset defaultCharset() { if (defaultCharset == null) { synchronized (Charset.class) { - String csn = GetPropertyAction.getProperty("file.encoding"); + String csn = GetPropertyAction + .privilegedGetProperty("file.encoding"); Charset cs = lookup(csn); if (cs != null) defaultCharset = cs;
--- a/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/nio/file/TempFileHelper.java Wed May 11 00:38:26 2016 +0300 @@ -46,7 +46,7 @@ // temporary directory location private static final Path tmpdir = - Paths.get(GetPropertyAction.getProperty("java.io.tmpdir")); + Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir")); private static final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/jdk/src/java.base/share/classes/java/security/Policy.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/security/Policy.java Wed May 11 00:38:26 2016 +0300 @@ -222,8 +222,9 @@ public Policy run() { try { ClassLoader scl = ClassLoader.getSystemClassLoader(); - Class<?> c = Class.forName(policyProvider, true, scl); - return (Policy)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(policyProvider, true, scl).newInstance(); + return (Policy)o; } catch (Exception e) { if (debug != null) { debug.println("policy provider " + policyProvider +
--- a/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/time/zone/ZoneRulesProvider.java Wed May 11 00:38:26 2016 +0300 @@ -147,6 +147,7 @@ if (prop != null) { try { Class<?> c = Class.forName(prop, true, ClassLoader.getSystemClassLoader()); + @SuppressWarnings("deprecation") ZoneRulesProvider provider = ZoneRulesProvider.class.cast(c.newInstance()); registerProvider(provider); loaded.add(provider);
--- a/jdk/src/java.base/share/classes/java/util/Arrays.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java Wed May 11 00:38:26 2016 +0300 @@ -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/Locale.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/Locale.java Wed May 11 00:38:26 2016 +0300 @@ -858,7 +858,7 @@ private static Locale initDefault() { String language, region, script, country, variant; - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); language = props.getProperty("user.language", "en"); // for compatibility, check for old user.region property region = props.getProperty("user.region"); @@ -883,7 +883,7 @@ } private static Locale initDefault(Locale.Category category) { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); return getInstance( props.getProperty(category.languageKey, defaultLocale.getLanguage()),
--- a/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/PropertyResourceBundle.java Wed May 11 00:38:26 2016 +0300 @@ -140,9 +140,8 @@ // Check whether the strict encoding is specified. // The possible encoding is either "ISO-8859-1" or "UTF-8". - private static final String encoding = - GetPropertyAction - .getProperty("java.util.PropertyResourceBundle.encoding", "") + private static final String encoding = GetPropertyAction + .privilegedGetProperty("java.util.PropertyResourceBundle.encoding", "") .toUpperCase(Locale.ROOT); /**
--- a/jdk/src/java.base/share/classes/java/util/ServiceLoader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/ServiceLoader.java Wed May 11 00:38:26 2016 +0300 @@ -29,8 +29,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ModuleDescriptor.Provides; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Layer; @@ -85,7 +83,7 @@ * and deployed as a named module must have an appropriate <i>uses</i> clause * in its <i>module descriptor</i> to declare that the module uses * implementations of the service. A corresponding requirement is that a - * provider deployed as a named modules must have an appropriate + * provider deployed as a named module must have an appropriate * <i>provides</i> clause in its module descriptor to declare that the module * provides an implementation of the service. The <i>uses</i> and * <i>provides</i> allow consumers of a service to be <i>linked</i> to @@ -550,35 +548,29 @@ /** * Implements lazy service provider lookup of service providers that * are provided by modules in a module Layer. - * - * For now, this iterator examines all modules in each Layer. This will - * be replaced once we decide on how the service-use graph is exposed - * in the module API. */ private class LayerLookupIterator extends RestrictedIterator<S> { final String serviceName; Layer currentLayer; - Iterator<ModuleDescriptor> descriptorIterator; - Iterator<String> providersIterator; - - Module nextModule; - String nextProvider; + Iterator<ServiceProvider> iterator; + ServiceProvider nextProvider; LayerLookupIterator() { serviceName = service.getName(); currentLayer = layer; // need to get us started - descriptorIterator = descriptors(layer, serviceName); + iterator = providers(currentLayer, serviceName); } - Iterator<ModuleDescriptor> descriptors(Layer layer, String service) { - return layer.modules().stream() - .map(Module::getDescriptor) - .filter(d -> d.provides().get(service) != null) - .iterator(); + Iterator<ServiceProvider> providers(Layer layer, String service) { + ServicesCatalog catalog = SharedSecrets + .getJavaLangReflectModuleAccess() + .getServicesCatalog(layer); + + return catalog.findServices(serviceName).iterator(); } @Override @@ -591,30 +583,18 @@ while (true) { // next provider - if (providersIterator != null && providersIterator.hasNext()) { - nextProvider = providersIterator.next(); + if (iterator != null && iterator.hasNext()) { + nextProvider = iterator.next(); return true; } - // next descriptor - if (descriptorIterator.hasNext()) { - ModuleDescriptor descriptor = descriptorIterator.next(); - - nextModule = currentLayer.findModule(descriptor.name()).get(); - - Provides provides = descriptor.provides().get(serviceName); - providersIterator = provides.providers().iterator(); - - continue; - } - // next layer Layer parent = currentLayer.parent().orElse(null); if (parent == null) return false; currentLayer = parent; - descriptorIterator = descriptors(currentLayer, serviceName); + iterator = providers(currentLayer, serviceName); } } @@ -623,13 +603,14 @@ if (!hasNextService()) throw new NoSuchElementException(); - assert nextModule != null && nextProvider != null; - - String cn = nextProvider; + ServiceProvider provider = nextProvider; nextProvider = null; + Module module = provider.module(); + String cn = provider.providerName(); + // attempt to load the provider - Class<?> c = loadClassInModule(nextModule, cn); + Class<?> c = loadClassInModule(module, cn); if (c == null) fail(service, "Provider " + cn + " not found"); if (!service.isAssignableFrom(c)) @@ -830,7 +811,9 @@ } S p = null; try { - p = service.cast(c.newInstance()); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + p = service.cast(tmp); } catch (Throwable x) { fail(service, "Provider " + cn + " could not be instantiated",
--- a/jdk/src/java.base/share/classes/java/util/TimeZone.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/TimeZone.java Wed May 11 00:38:26 2016 +0300 @@ -42,6 +42,7 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.time.ZoneId; +import java.util.Properties; import sun.security.action.GetPropertyAction; import sun.util.calendar.ZoneInfo; import sun.util.calendar.ZoneInfoFile; @@ -660,12 +661,13 @@ private static synchronized TimeZone setDefaultZone() { TimeZone tz; // get the time zone ID from the system properties - String zoneID = GetPropertyAction.getProperty("user.timezone"); + Properties props = GetPropertyAction.privilegedGetProperties(); + String zoneID = props.getProperty("user.timezone"); // if the time zone ID is not set (yet), perform the // platform to Java time zone ID mapping. if (zoneID == null || zoneID.isEmpty()) { - String javaHome = GetPropertyAction.getProperty("java.home"); + String javaHome = props.getProperty("java.home"); try { zoneID = getSystemTimeZoneID(javaHome); if (zoneID == null) { @@ -693,13 +695,7 @@ assert tz != null; final String id = zoneID; - AccessController.doPrivileged(new PrivilegedAction<>() { - @Override - public Void run() { - System.setProperty("user.timezone", id); - return null; - } - }); + props.setProperty("user.timezone", id); defaultTimeZone = tz; return tz;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java Wed May 11 00:38:26 2016 +0300 @@ -3507,6 +3507,7 @@ * Creates and returns the common pool, respecting user settings * specified via system properties. */ + @SuppressWarnings("deprecation") // Class.newInstance static ForkJoinPool makeCommonPool() { int parallelism = -1; ForkJoinWorkerThreadFactory factory = null;
--- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java Wed May 11 00:38:26 2016 +0300 @@ -155,7 +155,7 @@ BASE_VERSION = 8; // one less than lowest version for versioned entries int runtimeVersion = jdk.Version.current().major(); String jarVersion = - GetPropertyAction.getProperty("jdk.util.jar.version"); + GetPropertyAction.privilegedGetProperty("jdk.util.jar.version"); if (jarVersion != null) { int jarVer = Integer.parseInt(jarVersion); runtimeVersion = (jarVer > runtimeVersion) @@ -163,7 +163,7 @@ } RUNTIME_VERSION = runtimeVersion; String enableMultiRelease = GetPropertyAction - .getProperty("jdk.util.jar.enableMultiRelease", "true"); + .privilegedGetProperty("jdk.util.jar.enableMultiRelease", "true"); switch (enableMultiRelease) { case "true": default: @@ -658,6 +658,28 @@ return vze == null ? ze : vze; } + /** + * Returns the real name of a {@code JarEntry}. If this {@code JarFile} is + * a multi-release jar file and is configured to be processed as such, the + * name returned by this method is the path name of the versioned entry + * that the {@code JarEntry} represents, rather than the path name of the + * base entry that {@link JarEntry#getName()} returns. If the + * {@code JarEntry} does not represent a versioned entry, or the + * jar file is not a multi-release jar file or {@code JarFile} is not + * configured for processing a multi-release jar file, this method returns + * the same name that {@link JarEntry#getName()} returns. + * + * @param entry the JarEntry + * @return the real name of the JarEntry + * @since 9 + */ + String getRealName(JarEntry entry) { + if (entry instanceof JarFileEntry) { + return ((JarFileEntry)entry).realName(); + } + return entry.getName(); + } + private class JarFileEntry extends JarEntry { final private String name; @@ -684,7 +706,7 @@ throw new RuntimeException(e); } if (certs == null && jv != null) { - certs = jv.getCerts(JarFile.this, reifiedEntry()); + certs = jv.getCerts(JarFile.this, realEntry()); } return certs == null ? null : certs.clone(); } @@ -695,17 +717,20 @@ throw new RuntimeException(e); } if (signers == null && jv != null) { - signers = jv.getCodeSigners(JarFile.this, reifiedEntry()); + signers = jv.getCodeSigners(JarFile.this, realEntry()); } return signers == null ? null : signers.clone(); } - JarFileEntry reifiedEntry() { + JarFileEntry realEntry() { if (isMultiRelease()) { String entryName = super.getName(); return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); } return this; } + String realName() { + return super.getName(); + } @Override public String getName() { @@ -876,11 +901,11 @@ private JarEntry verifiableEntry(ZipEntry ze) { if (ze instanceof JarFileEntry) { // assure the name and entry match for verification - return ((JarFileEntry)ze).reifiedEntry(); + return ((JarFileEntry)ze).realEntry(); } ze = getJarEntry(ze.getName()); if (ze instanceof JarFileEntry) { - return ((JarFileEntry)ze).reifiedEntry(); + return ((JarFileEntry)ze).realEntry(); } return (JarEntry)ze; }
--- a/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/jar/JavaUtilJarAccessImpl.java Wed May 11 00:38:26 2016 +0300 @@ -60,4 +60,8 @@ public List<Object> getManifestDigests(JarFile jar) { return jar.getManifestDigests(); } + + public String getRealName(JarFile jar, JarEntry entry) { + return jar.getRealName(entry); + } }
--- a/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/jar/Pack200.java Wed May 11 00:38:26 2016 +0300 @@ -695,7 +695,7 @@ Class<?> impl = (PACK_PROVIDER.equals(prop))? packerImpl: unpackerImpl; if (impl == null) { // The first time, we must decide which class to use. - implName = GetPropertyAction.getProperty(prop,""); + implName = GetPropertyAction.privilegedGetProperty(prop,""); if (implName != null && !implName.equals("")) impl = Class.forName(implName); else if (PACK_PROVIDER.equals(prop)) @@ -704,7 +704,9 @@ impl = com.sun.java.util.jar.pack.UnpackerImpl.class; } // We have a class. Now instantiate it. - return impl.newInstance(); + @SuppressWarnings("deprecation") + Object result = impl.newInstance(); + return result; } catch (ClassNotFoundException e) { throw new Error("Class not found: " + implName + ":\ncheck property " + prop +
--- a/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/regex/PatternSyntaxException.java Wed May 11 00:38:26 2016 +0300 @@ -94,7 +94,7 @@ } private static final String nl = - GetPropertyAction.getProperty("line.separator"); + GetPropertyAction.privilegedGetProperty("line.separator"); /** * Returns a multi-line string containing the description of the syntax
--- a/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/stream/DoublePipeline.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/stream/IntPipeline.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/stream/LongPipeline.java Wed May 11 00:38:26 2016 +0300 @@ -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 Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/stream/StreamSpliterators.java Wed May 11 00:38:26 2016 +0300 @@ -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/java/util/zip/ZipOutputStream.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/util/zip/ZipOutputStream.java Wed May 11 00:38:26 2016 +0300 @@ -55,7 +55,7 @@ */ private static final boolean inhibitZip64 = Boolean.parseBoolean( - GetPropertyAction.getProperty("jdk.util.zip.inhibitZip64")); + GetPropertyAction.privilegedGetProperty("jdk.util.zip.inhibitZip64")); private static class XEntry { final ZipEntry entry;
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLServerSocketFactory.java Wed May 11 00:38:26 2016 +0300 @@ -97,6 +97,7 @@ } } log("class " + clsName + " is loaded"); + @SuppressWarnings("deprecation") SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance(); log("instantiated an instance of class " + clsName); theFactory = fac;
--- a/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/javax/net/ssl/SSLSocketFactory.java Wed May 11 00:38:26 2016 +0300 @@ -51,7 +51,7 @@ static final boolean DEBUG; static { - String s = GetPropertyAction.getProperty("javax.net.debug", "") + String s = GetPropertyAction.privilegedGetProperty("javax.net.debug", "") .toLowerCase(Locale.ENGLISH); DEBUG = s.contains("all") || s.contains("ssl"); @@ -106,6 +106,7 @@ } } log("class " + clsName + " is loaded"); + @SuppressWarnings("deprecation") SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance(); log("instantiated an instance of class " + clsName); theFactory = fac;
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/javax/security/auth/login/Configuration.java Wed May 11 00:38:26 2016 +0300 @@ -250,7 +250,9 @@ finalClass, false, Thread.currentThread().getContextClassLoader() ).asSubclass(Configuration.class); - return implClass.newInstance(); + @SuppressWarnings("deprecation") + Configuration result = implClass.newInstance(); + return result; } }); AccessController.doPrivileged(
--- a/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/javax/security/auth/login/LoginContext.java Wed May 11 00:38:26 2016 +0300 @@ -304,7 +304,9 @@ Class<? extends CallbackHandler> c = Class.forName( defaultHandler, true, finalLoader).asSubclass(CallbackHandler.class); - return c.newInstance(); + @SuppressWarnings("deprecation") + CallbackHandler result = c.newInstance(); + return result; } }); } catch (java.security.PrivilegedActionException pae) { @@ -697,8 +699,9 @@ if (moduleStack[i].module == null) { try { - moduleStack[i].module = (LoginModule) Class.forName( - name, false, contextClassLoader).newInstance(); + @SuppressWarnings("deprecation") + Object tmp = Class.forName(name, false, contextClassLoader).newInstance(); + moduleStack[i].module = (LoginModule) tmp; if (debug != null) { debug.println(name + " loaded via reflection"); }
--- a/jdk/src/java.base/share/classes/jdk/Version.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/Version.java Wed May 11 00:38:26 2016 +0300 @@ -273,7 +273,8 @@ */ public static Version current() { if (current == null) { - current = parse(GetPropertyAction.getProperty("java.version")); + current = parse( + GetPropertyAction.privilegedGetProperty("java.version")); } return current; }
--- a/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/jrtfs/JrtFileSystemProvider.java Wed May 11 00:38:26 2016 +0300 @@ -124,7 +124,9 @@ ClassLoader cl = newJrtFsLoader(jrtfs); try { Class<?> c = Class.forName(JrtFileSystemProvider.class.getName(), false, cl); - return ((FileSystemProvider)c.newInstance()).newFileSystem(uri, newEnv); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + return ((FileSystemProvider)tmp).newFileSystem(uri, newEnv); } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Wed May 11 00:38:26 2016 +0300 @@ -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 @@ -68,7 +68,7 @@ } // ServiceCatalog for the boot class loader - private static final ServicesCatalog SERVICES_CATALOG = new ServicesCatalog(); + private static final ServicesCatalog SERVICES_CATALOG = ServicesCatalog.create(); // ClassLoaderValue map for boot class loader private static final ConcurrentHashMap<?, ?> CLASS_LOADER_VALUE_MAP =
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/BuiltinClassLoader.java Wed May 11 00:38:26 2016 +0300 @@ -104,7 +104,7 @@ * A module defined/loaded by a built-in class loader. * * A LoadedModule encapsulates a ModuleReference along with its CodeSource - * URL to avoid needing to create this URL when define classes. + * URL to avoid needing to create this URL when defining classes. */ private static class LoadedModule { private final BuiltinClassLoader loader;
--- a/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java Wed May 11 00:38:26 2016 +0300 @@ -85,7 +85,7 @@ private static final boolean DISABLE_JAR_CHECKING; static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); JAVA_VERSION = props.getProperty("java.version"); DEBUG = (props.getProperty("sun.misc.URLClassPath.debug") != null); String p = props.getProperty("sun.misc.URLClassPath.disableJarChecking"); @@ -372,9 +372,15 @@ return java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<>() { public Loader run() throws IOException { + String protocol = url.getProtocol(); // lower cased in URL String file = url.getFile(); - if (file != null && file.endsWith("/")) { - if ("file".equals(url.getProtocol())) { + if ("jar".equals(protocol) + && file != null && (file.indexOf("!/") == file.length() - 2)) { + // extract the nested URL + URL nestedUrl = new URL(file.substring(0, file.length() - 2)); + return new JarLoader(nestedUrl, jarHandler, lmap); + } else if (file != null && file.endsWith("/")) { + if ("file".equals(protocol)) { return new FileLoader(url); } else { return new Loader(url); @@ -718,13 +724,13 @@ final URL url; try { + String nm; if (jar.isMultiRelease()) { - // add #runtime fragment to tell JarURLConnection to use - // runtime versioning if the underlying jar file is multi-release - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); + nm = SharedSecrets.javaUtilJarAccess().getRealName(jar, entry); } else { - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + nm = name; } + url = new URL(getBaseURL(), ParseUtil.encodePath(nm, false)); if (check) { URLClassPath.check(url); } @@ -940,7 +946,8 @@ ensureOpen(); - if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { // Only get manifest when necessary + // Only get manifest when necessary + if (SharedSecrets.javaUtilJarAccess().jarFileHasClassPathAttribute(jar)) { Manifest man = jar.getManifest(); if (man != null) { Attributes attr = man.getMainAttributes();
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/LoggerFinderLoader.java Wed May 11 00:38:26 2016 +0300 @@ -81,7 +81,7 @@ // Get configuration error policy private static ErrorPolicy configurationErrorPolicy() { String errorPolicy = - GetPropertyAction.getProperty("jdk.logger.finder.error"); + GetPropertyAction.privilegedGetProperty("jdk.logger.finder.error"); if (errorPolicy == null || errorPolicy.isEmpty()) { return ErrorPolicy.WARNING; } @@ -96,7 +96,7 @@ // This is further submitted to the configuration error policy. private static boolean ensureSingletonProvider() { return Boolean.parseBoolean( - GetPropertyAction.getProperty("jdk.logger.finder.singleton")); + GetPropertyAction.privilegedGetProperty("jdk.logger.finder.singleton")); } private static Iterator<System.LoggerFinder> findLoggerFinderProviders() {
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Wed May 11 00:38:26 2016 +0300 @@ -56,7 +56,7 @@ static Level getDefaultLevel() { String levelName = GetPropertyAction - .getProperty("jdk.system.logger.level", "INFO"); + .privilegedGetProperty("jdk.system.logger.level", "INFO"); try { return Level.valueOf(levelName); } catch (IllegalArgumentException iae) { @@ -426,7 +426,7 @@ static private final String[] skips; static { String additionalPkgs = - GetPropertyAction.getProperty("jdk.logger.packages"); + GetPropertyAction.privilegedGetProperty("jdk.logger.packages"); skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(","); } @@ -485,7 +485,7 @@ // jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java // to fail - because that test has a testcase which somehow references // PlatformLogger and counts the number of generated lambda classes. - String format = GetPropertyAction.getProperty(key); + String format = GetPropertyAction.privilegedGetProperty(key); if (format == null && defaultPropertyGetter != null) { format = defaultPropertyGetter.apply(key);
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangModuleAccess.java Wed May 11 00:38:26 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,13 +25,24 @@ package jdk.internal.misc; +import java.io.PrintStream; +import java.lang.module.Configuration; +import jdk.internal.module.ModuleHashes; + import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Exports; import java.lang.module.ModuleDescriptor.Requires; import java.lang.module.ModuleDescriptor.Provides; import java.lang.module.ModuleDescriptor.Version; +import java.lang.module.ModuleFinder; +import java.util.Collection; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.net.URI; import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.function.Supplier; /** * Provides access to non-public methods in java.lang.module. @@ -89,5 +100,29 @@ String osArch, String osVersion, Set<String> conceals, - Set<String> packages); + Set<String> packages, + ModuleHashes hashes); + + /** + * Resolves a collection of root modules, with service binding + * and the empty configuration as the parent. The post resolution + * checks are optionally run. + */ + Configuration resolveRequiresAndUses(ModuleFinder finder, + Collection<String> roots, + boolean check, + PrintStream traceOutput); + + /** + * Creates a ModuleReference to a "patched" module. + */ + ModuleReference newPatchedModule(ModuleDescriptor descriptor, + URI location, + Supplier<ModuleReader> readerSupplier); + + /** + * Returns the object with the hashes of other modules + */ + Optional<ModuleHashes> hashes(ModuleDescriptor descriptor); + }
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaLangReflectModuleAccess.java Wed May 11 00:38:26 2016 +0300 @@ -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 @@ -26,9 +26,12 @@ package jdk.internal.misc; import java.lang.module.ModuleDescriptor; +import java.lang.reflect.Layer; import java.lang.reflect.Module; import java.net.URI; +import jdk.internal.module.ServicesCatalog; + /** * Provides access to non-public methods in java.lang.reflect.Module */ @@ -57,6 +60,11 @@ void addReads(Module m1, Module m2); /** + * Updates module m to read all unnamed modules. + */ + void addReadsAllUnnamed(Module m); + + /** * Updates module m1 to export a package to module m2. The export does * not result in a strong reference to m2 (m2 can be GC'ed). */ @@ -76,4 +84,10 @@ * Add a package to the given module. */ void addPackage(Module m, String pkg); -} + + /** + * Returns the ServicesCatalog for the given Layer. + */ + ServicesCatalog getServicesCatalog(Layer layer); + +} \ No newline at end of file
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/JavaUtilJarAccess.java Wed May 11 00:38:26 2016 +0300 @@ -41,4 +41,5 @@ public Enumeration<JarEntry> entries2(JarFile jar); public void setEagerValidation(JarFile jar, boolean eager); public List<Object> getManifestDigests(JarFile jar); + public String getRealName(JarFile jar, JarEntry entry); }
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed May 11 00:38:26 2016 +0300 @@ -33,6 +33,7 @@ import jdk.internal.misc.VM; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.vm.annotation.ForceInline; /** @@ -209,46 +210,103 @@ /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native boolean getBoolean(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putBoolean(Object o, long offset, boolean x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native byte getByte(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putByte(Object o, long offset, byte x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native short getShort(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putShort(Object o, long offset, short x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native char getChar(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putChar(Object o, long offset, char x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native long getLong(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putLong(Object o, long offset, long x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native float getFloat(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putFloat(Object o, long offset, float x); + /** @see #getInt(Object, long) */ @HotSpotIntrinsicCandidate public native double getDouble(Object o, long offset); + /** @see #putInt(Object, long, int) */ @HotSpotIntrinsicCandidate public native void putDouble(Object o, long offset, double x); + /** + * Fetches a native pointer from a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>If the native pointer is less than 64 bits wide, it is extended as + * an unsigned number to a Java long. The pointer may be indexed by any + * given byte offset, simply by adding that offset (as a simple integer) to + * the long representing the pointer. The number of bytes actually read + * from the target address may be determined by consulting {@link + * #addressSize}. + * + * @see #allocateMemory + * @see #getInt(Object, long) + */ + @ForceInline + public long getAddress(Object o, long offset) { + if (ADDRESS_SIZE == 4) { + return Integer.toUnsignedLong(getInt(o, offset)); + } else { + return getLong(o, offset); + } + } + + /** + * Stores a native pointer into a given memory address. If the address is + * zero, or does not point into a block obtained from {@link + * #allocateMemory}, the results are undefined. + * + * <p>The number of bytes actually written at the target address may be + * determined by consulting {@link #addressSize}. + * + * @see #allocateMemory + * @see #putInt(Object, long, int) + */ + @ForceInline + public void putAddress(Object o, long offset, long x) { + if (ADDRESS_SIZE == 4) { + putInt(o, offset, (int)x); + } else { + putLong(o, offset, x); + } + } + // These read VM internal data. /** @@ -287,8 +345,10 @@ * * @see #allocateMemory */ - @HotSpotIntrinsicCandidate - public native byte getByte(long address); + @ForceInline + public byte getByte(long address) { + return getByte(null, address); + } /** * Stores a value into a given memory address. If the address is zero, or @@ -297,75 +357,94 @@ * * @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native void putByte(long address, byte x); + @ForceInline + public void putByte(long address, byte x) { + putByte(null, address, x); + } /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native short getShort(long address); + @ForceInline + public short getShort(long address) { + return getShort(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putShort(long address, short x); + @ForceInline + public void putShort(long address, short x) { + putShort(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native char getChar(long address); + @ForceInline + public char getChar(long address) { + return getChar(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putChar(long address, char x); + @ForceInline + public void putChar(long address, char x) { + putChar(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native int getInt(long address); + @ForceInline + public int getInt(long address) { + return getInt(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putInt(long address, int x); + @ForceInline + public void putInt(long address, int x) { + putInt(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native long getLong(long address); + @ForceInline + public long getLong(long address) { + return getLong(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putLong(long address, long x); + @ForceInline + public void putLong(long address, long x) { + putLong(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native float getFloat(long address); + @ForceInline + public float getFloat(long address) { + return getFloat(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putFloat(long address, float x); + @ForceInline + public void putFloat(long address, float x) { + putFloat(null, address, x); + } + /** @see #getByte(long) */ - @HotSpotIntrinsicCandidate - public native double getDouble(long address); + @ForceInline + public double getDouble(long address) { + return getDouble(null, address); + } + /** @see #putByte(long, byte) */ - @HotSpotIntrinsicCandidate - public native void putDouble(long address, double x); + @ForceInline + public void putDouble(long address, double x) { + putDouble(null, address, x); + } - /** - * Fetches a native pointer from a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - * <p>If the native pointer is less than 64 bits wide, it is extended as - * an unsigned number to a Java long. The pointer may be indexed by any - * given byte offset, simply by adding that offset (as a simple integer) to - * the long representing the pointer. The number of bytes actually read - * from the target address may be determined by consulting {@link - * #addressSize}. - * - * @see #allocateMemory - */ - @HotSpotIntrinsicCandidate - public native long getAddress(long address); + /** @see #getAddress(Object, long) */ + @ForceInline + public long getAddress(long address) { + return getAddress(null, address); + } - /** - * Stores a native pointer into a given memory address. If the address is - * zero, or does not point into a block obtained from {@link - * #allocateMemory}, the results are undefined. - * - * <p>The number of bytes actually written at the target address may be - * determined by consulting {@link #addressSize}. - * - * @see #getAddress(long) - */ - @HotSpotIntrinsicCandidate - public native void putAddress(long address, long x); + /** @see #putAddress(Object, long, long) */ + @ForceInline + public void putAddress(long address, long x) { + putAddress(null, address, x); + }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/Builder.java Wed May 11 00:38:26 2016 +0300 @@ -74,6 +74,8 @@ String osName; String osArch; String osVersion; + String algorithm; + Map<String, String> hashes; Builder(String name, int reqs, int exports, int provides, int conceals, int packages) { @@ -252,6 +254,25 @@ } /** + * Sets the algorithm of the module hashes + */ + public Builder algorithm(String algorithm) { + this.algorithm = algorithm; + return this; + } + + /** + * Sets the module hash for the given module name + */ + public Builder moduleHash(String mn, String hash) { + if (hashes == null) + hashes = new HashMap<>(); + + hashes.put(mn, hash); + return this; + } + + /** * Returns the set of packages that is the union of the exported and * concealed packages. */ @@ -273,6 +294,9 @@ public ModuleDescriptor build() { assert name != null; + ModuleHashes moduleHashes = + hashes != null ? new ModuleHashes(algorithm, hashes) : null; + return jlma.newModuleDescriptor(name, false, // automatic false, // assume not synthetic for now @@ -286,6 +310,7 @@ osArch, osVersion, conceals, - computePackages(exports, conceals)); + computePackages(exports, conceals), + moduleHashes); } }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ClassFileAttributes.java Wed May 11 00:38:26 2016 +0300 @@ -34,6 +34,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -42,7 +43,6 @@ import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.module.Hasher.DependencyHashes; import static jdk.internal.module.ClassFileConstants.*; @@ -148,7 +148,7 @@ for (int i=0; i<provides_count; i++) { String sn = cr.readClass(off, buf).replace('/', '.'); String cn = cr.readClass(off + 2, buf).replace('/', '.'); - provides.computeIfAbsent(sn, k -> new HashSet<>()).add(cn); + provides.computeIfAbsent(sn, k -> new LinkedHashSet<>()).add(cn); off += 4; } provides.entrySet().forEach(e -> builder.provides(e.getKey(), @@ -281,10 +281,10 @@ * u4 attribute_length; * * // the number of entries in the packages table - * u2 package_count; + * u2 packages_count; * { // index to CONSTANT_CONSTANT_utf8_info structure with the package name * u2 package_index - * } package[package_count]; + * } packages[package_count]; * * }</pre> */ @@ -579,9 +579,9 @@ * alternative is to store it as an array of u1. */ static class HashesAttribute extends Attribute { - private final DependencyHashes hashes; + private final ModuleHashes hashes; - HashesAttribute(DependencyHashes hashes) { + HashesAttribute(ModuleHashes hashes) { super(HASHES); this.hashes = hashes; } @@ -613,7 +613,7 @@ map.put(dn, hash); } - DependencyHashes hashes = new DependencyHashes(algorithm, map); + ModuleHashes hashes = new ModuleHashes(algorithm, map); return new HashesAttribute(hashes); }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Hasher.java Fri May 06 19:35:34 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.internal.module; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -/** - * Supporting class for computing, encoding and decoding hashes (message - * digests). - */ - -public class Hasher { - private Hasher() { } - - /** - * A supplier of an encoded message digest. - */ - public static interface HashSupplier { - String generate(String algorithm); - } - - /** - * Encapsulates the result of hashing the contents of a number of module - * artifacts. - */ - public static class DependencyHashes { - private final String algorithm; - private final Map<String, String> nameToHash; - - public DependencyHashes(String algorithm, Map<String, String> nameToHash) { - this.algorithm = algorithm; - this.nameToHash = nameToHash; - } - - /** - * Returns the algorithm used to hash the dependences ("SHA-256" or - * "MD5" for example). - */ - public String algorithm() { - return algorithm; - } - - /** - * Returns the set of module names for which hashes are recorded. - */ - public Set<String> names() { - return nameToHash.keySet(); - } - - /** - * Retruns the hash string for the given module name, {@code null} - * if there is no hash recorded for the module. - */ - public String hashFor(String dn) { - return nameToHash.get(dn); - } - } - - - /** - * Computes the hash for the given file with the given message digest - * algorithm. Returns the results a base64-encoded String. - * - * @throws UncheckedIOException if an I/O error occurs - * @throws RuntimeException if the algorithm is not available - */ - public static String generate(Path file, String algorithm) { - try { - MessageDigest md = MessageDigest.getInstance(algorithm); - - // Ideally we would just mmap the file but this consumes too much - // memory when jlink is running concurrently on very large jmods - try (FileChannel fc = FileChannel.open(file)) { - ByteBuffer bb = ByteBuffer.allocate(32*1024); - int nread; - while ((nread = fc.read(bb)) > 0) { - bb.flip(); - md.update(bb); - assert bb.remaining() == 0; - bb.clear(); - } - } - - byte[] bytes = md.digest(); - return Base64.getEncoder().encodeToString(bytes); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (IOException ioe) { - throw new UncheckedIOException(ioe); - } - } - - /** - * Computes the hash for every entry in the given map, returning a - * {@code DependencyHashes} to encapsulate the result. The map key is - * the entry name, typically the module name. The map value is the file - * path to the entry (module artifact). - * - * @return DependencyHashes encapsulate the hashes - */ - public static DependencyHashes generate(Map<String, Path> map, String algorithm) { - Map<String, String> nameToHash = new HashMap<>(); - for (Map.Entry<String, Path> entry: map.entrySet()) { - String name = entry.getKey(); - Path path = entry.getValue(); - nameToHash.put(name, generate(path, algorithm)); - } - return new DependencyHashes(algorithm, nameToHash); - } -}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java Wed May 11 00:38:26 2016 +0300 @@ -26,12 +26,15 @@ package jdk.internal.module; import java.io.File; +import java.io.PrintStream; import java.lang.module.Configuration; +import java.lang.module.ModuleDescriptor; +import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; -import java.lang.module.ModuleFinder; import java.lang.module.ResolvedModule; import java.lang.reflect.Layer; import java.lang.reflect.Module; +import java.net.URI; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; @@ -41,10 +44,10 @@ import java.util.Optional; import java.util.Set; import java.util.function.Function; -import java.util.stream.Collectors; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; +import jdk.internal.misc.SharedSecrets; import jdk.internal.perf.PerfCounter; /** @@ -54,10 +57,9 @@ * the module system. In summary, the boot method creates a Configuration by * resolving a set of module names specified via the launcher (or equivalent) * -m and -addmods options. The modules are located on a module path that is - * constructed from the upgrade, system and application module paths. The - * Configuration is reified by creating the boot Layer with each module in the - * the configuration defined to one of the built-in class loaders. The mapping - * of modules to class loaders is statically mapped in a helper class. + * constructed from the upgrade module path, system modules, and application + * module path. The Configuration is instantiated as the boot Layer with each + * module in the the configuration defined to one of the built-in class loaders. */ public final class ModuleBootstrap { @@ -65,6 +67,11 @@ private static final String JAVA_BASE = "java.base"; + private static final String JAVA_SE = "java.se"; + + // the token for "all default modules" + private static final String ALL_DEFAULT = "ALL-DEFAULT"; + // the token for "all unnamed modules" private static final String ALL_UNNAMED = "ALL-UNNAMED"; @@ -94,47 +101,65 @@ long t0 = System.nanoTime(); - // system module path - ModuleFinder systemModulePath = ModuleFinder.ofSystem(); + // system modules + ModuleFinder systemModules = ModuleFinder.ofSystem(); - // Once we have the system module path then we define the base module. - // We do this here so that java.base is defined to the VM as early as + PerfCounters.systemModulesTime.addElapsedTimeFrom(t0); + + + long t1 = System.nanoTime(); + + // Once we have the system modules then we define the base module to + // the VM. We do this here so that java.base is defined as early as // possible and also that resources in the base module can be located // for error messages that may happen from here on. - Optional<ModuleReference> obase = systemModulePath.find(JAVA_BASE); - if (!obase.isPresent()) + ModuleReference base = systemModules.find(JAVA_BASE).orElse(null); + if (base == null) throw new InternalError(JAVA_BASE + " not found"); - ModuleReference base = obase.get(); + URI baseUri = base.location().orElse(null); + if (baseUri == null) + throw new InternalError(JAVA_BASE + " does not have a location"); BootLoader.loadModule(base); - Modules.defineModule(null, base.descriptor(), base.location().orElse(null)); + Modules.defineModule(null, base.descriptor(), baseUri); + PerfCounters.defineBaseTime.addElapsedTimeFrom(t1); + + + long t2 = System.nanoTime(); // -upgrademodulepath option specified to launcher ModuleFinder upgradeModulePath = createModulePathFinder("jdk.upgrade.module.path"); + if (upgradeModulePath != null) + systemModules = ModuleFinder.compose(upgradeModulePath, systemModules); // -modulepath option specified to the launcher ModuleFinder appModulePath = createModulePathFinder("jdk.module.path"); - // The module finder: [-upgrademodulepath] system-module-path [-modulepath] - ModuleFinder finder = systemModulePath; - if (upgradeModulePath != null) - finder = ModuleFinder.compose(upgradeModulePath, finder); + // The module finder: [-upgrademodulepath] system [-modulepath] + ModuleFinder finder = systemModules; if (appModulePath != null) finder = ModuleFinder.compose(finder, appModulePath); - // launcher -m option to specify the initial module + // The root modules to resolve + Set<String> roots = new HashSet<>(); + + // launcher -m option to specify the main/initial module String mainModule = System.getProperty("jdk.module.main"); + if (mainModule != null) + roots.add(mainModule); // additional module(s) specified by -addmods + boolean addAllDefaultModules = false; boolean addAllSystemModules = false; boolean addAllApplicationModules = false; - Set<String> addModules = null; String propValue = System.getProperty("jdk.launcher.addmods"); if (propValue != null) { - addModules = new HashSet<>(); for (String mod: propValue.split(",")) { switch (mod) { + case ALL_DEFAULT: + addAllDefaultModules = true; + break; case ALL_SYSTEM: addAllSystemModules = true; break; @@ -142,28 +167,12 @@ addAllApplicationModules = true; break; default : - addModules.add(mod); + roots.add(mod); } } } - // The root modules to resolve - Set<String> roots = new HashSet<>(); - - // main/initial module - if (mainModule != null) { - roots.add(mainModule); - if (addAllApplicationModules) - fail(ALL_MODULE_PATH + " not allowed with initial module"); - } - - // If -addmods is specified then those modules need to be resolved - if (addModules != null) - roots.addAll(addModules); - - // -limitmods - boolean limitmods = false; propValue = System.getProperty("jdk.launcher.limitmods"); if (propValue != null) { Set<String> mods = new HashSet<>(); @@ -171,62 +180,101 @@ mods.add(mod); } finder = limitFinder(finder, mods, roots); - limitmods = true; } - - // If there is no initial module specified then assume that the - // initial module is the unnamed module of the application class - // loader. By convention, and for compatibility, this is - // implemented by putting the names of all modules on the system - // module path into the set of modules to resolve. - // - // If `-addmods ALL-SYSTEM` is used then all modules on the system - // module path will be resolved, irrespective of whether an initial - // module is specified. - // - // If `-addmods ALL-MODULE-PATH` is used, and no initial module is - // specified, then all modules on the application module path will - // be resolved. - // - if (mainModule == null || addAllSystemModules) { - Set<ModuleReference> mrefs; - if (addAllApplicationModules) { - assert mainModule == null; - mrefs = finder.findAll(); - } else { - mrefs = systemModulePath.findAll(); - if (limitmods) { - ModuleFinder f = finder; - mrefs = mrefs.stream() - .filter(m -> f.find(m.descriptor().name()).isPresent()) - .collect(Collectors.toSet()); + // If there is no initial module specified then assume that the initial + // module is the unnamed module of the application class loader. This + // is implemented by resolving "java.se" and all (non-java.*) modules + // that export an API. If "java.se" is not observable then all java.* + // modules are resolved. + if (mainModule == null || addAllDefaultModules) { + boolean hasJava = false; + if (systemModules.find(JAVA_SE).isPresent()) { + // java.se is a system module + if (finder == systemModules || finder.find(JAVA_SE).isPresent()) { + // java.se is observable + hasJava = true; + roots.add(JAVA_SE); } } - // map to module names - for (ModuleReference mref : mrefs) { - roots.add(mref.descriptor().name()); + + for (ModuleReference mref : systemModules.findAll()) { + String mn = mref.descriptor().name(); + if (hasJava && mn.startsWith("java.")) + continue; + + // add as root if observable and exports at least one package + if ((finder == systemModules || finder.find(mn).isPresent())) { + ModuleDescriptor descriptor = mref.descriptor(); + for (ModuleDescriptor.Exports e : descriptor.exports()) { + if (!e.isQualified()) { + roots.add(mn); + break; + } + } + } } } - long t1 = System.nanoTime(); + // If `-addmods ALL-SYSTEM` is specified then all observable system + // modules will be resolved. + if (addAllSystemModules) { + ModuleFinder f = finder; // observable modules + systemModules.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(mn -> f.find(mn).isPresent()) // observable + .forEach(mn -> roots.add(mn)); + } + + // If `-addmods ALL-MODULE-PATH` is specified then all observable + // modules on the application module path will be resolved. + if (appModulePath != null && addAllApplicationModules) { + ModuleFinder f = finder; // observable modules + appModulePath.findAll() + .stream() + .map(ModuleReference::descriptor) + .map(ModuleDescriptor::name) + .filter(mn -> f.find(mn).isPresent()) // observable + .forEach(mn -> roots.add(mn)); + } + + PerfCounters.optionsAndRootsTime.addElapsedTimeFrom(t2); + + + long t3 = System.nanoTime(); + + // determine if post resolution checks are needed + boolean needPostResolutionChecks = true; + if (baseUri.getScheme().equals("jrt") // toLowerCase not needed here + && (upgradeModulePath == null) + && (appModulePath == null) + && (System.getProperty("jdk.launcher.patch.0") == null)) { + needPostResolutionChecks = false; + } + + PrintStream traceOutput = null; + if (Boolean.getBoolean("jdk.launcher.traceResolver")) + traceOutput = System.out; // run the resolver to create the configuration - - Configuration cf = Configuration.empty() + Configuration cf = SharedSecrets.getJavaLangModuleAccess() .resolveRequiresAndUses(finder, - ModuleFinder.empty(), - roots); + roots, + needPostResolutionChecks, + traceOutput); // time to create configuration - PerfCounters.resolveTime.addElapsedTimeFrom(t1); + PerfCounters.resolveTime.addElapsedTimeFrom(t3); + // mapping of modules to class loaders Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf); // check that all modules to be mapped to the boot loader will be - // loaded from the system module path - if (finder != systemModulePath) { + // loaded from the runtime image + if (needPostResolutionChecks) { for (ResolvedModule resolvedModule : cf.modules()) { ModuleReference mref = resolvedModule.reference(); String name = mref.descriptor().name(); @@ -237,20 +285,22 @@ && upgradeModulePath.find(name).isPresent()) fail(name + ": cannot be loaded from upgrade module path"); - if (!systemModulePath.find(name).isPresent()) + if (!systemModules.find(name).isPresent()) fail(name + ": cannot be loaded from application module path"); } } } - long t2 = System.nanoTime(); + + long t4 = System.nanoTime(); // define modules to VM/runtime Layer bootLayer = Layer.empty().defineModules(cf, clf); - PerfCounters.layerCreateTime.addElapsedTimeFrom(t2); + PerfCounters.layerCreateTime.addElapsedTimeFrom(t4); - long t3 = System.nanoTime(); + + long t5 = System.nanoTime(); // define the module to its class loader, except java.base for (ResolvedModule resolvedModule : cf.modules()) { @@ -264,7 +314,8 @@ } } - PerfCounters.loadModulesTime.addElapsedTimeFrom(t3); + PerfCounters.loadModulesTime.addElapsedTimeFrom(t5); + // -XaddReads and -XaddExports addExtraReads(bootLayer); @@ -295,25 +346,21 @@ // module name -> reference Map<String, ModuleReference> map = new HashMap<>(); + + // root modules and their transitive dependences cf.modules().stream() .map(ResolvedModule::reference) .forEach(mref -> map.put(mref.descriptor().name(), mref)); + // additional modules + otherMods.stream() + .map(finder::find) + .flatMap(Optional::stream) + .forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref)); + // set of modules that are observable Set<ModuleReference> mrefs = new HashSet<>(map.values()); - // add the other modules - for (String mod : otherMods) { - Optional<ModuleReference> omref = finder.find(mod); - if (omref.isPresent()) { - ModuleReference mref = omref.get(); - map.putIfAbsent(mod, mref); - mrefs.add(mref); - } else { - // no need to fail - } - } - return new ModuleFinder() { @Override public Optional<ModuleReference> find(String name) { @@ -369,15 +416,15 @@ Module other; if (ALL_UNNAMED.equals(name)) { - other = null; // loose + Modules.addReadsAllUnnamed(m); } else { om = bootLayer.findModule(name); if (!om.isPresent()) fail("Unknown module: " + name); other = om.get(); + Modules.addReads(m, other); } - Modules.addReads(m, other); } } } @@ -439,10 +486,6 @@ * Decodes the values of -XaddReads or -XaddExports options * * The format of the options is: $KEY=$MODULE(,$MODULE)* - * - * For transition purposes, this method allows the first usage to be - * $KEY=$MODULE(,$KEY=$MODULE) - * This format will eventually be removed. */ private static Map<String, Set<String>> decode(String prefix) { int index = 0; @@ -467,42 +510,15 @@ if (rhs.isEmpty()) fail("Unable to parse: " + value); - // new format $MODULE(,$MODULE)* or old format $(MODULE)=... - pos = rhs.indexOf('='); - // old format only allowed in first -X option - if (pos >= 0 && index > 0) - fail("Unable to parse: " + value); + // value is <module>(,<module>)* + if (map.containsKey(key)) + fail(key + " specified more than once"); - if (pos == -1) { - - // new format: $KEY=$MODULE(,$MODULE)* - - Set<String> values = map.get(key); - if (values != null) - fail(key + " specified more than once"); - - values = new HashSet<>(); - map.put(key, values); - for (String s : rhs.split(",")) { - if (s.length() > 0) values.add(s); - } - - } else { - - // old format: $KEY=$MODULE(,$KEY=$MODULE)* - - assert index == 0; // old format only allowed in first usage - - for (String expr : value.split(",")) { - if (expr.length() > 0) { - String[] s = expr.split("="); - if (s.length != 2) - fail("Unable to parse: " + expr); - - map.computeIfAbsent(s[0], k -> new HashSet<>()).add(s[1]); - } - } + Set<String> values = new HashSet<>(); + map.put(key, values); + for (String s : rhs.split(",")) { + if (s.length() > 0) values.add(s); } index++; @@ -521,6 +537,13 @@ } static class PerfCounters { + + static PerfCounter systemModulesTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.systemModulesTime"); + static PerfCounter defineBaseTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.defineBaseTime"); + static PerfCounter optionsAndRootsTime + = PerfCounter.newPerfCounter("jdk.module.bootstrap.optionsAndRootsTime"); static PerfCounter resolveTime = PerfCounter.newPerfCounter("jdk.module.bootstrap.resolveTime"); static PerfCounter layerCreateTime
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleHashes.java Wed May 11 00:38:26 2016 +0300 @@ -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.internal.module; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Path; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * The result of hashing the contents of a number of module artifacts. + */ + +public final class ModuleHashes { + + /** + * A supplier of an encoded message digest. + */ + public static interface HashSupplier { + String generate(String algorithm); + } + + + private final String algorithm; + private final Map<String, String> nameToHash; + + /** + * Creates a {@code ModuleHashes}. + * + * @param algorithm the algorithm used to create the hashes + * @param nameToHash the map of module name to hash value (in string form) + */ + public ModuleHashes(String algorithm, Map<String, String> nameToHash) { + this.algorithm = algorithm; + this.nameToHash = Collections.unmodifiableMap(nameToHash); + } + + /** + * Returns the algorithm used to hash the modules ("SHA-256" for example). + */ + public String algorithm() { + return algorithm; + } + + /** + * Returns the set of module names for which hashes are recorded. + */ + public Set<String> names() { + return nameToHash.keySet(); + } + + /** + * Returns the hash string for the given module name, {@code null} + * if there is no hash recorded for the module. + */ + public String hashFor(String mn) { + return nameToHash.get(mn); + } + + /** + * Returns unmodifiable map of module name to hash string. + */ + public Map<String, String> hashes() { + return nameToHash; + } + + /** + * Computes the hash for the given file with the given message digest + * algorithm. Returns the results a base64-encoded String. + * + * @throws UncheckedIOException if an I/O error occurs + * @throws RuntimeException if the algorithm is not available + */ + public static String computeHashAsString(Path file, String algorithm) { + try { + MessageDigest md = MessageDigest.getInstance(algorithm); + + // Ideally we would just mmap the file but this consumes too much + // memory when jlink is running concurrently on very large jmods + try (FileChannel fc = FileChannel.open(file)) { + ByteBuffer bb = ByteBuffer.allocate(32*1024); + while (fc.read(bb) > 0) { + bb.flip(); + md.update(bb); + assert bb.remaining() == 0; + bb.clear(); + } + } + + byte[] bytes = md.digest(); + return Base64.getEncoder().encodeToString(bytes); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + + /** + * Computes the hash for every entry in the given map, returning a + * {@code ModuleHashes} to encapsulate the result. The map key is + * the entry name, typically the module name. The map value is the file + * path to the entry (module artifact). + * + * @return ModuleHashes encapsulate the hashes + */ + public static ModuleHashes generate(Map<String, Path> map, String algorithm) { + Map<String, String> nameToHash = new HashMap<>(); + for (Map.Entry<String, Path> entry: map.entrySet()) { + String name = entry.getKey(); + Path path = entry.getValue(); + nameToHash.put(name, computeHashAsString(path, algorithm)); + } + return new ModuleHashes(algorithm, nameToHash); + } +}
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoExtender.java Wed May 11 00:38:26 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ import jdk.internal.org.objectweb.asm.ClassVisitor; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.module.Hasher.DependencyHashes; import static jdk.internal.module.ClassFileAttributes.*; @@ -69,7 +68,7 @@ private String osVersion; // the hashes for the Hashes attribute - private DependencyHashes hashes; + private ModuleHashes hashes; private ModuleInfoExtender(InputStream in) { this.in = in; @@ -113,10 +112,10 @@ /** * The Hashes attribute will be emitted to the module-info with - * the hashes encapsulated in the given {@code DependencyHashes} + * the hashes encapsulated in the given {@code ModuleHashes} * object. */ - public ModuleInfoExtender hashes(DependencyHashes hashes) { + public ModuleInfoExtender hashes(ModuleHashes hashes) { this.hashes = hashes; return this; }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModuleInfoWriter.java Wed May 11 00:38:26 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,28 +49,22 @@ * Writes the given module descriptor to a module-info.class file, * returning it in a byte array. */ - private static byte[] toModuleInfo(ModuleDescriptor descriptor) { + private static byte[] toModuleInfo(ModuleDescriptor md) { ClassWriter cw = new ClassWriter(0); - String name = descriptor.name().replace('.', '/') + "/module-info"; + String name = md.name().replace('.', '/') + "/module-info"; cw.visit(Opcodes.V1_8, ACC_MODULE, name, null, null, null); - cw.visitAttribute(new ModuleAttribute(descriptor)); - cw.visitAttribute(new ConcealedPackagesAttribute(descriptor.conceals())); - - Optional<Version> oversion = descriptor.version(); - if (oversion.isPresent()) - cw.visitAttribute(new VersionAttribute(oversion.get())); - - Optional<String> omain = descriptor.mainClass(); - if (omain.isPresent()) - cw.visitAttribute(new MainClassAttribute(omain.get())); + cw.visitAttribute(new ModuleAttribute(md)); + cw.visitAttribute(new ConcealedPackagesAttribute(md.conceals())); + md.version().ifPresent(v -> cw.visitAttribute(new VersionAttribute(v))); + md.mainClass().ifPresent(mc -> cw.visitAttribute(new MainClassAttribute(mc))); // write the TargetPlatform attribute if have any of OS name/arch/version - String osName = descriptor.osName().orElse(null); - String osArch = descriptor.osArch().orElse(null); - String osVersion = descriptor.osVersion().orElse(null); + String osName = md.osName().orElse(null); + String osArch = md.osArch().orElse(null); + String osVersion = md.osVersion().orElse(null); if (osName != null || osArch != null || osVersion != null) { cw.visitAttribute(new TargetPlatformAttribute(osName, osArch,
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ModulePatcher.java Wed May 11 00:38:26 2016 +0300 @@ -91,56 +91,29 @@ Map<String, List<Path>> map = new HashMap<>(); while (value != null) { + + // <module>=<file>(:<file>)* + int pos = value.indexOf('='); - - if (pos == -1 && index > 0) + if (pos == -1) throwIAE("Unable to parse: " + value); - if (pos == 0) throwIAE("Missing module name: " + value); - if (pos > 0) { + String mn = value.substring(0, pos); + List<Path> list = map.get(mn); + if (list != null) + throwIAE("Module " + mn + " specified more than once"); + list = new ArrayList<>(); + map.put(mn, list); - // new format: <module>=<file>(:<file>)* - - String mn = value.substring(0, pos); - List<Path> list = map.get(mn); - if (list != null) - throwIAE("Module " + mn + " specified more than once"); - list = new ArrayList<>(); - map.put(mn, list); - - String paths = value.substring(pos+1); - for (String path : paths.split(File.pathSeparator)) { - if (!path.isEmpty()) { - list.add(Paths.get(path)); - } + String paths = value.substring(pos+1); + for (String path : paths.split(File.pathSeparator)) { + if (!path.isEmpty()) { + list.add(Paths.get(path)); } - - } else { - - // old format: <dir>(:<dir>)* - - assert index == 0; // old format only allowed in first -Xpatch - - String[] dirs = value.split(File.pathSeparator); - for (String d : dirs) { - if (d.length() > 0) { - Path top = Paths.get(d); - try { - Files.list(top).forEach(e -> { - String mn = e.getFileName().toString(); - Path dir = top.resolve(mn); - map.computeIfAbsent(mn, k -> new ArrayList<>()) - .add(dir); - }); - } catch (IOException ignore) { } - } - } - } - index++; value = System.getProperty(PATCH_PROPERTY_PREFIX + index); } @@ -175,7 +148,8 @@ for (Path file : paths) { if (Files.isRegularFile(file)) { - // JAR file + // JAR file - do not open as a multi-release JAR as this + // is not supported by the boot class loader try (JarFile jf = new JarFile(file.toFile())) { jf.stream() .filter(e -> e.getName().endsWith(".class")) @@ -209,10 +183,11 @@ descriptor = JLMA.newModuleDescriptor(descriptor, packages); } - // return a new module reference + // return a module reference to the patched module URI location = mref.location().orElse(null); - return new ModuleReference(descriptor, location, - () -> new PatchedModuleReader(paths, mref)); + return JLMA.newPatchedModule(descriptor, + location, + () -> new PatchedModuleReader(paths, mref)); }
--- a/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/Modules.java Wed May 11 00:38:26 2016 +0300 @@ -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 @@ -58,7 +58,7 @@ * Creates a new Module. The module has the given ModuleDescriptor and * is defined to the given class loader. * - * The resulting Module is in a larva state in that it does not not read + * The resulting Module is in a larval state in that it does not not read * any other module and does not have any exports. * * The URI is for information purposes only. @@ -74,7 +74,7 @@ * Define a new module to the VM. The module has the given set of * concealed packages and is defined to the given class loader. * - * The resulting Module is in a larva state in that it does not not read + * The resulting Module is in a larval state in that it does not not read * any other module and does not have any exports. */ public static Module defineModule(ClassLoader loader, @@ -96,6 +96,13 @@ } /** + * Update module {@code m} to read all unnamed modules. + */ + public static void addReadsAllUnnamed(Module m) { + JLRMA.addReadsAllUnnamed(m); + } + + /** * Updates module m1 to export a package to module m2. * Same as m1.addExports(pkg, m2) but without a caller check. */
--- a/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/ServicesCatalog.java Wed May 11 00:38:26 2016 +0300 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,94 +29,105 @@ import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleDescriptor.Provides; import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import java.util.Set; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.ConcurrentHashMap; /** - * A services catalog. Each {@code ClassLoader} has an optional {@code - * ServicesCatalog} for modules that provide services. This is to support - * ClassLoader centric ServiceLoader.load methods. + * A <em>services catalog</em>. Each {@code ClassLoader} and {@code Layer} has + * an optional {@code ServicesCatalog} for modules that provide services. + * + * @see java.util.ServiceLoader */ -public class ServicesCatalog { - - // use RW locks as register is rare - private final ReadWriteLock lock = new ReentrantReadWriteLock(); - private final Lock readLock = lock.readLock(); - private final Lock writeLock = lock.writeLock(); +public interface ServicesCatalog { /** * Represents a service provider in the services catalog. */ - public class ServiceProvider { + public final class ServiceProvider { private final Module module; private final String providerName; - ServiceProvider(Module module, String providerName) { + + public ServiceProvider(Module module, String providerName) { this.module = module; this.providerName = providerName; } + public Module module() { return module; } + public String providerName() { return providerName; } - } - // service providers - private final Map<String, Set<ServiceProvider>> loaderServices = new HashMap<>(); + @Override + public int hashCode() { + return Objects.hash(module, providerName); + } - /** - * Creates a new module catalog. - */ - public ServicesCatalog() { } - - /** - * Registers the module in this module catalog. - */ - public void register(Module m) { - ModuleDescriptor descriptor = m.getDescriptor(); - - writeLock.lock(); - try { - // extend the services map - for (Provides ps : descriptor.provides().values()) { - String service = ps.service(); - Set<String> providerNames = ps.providers(); - - // create a new set to replace the existing - Set<ServiceProvider> result = new HashSet<>(); - Set<ServiceProvider> providers = loaderServices.get(service); - if (providers != null) { - result.addAll(providers); - } - for (String pn : providerNames) { - result.add(new ServiceProvider(m, pn)); - } - loaderServices.put(service, Collections.unmodifiableSet(result)); - } - - } finally { - writeLock.unlock(); + @Override + public boolean equals(Object ob) { + if (!(ob instanceof ServiceProvider)) + return false; + ServiceProvider that = (ServiceProvider)ob; + return Objects.equals(this.module, that.module) + && Objects.equals(this.providerName, that.providerName); } } /** + * Registers the providers in the given module in this services catalog. + * + * @throws UnsupportedOperationException + * If this services catalog is immutable + */ + void register(Module module); + + /** * Returns the (possibly empty) set of service providers that implement the * given service type. - * - * @see java.util.ServiceLoader */ - public Set<ServiceProvider> findServices(String service) { - readLock.lock(); - try { - return loaderServices.getOrDefault(service, Collections.emptySet()); - } finally { - readLock.unlock(); - } + Set<ServiceProvider> findServices(String service); + + /** + * Creates a ServicesCatalog that supports concurrent registration and + * and lookup. + */ + static ServicesCatalog create() { + return new ServicesCatalog() { + + private Map<String, Set<ServiceProvider>> map = new ConcurrentHashMap<>(); + + @Override + public void register(Module m) { + ModuleDescriptor descriptor = m.getDescriptor(); + + for (Provides provides : descriptor.provides().values()) { + String service = provides.service(); + Set<String> providerNames = provides.providers(); + + // create a new set to replace the existing + Set<ServiceProvider> result = new HashSet<>(); + Set<ServiceProvider> providers = map.get(service); + if (providers != null) { + result.addAll(providers); + } + for (String pn : providerNames) { + result.add(new ServiceProvider(m, pn)); + } + map.put(service, Collections.unmodifiableSet(result)); + } + + } + + @Override + public Set<ServiceProvider> findServices(String service) { + return map.getOrDefault(service, Collections.emptySet()); + } + + }; } -} +} \ No newline at end of file
--- a/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/module/SystemModules.java Wed May 11 00:38:26 2016 +0300 @@ -40,21 +40,26 @@ */ public final class SystemModules { /** - * Name of the installed modules. + * Name of the system modules. * - * This array provides a way for InstalledModuleFinder to fallback + * This array provides a way for SystemModuleFinder to fallback * and read module-info.class from the run-time image instead of * the fastpath. */ public static final String[] MODULE_NAMES = new String[1]; /** + * Hash of system modules. + */ + public static String[] MODULES_TO_HASH = new String[1]; + + /** * Number of packages in the boot layer from the installed modules. * * Don't make it final to avoid inlining during compile time as * the value will be changed at jlink time. */ - public static final int PACKAGES_IN_BOOT_LAYER = 1024; + public static int PACKAGES_IN_BOOT_LAYER = 1024; /** * Returns a non-empty array of ModuleDescriptors in the run-time image. @@ -64,4 +69,5 @@ public static ModuleDescriptor[] modules() { return new ModuleDescriptor[0]; } -} \ No newline at end of file + +}
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/MethodAccessorGenerator.java Wed May 11 00:38:26 2016 +0300 @@ -392,6 +392,7 @@ // matter. return AccessController.doPrivileged( new PrivilegedAction<MagicAccessorImpl>() { + @SuppressWarnings("deprecation") // Class.newInstance public MagicAccessorImpl run() { try { return (MagicAccessorImpl)
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/Reflection.java Wed May 11 00:38:26 2016 +0300 @@ -343,8 +343,8 @@ private static void printStackTraceIfNeeded(Throwable e) { if (!printStackWhenAccessFailsSet && VM.initLevel() >= 1) { - String s = GetPropertyAction - .getProperty("sun.reflect.debugModuleAccessChecks"); + String s = GetPropertyAction.privilegedGetProperty( + "sun.reflect.debugModuleAccessChecks"); printStackWhenAccessFails = (s != null && !s.equalsIgnoreCase("false")); printStackWhenAccessFailsSet = true;
--- a/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/jdk/internal/reflect/ReflectionFactory.java Wed May 11 00:38:26 2016 +0300 @@ -398,7 +398,7 @@ return; } - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String val = props.getProperty("sun.reflect.noInflation"); if (val != null && val.equals("true")) { noInflation = true;
--- a/jdk/src/java.base/share/classes/module-info.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/module-info.java Wed May 11 00:38:26 2016 +0300 @@ -166,6 +166,8 @@ java.sql, java.xml, jdk.charsets, + jdk.jartool, + jdk.jlink, jdk.net, jdk.scripting.nashorn, jdk.unsupported,
--- a/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/launcher/LauncherHelper.java Wed May 11 00:38:26 2016 +0300 @@ -84,8 +84,10 @@ import jdk.internal.misc.VM; -public enum LauncherHelper { - INSTANCE; +public final class LauncherHelper { + + // No instantiation + private LauncherHelper() {} // used to identify JavaFX applications private static final String JAVAFX_APPLICATION_MARKER =
--- a/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/launcher/resources/launcher.properties Wed May 11 00:38:26 2016 +0300 @@ -27,7 +27,7 @@ java.launcher.opt.header = Usage: {0} [options] class [args...]\n\ \ (to execute a class)\n or {0} [options] -jar jarfile [args...]\n\ \ (to execute a jar file)\n\ -\ or {0} [-options] -mp <modulepath> -m <modulename> | <modulename>/<mainclass>\n\ +\ or {0} [options] -mp <modulepath> -m <modulename>[/<mainclass>] [args...]\n\ \ (to execute the main class in a module)\n\ where options include:\n @@ -51,8 +51,9 @@ \ A {0} separated list of directories, each directory\n\ \ is a directory of modules that replace upgradeable\n\ \ modules in the runtime image\n\ -\ -m <modulename> | <modulename>/<mainclass>\n\ -\ the initial or main module to resolve\n\ +\ -m <modulename>[/<mainclass>]\n\ +\ the initial module to resolve, and the name of the main class\n\ +\ to execute if not specified by the module\n\ \ -addmods <modulename>[,<modulename>...]\n\ \ root modules to resolve in addition to the initial module\n\ \ -limitmods <modulename>[,<modulename>...]\n\
--- a/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/ResourceManager.java Wed May 11 00:38:26 2016 +0300 @@ -53,8 +53,8 @@ private static final AtomicInteger numSockets; static { - String prop = - GetPropertyAction.getProperty("sun.net.maxDatagramSockets"); + String prop = GetPropertyAction + .privilegedGetProperty("sun.net.maxDatagramSockets"); int defmax = DEFAULT_MAX_SOCKETS; try { if (prop != null) {
--- a/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/ftp/FtpClientProvider.java Wed May 11 00:38:26 2016 +0300 @@ -67,8 +67,9 @@ return false; } try { - Class<?> c = Class.forName(cm, true, null); - provider = (FtpClientProvider) c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(cm, true, null).newInstance(); + provider = (FtpClientProvider)o; return true; } catch (ClassNotFoundException | IllegalAccessException |
--- a/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/sdp/SdpSupport.java Wed May 11 00:38:26 2016 +0300 @@ -40,7 +40,7 @@ */ public final class SdpSupport { - private static final String os = GetPropertyAction.getProperty("os.name"); + private static final String os = GetPropertyAction.privilegedGetProperty("os.name"); private static final boolean isSupported = (os.equals("SunOS") || (os.equals("Linux"))); private static final JavaIOFileDescriptorAccess fdAccess = SharedSecrets.getJavaIOFileDescriptorAccess();
--- a/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/smtp/SmtpClient.java Wed May 11 00:38:26 2016 +0300 @@ -157,7 +157,7 @@ } try { String s; - mailhost = GetPropertyAction.getProperty("mail.host"); + mailhost = GetPropertyAction.privilegedGetProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return; @@ -183,7 +183,7 @@ setConnectTimeout(to); try { String s; - mailhost = GetPropertyAction.getProperty("mail.host"); + mailhost = GetPropertyAction.privilegedGetProperty("mail.host"); if (mailhost != null) { openServer(mailhost); return;
--- a/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/MimeLauncher.java Wed May 11 00:38:26 2016 +0300 @@ -183,7 +183,7 @@ } String execPathList; - execPathList = GetPropertyAction.getProperty("exec.path"); + execPathList = GetPropertyAction.privilegedGetProperty("exec.path"); if (execPathList == null) { // exec.path property not set return false;
--- a/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/http/HttpClient.java Wed May 11 00:38:26 2016 +0300 @@ -145,7 +145,7 @@ } static { - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String keepAlive = props.getProperty("http.keepAlive"); String retryPost = props.getProperty("sun.net.http.retryPost");
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Wed May 11 00:38:26 2016 +0300 @@ -278,7 +278,7 @@ if (user == null) { user = "anonymous"; - Properties props = GetPropertyAction.getProperties(); + Properties props = GetPropertyAction.privilegedGetProperties(); String vers = props.getProperty("java.version"); password = props.getProperty("ftp.protocol.user", "Java" + vers + "@");
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationHeader.java Wed May 11 00:38:26 2016 +0300 @@ -94,7 +94,7 @@ } static { - authPref = GetPropertyAction.getProperty("http.auth.preference"); + authPref = GetPropertyAction.privilegedGetProperty("http.auth.preference"); // http.auth.preference can be set to SPNEGO or Kerberos. // In fact they means "Negotiate with SPNEGO" and "Negotiate with
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed May 11 00:38:26 2016 +0300 @@ -207,9 +207,9 @@ }; static { - Properties props = GetPropertyAction.getProperties(); - maxRedirects = GetIntegerAction.getProperty("http.maxRedirects", - defaultmaxRedirects); + Properties props = GetPropertyAction.privilegedGetProperties(); + maxRedirects = GetIntegerAction.privilegedGetProperty( + "http.maxRedirects", defaultmaxRedirects); version = props.getProperty("java.version"); String agent = props.getProperty("http.agent"); if (agent == null) { @@ -225,14 +225,14 @@ enableESBuffer = Boolean.parseBoolean( props.getProperty("sun.net.http.errorstream.enableBuffering")); - timeout4ESBuffer = GetIntegerAction - .getProperty("sun.net.http.errorstream.timeout", 300); + timeout4ESBuffer = GetIntegerAction.privilegedGetProperty( + "sun.net.http.errorstream.timeout", 300); if (timeout4ESBuffer <= 0) { timeout4ESBuffer = 300; // use the default } - bufSize4ES = GetIntegerAction - .getProperty("sun.net.http.errorstream.bufferSize", 4096); + bufSize4ES = GetIntegerAction.privilegedGetProperty( + "sun.net.http.errorstream.bufferSize", 4096); if (bufSize4ES <= 0) { bufSize4ES = 4096; // use the default }
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java Wed May 11 00:38:26 2016 +0300 @@ -139,7 +139,7 @@ // String ciphers []; String cipherString = - GetPropertyAction.getProperty("https.cipherSuites"); + GetPropertyAction.privilegedGetProperty("https.cipherSuites"); if (cipherString == null || "".equals(cipherString)) { ciphers = null; @@ -163,7 +163,7 @@ // String protocols []; String protocolString = - GetPropertyAction.getProperty("https.protocols"); + GetPropertyAction.privilegedGetProperty("https.protocols"); if (protocolString == null || "".equals(protocolString)) { protocols = null; @@ -183,7 +183,8 @@ } private String getUserAgent() { - String userAgent = GetPropertyAction.getProperty("https.agent"); + String userAgent = + GetPropertyAction.privilegedGetProperty("https.agent"); if (userAgent == null || userAgent.length() == 0) { userAgent = "JSSE"; }
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java Wed May 11 00:38:26 2016 +0300 @@ -161,7 +161,7 @@ public Permission getPermission() throws IOException { Permission p = permission; if (p == null) { - String home = GetPropertyAction.getProperty("java.home"); + String home = GetPropertyAction.privilegedGetProperty("java.home"); p = new FilePermission(home + File.separator + "-", "read"); permission = p; }
--- a/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/netdoc/Handler.java Wed May 11 00:38:26 2016 +0300 @@ -56,9 +56,9 @@ URL ru; boolean localonly = Boolean.parseBoolean( - GetPropertyAction.getProperty("newdoc.localonly")); + GetPropertyAction.privilegedGetProperty("newdoc.localonly")); - String docurl = GetPropertyAction.getProperty("doc.url"); + String docurl = GetPropertyAction.privilegedGetProperty("doc.url"); String file = u.getFile(); if (!localonly) {
--- a/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java Wed May 11 00:38:26 2016 +0300 @@ -1019,7 +1019,7 @@ if (!propertyChecked) { synchronized (FileChannelImpl.class) { if (!propertyChecked) { - String value = GetPropertyAction.getProperty( + String value = GetPropertyAction.privilegedGetProperty( "sun.nio.ch.disableSystemWideOverlappingFileLockCheck"); isSharedFileLockTable = ((value == null) || value.equals("false")); propertyChecked = true;
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Wed May 11 00:38:26 2016 +0300 @@ -374,8 +374,8 @@ } public static boolean isFastTcpLoopbackRequested() { - String loopbackProp = - GetPropertyAction.getProperty("jdk.net.useFastTcpLoopback"); + String loopbackProp = GetPropertyAction + .privilegedGetProperty("jdk.net.useFastTcpLoopback"); boolean enable; if ("".equals(loopbackProp)) { enable = true; @@ -633,8 +633,8 @@ static { int availLevel = isExclusiveBindAvailable(); if (availLevel >= 0) { - String exclBindProp = - GetPropertyAction.getProperty("sun.net.useExclusiveBind"); + String exclBindProp = GetPropertyAction + .privilegedGetProperty("sun.net.useExclusiveBind"); if (exclBindProp != null) { exclusiveBind = exclBindProp.isEmpty() ? true : Boolean.parseBoolean(exclBindProp);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ThreadPool.java Wed May 11 00:38:26 2016 +0300 @@ -165,14 +165,11 @@ GetPropertyAction(DEFAULT_THREAD_POOL_THREAD_FACTORY)); if (propValue != null) { try { - Class<?> c = Class - .forName(propValue, true, ClassLoader.getSystemClassLoader()); - return ((ThreadFactory)c.newInstance()); - } catch (ClassNotFoundException x) { - throw new Error(x); - } catch (InstantiationException x) { - throw new Error(x); - } catch (IllegalAccessException x) { + @SuppressWarnings("deprecation") + Object tmp = Class + .forName(propValue, true, ClassLoader.getSystemClassLoader()).newInstance(); + return (ThreadFactory)tmp; + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException x) { throw new Error(x); } }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java Wed May 11 00:38:26 2016 +0300 @@ -64,7 +64,8 @@ * for potential future-proofing. */ private static long getMaxCachedBufferSize() { - String s = GetPropertyAction.getProperty("jdk.nio.maxCachedBufferSize"); + String s = GetPropertyAction + .privilegedGetProperty("jdk.nio.maxCachedBufferSize"); if (s != null) { try { long m = Long.parseLong(s); @@ -465,7 +466,8 @@ if (bugLevel == null) { if (!jdk.internal.misc.VM.isBooted()) return false; - String value = GetPropertyAction.getProperty("sun.nio.ch.bugLevel"); + String value = GetPropertyAction + .privilegedGetProperty("sun.nio.ch.bugLevel"); bugLevel = (value != null) ? value : ""; } return bugLevel.equals(bl);
--- a/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/cs/FastCharsetProvider.java Wed May 11 00:38:26 2016 +0300 @@ -115,10 +115,11 @@ // Instantiate the charset and cache it try { - Class<?> c = Class.forName(packagePrefix + "." + cln, + @SuppressWarnings("deprecation") + Object o= Class.forName(packagePrefix + "." + cln, true, - this.getClass().getClassLoader()); - cs = (Charset)c.newInstance(); + this.getClass().getClassLoader()).newInstance(); + cs = (Charset)o; cache.put(csn, cs); return cs; } catch (ClassNotFoundException |
--- a/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/cs/StandardCharsets.java.template Wed May 11 00:38:26 2016 +0300 @@ -110,10 +110,11 @@ // Instantiate the charset and cache it try { - Class<?> c = Class.forName(packagePrefix + "." + cln, - true, - this.getClass().getClassLoader()); - cs = (Charset)c.newInstance(); + @SuppressWarnings("deprecation") + Object o = Class.forName(packagePrefix + "." + cln, + true, + this.getClass().getClassLoader()).newInstance(); + cs = (Charset)o; cache.put(csn, cs); return cs; } catch (ClassNotFoundException | @@ -164,7 +165,7 @@ return; initialized = true; - String map = getProperty("sun.nio.cs.map"); + String map = GetPropertyAction.privilegedGetProperty("sun.nio.cs.map"); if (map != null) { String[] maps = map.split(","); for (int i = 0; i < maps.length; i++) { @@ -199,9 +200,4 @@ } } - private static String getProperty(String key) { - return GetPropertyAction.getProperty(key); - } - - }
--- a/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/nio/fs/Util.java Wed May 11 00:38:26 2016 +0300 @@ -38,7 +38,7 @@ private Util() { } private static final Charset jnuEncoding = Charset.forName( - GetPropertyAction.getProperty("sun.jnu.encoding")); + GetPropertyAction.privilegedGetProperty("sun.jnu.encoding")); /** * Returns {@code Charset} corresponding to the sun.jnu.encoding property
--- a/jdk/src/java.base/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java Fri May 06 19:35:34 2016 +0300 +++ /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/action/GetIntegerAction.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/action/GetIntegerAction.java Wed May 11 00:38:26 2016 +0300 @@ -118,9 +118,14 @@ * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. */ - public static Integer getProperty(String theProp) { + public static Integer privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return Integer.getInteger(theProp); } else { @@ -134,10 +139,16 @@ * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. * @param defaultVal the default value. */ - public static Integer getProperty(String theProp, int defaultVal) { + public static Integer privilegedGetProperty(String theProp, + int defaultVal) { Integer value; if (System.getSecurityManager() == null) { value = Integer.getInteger(theProp);
--- a/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/action/GetPropertyAction.java Wed May 11 00:38:26 2016 +0300 @@ -93,9 +93,14 @@ * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. */ - public static String getProperty(String theProp) { + public static String privilegedGetProperty(String theProp) { if (System.getSecurityManager() == null) { return System.getProperty(theProp); } else { @@ -109,10 +114,16 @@ * if no security manager is present. This is unsafe for inclusion in a * public API but allowable here since this class is now encapsulated. * + * Note that this method performs a privileged action using caller-provided + * inputs. The caller of this method should take care to ensure that the + * inputs are not tainted and the returned property is not made accessible + * to untrusted code if it contains sensitive information. + * * @param theProp the name of the system property. * @param defaultVal the default value. */ - public static String getProperty(String theProp, String defaultVal) { + public static String privilegedGetProperty(String theProp, + String defaultVal) { if (System.getSecurityManager() == null) { return System.getProperty(theProp, defaultVal); } else { @@ -126,8 +137,13 @@ * having to go through doPrivileged if no security manager is present. * This is unsafe for inclusion in a public API but allowable here since * this class is now encapsulated. + * + * Note that this method performs a privileged action, and callers of + * this method should take care to ensure that the returned properties + * are not made accessible to untrusted code since it may contain + * sensitive information. */ - public static Properties getProperties() { + public static Properties privilegedGetProperties() { if (System.getSecurityManager() == null) { return System.getProperties(); } else {
--- a/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/jca/ProviderConfig.java Wed May 11 00:38:26 2016 +0300 @@ -185,7 +185,9 @@ try { Class<?> c = Class.forName("apple.security.AppleProvider"); if (Provider.class.isAssignableFrom(c)) { - return (Provider) c.newInstance(); + @SuppressWarnings("deprecation") + Object tmp = c.newInstance(); + return (Provider) tmp; } else { return null; } @@ -386,6 +388,7 @@ Provider p = AccessController.doPrivileged (new PrivilegedExceptionAction<Provider>() { + @SuppressWarnings("deprecation") // Class.newInstance public Provider run() throws Exception { return (Provider) provClass.newInstance(); }
--- a/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/pkcs/PKCS8Key.java Wed May 11 00:38:26 2016 +0300 @@ -218,11 +218,10 @@ } } - Object inst = null; + @SuppressWarnings("deprecation") + Object inst = (keyClass != null) ? keyClass.newInstance() : null; PKCS8Key result; - if (keyClass != null) - inst = keyClass.newInstance(); if (inst instanceof PKCS8Key) { result = (PKCS8Key) inst; result.algid = algid;
--- a/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/provider/DSAKeyFactory.java Wed May 11 00:38:26 2016 +0300 @@ -70,7 +70,7 @@ * By default this is false. * This incompatibility was introduced by 4532506. */ - String prop = GetPropertyAction.getProperty(SERIAL_PROP); + String prop = GetPropertyAction.privilegedGetProperty(SERIAL_PROP); SERIAL_INTEROP = "true".equalsIgnoreCase(prop); }
--- a/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Fri May 06 19:35:34 2016 +0300 +++ b/jdk/src/java.base/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Wed May 11 00:38:26 2016 +0300 @@ -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 " + +