changeset 4142:77a2d6c1f321

8178152: Handling of incubating modules, the jdk.unsupported module and --add-exports with --release <current> Summary: --release 9 should only allow documented modules; --add-exports/--add-reads/--patch-module should not be allowed on system modules when --release 9 is used. Reviewed-by: jjg, erikj, ihse
author jlahoda
date Fri, 12 May 2017 06:42:37 +0200
parents 6ffca66728a7
children 18355c879c69
files make/gendata/Gendata-jdk.compiler.gmk make/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/diags/examples/AddExportsWithRelease.java test/tools/javac/diags/examples/AddReadsWithRelease.java test/tools/javac/diags/examples/PatchModuleWithRelease/PatchModuleWithRelease.java test/tools/javac/diags/examples/PatchModuleWithRelease/patchmodule/java.base/java/lang/Test.java test/tools/javac/options/release/ReleaseOptionClashes.java test/tools/javac/options/release/ReleaseOptionUnsupported.java
diffstat 12 files changed, 627 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/make/gendata/Gendata-jdk.compiler.gmk	Thu May 11 15:12:38 2017 -0700
+++ b/make/gendata/Gendata-jdk.compiler.gmk	Fri May 12 06:42:37 2017 +0200
@@ -25,10 +25,20 @@
 
 include JarArchive.gmk
 include JavaCompilation.gmk
+include Modules.gmk
 include SetupJavaCompilers.gmk
 
 ################################################################################
 
+# This is needed to properly setup DOCS_MODULES.
+$(eval $(call ReadImportMetaData))
+
+# Modules that should be visible for 9 - the documented modules:
+CT_MODULES := $(DOCS_MODULES)
+
+# Get the complete module source path:
+CT_MODULESOURCEPATH := $(call GetModuleSrcPath)
+
 CT_DATA_DESCRIPTION ?= $(LANGTOOLS_TOPDIR)/make/data/symbols/symbols
 
 $(eval $(call SetupJavaCompilation, COMPILE_CREATE_SYMBOLS, \
@@ -41,6 +51,8 @@
 
 ifeq ($(BOOT_JDK_MODULAR), true)
   COMPILECREATESYMBOLS_ADD_EXPORTS := \
+      --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED \
+      --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED \
       --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED \
       --add-exports=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED \
       --add-exports=jdk.jdeps/com.sun.tools.classfile=ALL-UNNAMED
@@ -59,6 +71,14 @@
 	    build-ctsym \
 	    $(CT_DATA_DESCRIPTION) \
 	    $(@D)
+	$(MKDIR) $(@D)/9
+	$(JAVA_SMALL) $(INTERIM_LANGTOOLS_ARGS) \
+	    $(COMPILECREATESYMBOLS_ADD_EXPORTS) \
+	    -classpath $(BUILDTOOLS_OUTPUTDIR)/create_symbols \
+	    build.tools.symbolgenerator.TransitiveDependencies \
+	    $(CT_MODULESOURCEPATH) \
+	    $(CT_MODULES) \
+	    >$(@D)/9/system-modules
 	$(TOUCH) $@
 
 # Can't generate ct.sym directly into modules libs as the SetupJarArchive macro
@@ -66,7 +86,7 @@
 $(eval $(call SetupJarArchive, CREATE_CTSYM, \
     DEPENDENCIES := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files/_the.symbols, \
     SRCS := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym-files, \
-    SUFFIXES := .sig, \
+    SUFFIXES := .sig system-modules, \
     JAR := $(SUPPORT_OUTPUTDIR)/symbols/ct.sym, \
 ))
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/src/classes/build/tools/symbolgenerator/TransitiveDependencies.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.symbolgenerator;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import javax.lang.model.element.ModuleElement.RequiresDirective;
+import javax.lang.model.util.Elements;
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+
+/**
+ * Print reflexive transitive closure of the given modules along their requires transitive edges.
+ */
+public class TransitiveDependencies {
+
+    private static void help() {
+        System.err.println("java TransitiveDependencies <module-source-path> <root-modules>");
+    }
+
+    public static void main(String... args) throws IOException {
+        if (args.length < 1) {
+            help();
+            return ;
+        }
+
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        List<String> options = Arrays.asList("-source", "9",
+                                             "-target", "9",
+                                             "--system", "none",
+                                             "--module-source-path", args[0],
+                                             "--add-modules", Arrays.stream(args)
+                                                                    .skip(1)
+                                                                    .collect(Collectors.joining(",")));
+        List<String> jlObjectList = Arrays.asList("java.lang.Object");
+        JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, d -> {}, options, jlObjectList, null);
+        task.enter();
+        Elements elements = task.getElements();
+        List<String> todo = new LinkedList<>();
+        Arrays.stream(args).skip(1).forEach(todo::add);
+        Set<String> allModules = new HashSet<>();
+
+        while (!todo.isEmpty()) {
+            String current = todo.remove(0);
+
+            if (!allModules.add(current))
+                continue;
+
+            ModuleSymbol mod = (ModuleSymbol) elements.getModuleElement(current);
+
+            if (mod == null) {
+                throw new IllegalStateException("Missing: " + current);
+            }
+
+             //use the internal structure to avoid unnecesarily completing the symbol using the UsesProvidesVisitor:
+            for (RequiresDirective rd : mod.requires) {
+                if (rd.isTransitive()) {
+                    todo.add(rd.getDependency().getQualifiedName().toString());
+                }
+            }
+        }
+
+        allModules.add("java.base");
+        allModules.add("jdk.unsupported");
+
+        allModules.stream()
+                  .sorted()
+                  .forEach(System.out::println);
+    }
+
+}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Thu May 11 15:12:38 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Fri May 12 06:42:37 2017 +0200
@@ -142,6 +142,7 @@
     private final ModuleFinder moduleFinder;
     private final Source source;
     private final boolean allowModules;
+    private final boolean allowAccessIntoSystem;
 
     public final boolean multiModuleMode;
 
@@ -192,6 +193,7 @@
         allowModules = source.allowModules();
         Options options = Options.instance(context);
 
+        allowAccessIntoSystem = options.isUnset(Option.RELEASE);
         lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
 
         Collection<String> xmodules = options.keySet()
@@ -1230,7 +1232,7 @@
             for (String limit : extraLimitMods) {
                 limitMods.add(syms.enterModule(names.fromString(limit)));
             }
-            observable = computeTransitiveClosure(limitMods, null);
+            observable = computeTransitiveClosure(limitMods, rootModules, null);
             observable.addAll(rootModules);
             if (lintOptions) {
                 for (ModuleSymbol msym : limitMods) {
@@ -1310,7 +1312,7 @@
             }
         }
 
-        Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
+        Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, rootModules, observable);
 
         result.add(syms.unnamedModule);
 
@@ -1348,12 +1350,18 @@
         return allModules == null || allModules.contains(msym);
     }
 
-    private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
+    private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base,
+                                                       Set<? extends ModuleSymbol> rootModules,
+                                                       Set<ModuleSymbol> observable) {
         List<ModuleSymbol> primaryTodo = List.nil();
         List<ModuleSymbol> secondaryTodo = List.nil();
 
         for (ModuleSymbol ms : base) {
-            primaryTodo = primaryTodo.prepend(ms);
+            if (rootModules.contains(ms)) {
+                primaryTodo = primaryTodo.prepend(ms);
+            } else {
+                secondaryTodo = secondaryTodo.prepend(ms);
+            }
         }
 
         Set<ModuleSymbol> result = new LinkedHashSet<>();
@@ -1376,12 +1384,12 @@
             if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0))
                 continue;
             current.complete();
-            if (current.kind == ERR && isPrimaryTodo && warnedMissing.add(current)) {
+            if (current.kind == ERR && (isPrimaryTodo || base.contains(current)) && warnedMissing.add(current)) {
                 log.error(Errors.ModuleNotFound(current));
             }
             for (RequiresDirective rd : current.requires) {
                 if (rd.module == syms.java_base) continue;
-                if ((rd.isTransitive() && isPrimaryTodo) || base.contains(current)) {
+                if ((rd.isTransitive() && isPrimaryTodo) || rootModules.contains(current)) {
                     primaryTodo = primaryTodo.prepend(rd.module);
                 } else {
                     secondaryTodo = secondaryTodo.prepend(rd.module);
@@ -1488,6 +1496,10 @@
             }
         }
 
+        if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0 &&
+            msym.patchLocation != null) {
+            log.error(Errors.PatchModuleWithRelease(msym));
+        }
     }
 
     private Set<ModuleSymbol> retrieveRequiresTransitive(ModuleSymbol msym) {
@@ -1613,6 +1625,12 @@
 
             if (!isValidName(packageName))
                 continue;
+
+            if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) {
+                log.error(Errors.AddExportsWithRelease(msym));
+                continue;
+            }
+
             PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName));
             p.modle = msym;  // TODO: do we need this?
 
@@ -1688,6 +1706,11 @@
                 continue;
             }
 
+            if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) {
+                log.error(Errors.AddReadsWithRelease(msym));
+                continue;
+            }
+
             for (String targetName : targetNames.split("[ ,]+", -1)) {
                 ModuleSymbol targetModule;
                 if (targetName.equals("ALL-UNNAMED")) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Thu May 11 15:12:38 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java	Fri May 12 06:42:37 2017 +0200
@@ -300,7 +300,8 @@
                 Option.XBOOTCLASSPATH_PREPEND,
                 Option.ENDORSEDDIRS, Option.DJAVA_ENDORSED_DIRS,
                 Option.EXTDIRS, Option.DJAVA_EXT_DIRS,
-                Option.SOURCE, Option.TARGET);
+                Option.SOURCE, Option.TARGET,
+                Option.SYSTEM, Option.UPGRADE_MODULE_PATH);
 
         if (platformString != null) {
             PlatformDescription platformDescription = PlatformUtils.lookupPlatformDescription(platformString);
@@ -331,7 +332,12 @@
                 try {
                     StandardJavaFileManager sfm = (StandardJavaFileManager) fm;
 
-                    sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
+                    if (Source.instance(context).allowModules()) {
+                        sfm.handleOption("--system", Arrays.asList("none").iterator());
+                        sfm.setLocationFromPaths(StandardLocation.UPGRADE_MODULE_PATH, platformCP);
+                    } else {
+                        sfm.setLocationFromPaths(StandardLocation.PLATFORM_CLASS_PATH, platformCP);
+                    }
                 } catch (IOException ex) {
                     log.printLines(PrefixKind.JAVAC, "msg.io");
                     ex.printStackTrace(log.getWriter(WriterKind.NOTICE));
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Thu May 11 15:12:38 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/platform/JDKPlatformProvider.java	Fri May 12 06:42:37 2017 +0200
@@ -26,6 +26,8 @@
 package com.sun.tools.javac.platform;
 
 import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.Charset;
 import java.nio.file.DirectoryStream;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
@@ -41,6 +43,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.stream.Stream;
 
 import javax.annotation.processing.Processor;
 
@@ -90,7 +93,6 @@
             } catch (IOException | ProviderNotFoundException ex) {
             }
         }
-        SUPPORTED_JAVA_PLATFORM_VERSIONS.add(targetNumericVersion(Target.DEFAULT));
     }
 
     private static String targetNumericVersion(Target target) {
@@ -108,10 +110,6 @@
 
         @Override
         public Collection<Path> getPlatformPath() {
-            if (Target.lookup(version) == Target.DEFAULT) {
-                return null;
-            }
-
             List<Path> paths = new ArrayList<>();
             Path file = findCtSym();
             // file == ${jdk.home}/lib/ct.sym
@@ -128,7 +126,21 @@
                 try (DirectoryStream<Path> dir = Files.newDirectoryStream(root)) {
                     for (Path section : dir) {
                         if (section.getFileName().toString().contains(version)) {
-                            paths.add(section);
+                            Path systemModules = section.resolve("system-modules");
+
+                            if (Files.isRegularFile(systemModules)) {
+                                Path modules =
+                                        FileSystems.getFileSystem(URI.create("jrt:/"))
+                                                   .getPath("modules");
+                                try (Stream<String> lines =
+                                        Files.lines(systemModules, Charset.forName("UTF-8"))) {
+                                    lines.map(line -> modules.resolve(line))
+                                         .filter(mod -> Files.exists(mod))
+                                         .forEach(mod -> paths.add(mod));
+                                }
+                            } else {
+                                paths.add(section);
+                            }
                         }
                     }
                 } catch (IOException ex) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu May 11 15:12:38 2017 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri May 12 06:42:37 2017 +0200
@@ -3027,6 +3027,18 @@
 compiler.err.addmods.all.module.path.invalid=\
     --add-modules ALL-MODULE-PATH can only be used when compiling the unnamed module
 
+# 0: symbol
+compiler.err.add.exports.with.release=\
+    exporting a package from system module {0} is not allowed with --release
+
+# 0: symbol
+compiler.err.add.reads.with.release=\
+    adding read edges for system module {0} is not allowed with --release
+
+# 0: symbol
+compiler.err.patch.module.with.release=\
+    patching system module {0} is not allowed in combination with --release
+
 compiler.warn.addopens.ignored=\
     --add-opens has no effect at compile time
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/AddExportsWithRelease.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.add.exports.with.release
+// options: --add-exports java.base/jdk.internal.misc=ALL-UNNAMED --release 9
+
+class AddExportsWithRelease {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/AddReadsWithRelease.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.add.reads.with.release
+// options: --add-reads java.base=java.compiler --release 9
+
+class AddReadsWithRelease {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/PatchModuleWithRelease/PatchModuleWithRelease.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.patch.module.with.release
+// options: --release 9
+
+class PatchModuleWithRelease {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/PatchModuleWithRelease/patchmodule/java.base/java/lang/Test.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact 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;
+
+class Test {
+}
--- a/test/tools/javac/options/release/ReleaseOptionClashes.java	Thu May 11 15:12:38 2017 -0700
+++ b/test/tools/javac/options/release/ReleaseOptionClashes.java	Fri May 12 06:42:37 2017 +0200
@@ -44,17 +44,19 @@
     }
 
     void run() throws Exception {
-        doRunTest("-bootclasspath", "any");
-        doRunTest("-Xbootclasspath:any");
-        doRunTest("-Xbootclasspath/a:any");
-        doRunTest("-Xbootclasspath/p:any");
-        doRunTest("-endorseddirs", "any");
-        doRunTest("-extdirs", "any");
-        doRunTest("-source", "8");
-        doRunTest("-target", "8");
+        doRunTest("7", "-bootclasspath", "any");
+        doRunTest("7", "-Xbootclasspath:any");
+        doRunTest("7", "-Xbootclasspath/a:any");
+        doRunTest("7", "-Xbootclasspath/p:any");
+        doRunTest("7", "-endorseddirs", "any");
+        doRunTest("7", "-extdirs", "any");
+        doRunTest("7", "-source", "8");
+        doRunTest("7", "-target", "8");
+        doRunTest("9", "--system", "none");
+        doRunTest("9", "--upgrade-module-path", "any");
     }
 
-    void doRunTest(String... args) throws Exception {
+    void doRunTest(String release, String... args) throws Exception {
         System.out.println("Testing clashes for arguments: " + Arrays.asList(args));
         Class<?> log = Class.forName("com.sun.tools.javac.util.Log", true, cl);
         Field useRawMessages = log.getDeclaredField("useRawMessages");
@@ -62,7 +64,7 @@
         useRawMessages.setBoolean(null, true);
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         List<String> options = new ArrayList<>();
-        options.addAll(Arrays.asList("--release", "7"));
+        options.addAll(Arrays.asList("--release", release));
         options.addAll(Arrays.asList(args));
         options.add(System.getProperty("test.src") + File.separator + "ReleaseOptionClashes.java");
         compiler.run(null, null, out, options.toArray(new String[0]));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/options/release/ReleaseOptionUnsupported.java	Fri May 12 06:42:37 2017 +0200
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8178152
+ * @summary Verify unsupported modules and module options handling.
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.main
+ *          jdk.compiler/com.sun.tools.javac.jvm
+ *          jdk.jdeps/com.sun.tools.classfile
+ *          jdk.jdeps/com.sun.tools.javap
+ * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavapTask toolbox.TestRunner
+ * @run main ReleaseOptionUnsupported
+ */
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import com.sun.tools.javac.jvm.Target;
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.Task.Expect;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+public class ReleaseOptionUnsupported extends TestRunner {
+
+    private final ToolBox tb = new ToolBox();
+
+    public ReleaseOptionUnsupported() {
+        super(System.err);
+    }
+
+    public static void main(String... args) throws Exception {
+        new ReleaseOptionUnsupported().runTests();
+    }
+
+    @Test
+    public void testUnsafe(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "module m { requires jdk.unsupported; }",
+                          "package test; public class Test { sun.misc.Unsafe unsafe; } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log;
+        List<String> expected = Arrays.asList(
+                "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe",
+                "1 warning"
+        );
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    public void testUnsafeUnnamed(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "package test; public class Test { sun.misc.Unsafe unsafe; } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        List<String> log;
+        List<String> expected = Arrays.asList(
+                "Test.java:1:43: compiler.warn.sun.proprietary: sun.misc.Unsafe",
+                "1 warning"
+        );
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+    }
+
+    @Test
+    public void testAddExports(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "module m { }",
+                          "package test; public class Test { jdk.internal.misc.Unsafe unsafe; } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-exports", "java.base/jdk.internal.misc=m")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> log;
+        List<String> expected;
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-exports", "java.base/jdk.internal.misc=m",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList(
+                "- compiler.err.add.exports.with.release: java.base",
+                "1 error"
+        );
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        //OK to add exports a package of a non-system module:
+        tb.writeJavaFiles(src,
+                          "package test; public class Test { } ");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-exports", "m/test=ALL-UNNAMED",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+    }
+
+    @Test
+    public void testAddReads(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "module m { }",
+                          "package test; public class Test { } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "java.base=m")
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> log;
+        List<String> expected;
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "java.base=m",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList(
+                "- compiler.err.add.reads.with.release: java.base",
+                "1 error"
+        );
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        //OK to add reads a package of a non-system module:
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--add-reads", "m=java.base",
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+    }
+
+    @Test
+    public void testPatchModule(Path base) throws IOException {
+        Path src = base.resolve("src");
+        tb.writeJavaFiles(src,
+                          "module m { }",
+                          "package test; public class Test { } ");
+        Path classes = base.resolve("classes");
+        tb.createDirectories(classes);
+        Path patch = base.resolve("patch");
+        tb.createDirectories(patch);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--patch-module", "java.base=" + patch)
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        List<String> log;
+        List<String> expected;
+
+        log = new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--patch-module", "java.base=" + patch,
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.FAIL)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+
+        expected = Arrays.asList(
+                "- compiler.err.patch.module.with.release: java.base",
+                "1 error"
+        );
+
+        if (!expected.equals(log)) {
+            throw new AssertionError("Unexpected output: " + log);
+        }
+
+        //OK to patch a non-system module:
+        tb.createDirectories(classes);
+
+        new JavacTask(tb)
+                .options("-XDrawDiagnostics",
+                         "--patch-module", "m=" + patch,
+                         "--release", Target.DEFAULT.multiReleaseValue())
+                .outdir(classes)
+                .files(tb.findJavaFiles(src))
+                .run(Expect.SUCCESS)
+                .writeAll()
+                .getOutputLines(Task.OutputKind.DIRECT);
+    }
+
+    protected void runTests() throws Exception {
+        runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+}