8197532: Re-examine policy for the default set of modules when compiling or running code on the class path
authoralanb
Sat, 23 Jun 2018 08:03:52 +0100
changeset 50738 6cc2dc161c64
parent 50734 0828a0f6676b
child 50739 4bedc9338137
8197532: Re-examine policy for the default set of modules when compiling or running code on the class path Reviewed-by: jlahoda, mchung
src/java.base/share/classes/java/lang/module/package-info.java
src/java.base/share/classes/jdk/internal/module/DefaultRoots.java
src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java
src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java
test/jdk/jdk/modules/etc/DefaultModules.java
test/jdk/jdk/modules/etc/src/TestJson.java
test/jdk/jdk/modules/etc/src/TestRootModules.java
test/jdk/jdk/modules/etc/src/java.json/javax/json/Json.java
test/jdk/jdk/modules/etc/src/java.json/javax/json/JsonParser.java
test/jdk/jdk/modules/etc/src/java.json/module-info.java
--- a/src/java.base/share/classes/java/lang/module/package-info.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/java.base/share/classes/java/lang/module/package-info.java	Sat Jun 23 08:03:52 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -154,8 +154,9 @@
  * application module specified to the 'java' launcher. When compiling code in
  * the unnamed module, or at run-time when the main application class is loaded
  * from the class path, then the default set of root modules is implementation
- * specific (In the JDK implementation it is the module "java.se", if observable,
- * and every observable module that exports an API). </p>
+ * specific. In the JDK the default set of root modules contains every module
+ * that is observable on the upgrade module path or among the system modules,
+ * and that exports at least one package without qualification. </p>
  *
  * <h2> Observable modules </h2>
  *
--- a/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/DefaultRoots.java	Sat Jun 23 08:03:52 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,13 +22,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package jdk.internal.module;
 
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleFinder;
 import java.lang.module.ModuleReference;
-import java.util.HashSet;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Defines methods to compute the default set of root modules for the unnamed
@@ -36,58 +37,45 @@
  */
 
 public final class DefaultRoots {
-    private static final String JAVA_SE = "java.se";
-
     private DefaultRoots() { }
 
     /**
-     * Returns the default set of root modules for the unnamed module computed from
-     * the system modules observable with the given module finder.
+     * Returns the default set of root modules for the unnamed module from the
+     * modules observable with the intersection of two module finders.
+     *
+     * The first module finder should be the module finder that finds modules on
+     * the upgrade module path or among the system modules. The second module
+     * finder should be the module finder that finds all modules on the module
+     * path, or a subset of when using --limit-modules.
      */
-    static Set<String> compute(ModuleFinder systemModuleFinder, ModuleFinder finder) {
-        Set<String> roots = new HashSet<>();
-
-        boolean hasJava = false;
-        if (systemModuleFinder.find(JAVA_SE).isPresent()) {
-            if (finder == systemModuleFinder || finder.find(JAVA_SE).isPresent()) {
-                // java.se is a system module
-                hasJava = true;
-                roots.add(JAVA_SE);
-            }
-        }
-
-        for (ModuleReference mref : systemModuleFinder.findAll()) {
-            String mn = mref.descriptor().name();
-            if (hasJava && mn.startsWith("java.")) {
-                // not a root
-                continue;
-            }
-
-            if (ModuleResolution.doNotResolveByDefault(mref)) {
-                // not a root
-                continue;
-            }
-
-            if ((finder == systemModuleFinder || finder.find(mn).isPresent())) {
-                // add as root if exports at least one package to all modules
-                ModuleDescriptor descriptor = mref.descriptor();
-                for (ModuleDescriptor.Exports e : descriptor.exports()) {
-                    if (!e.isQualified()) {
-                        roots.add(mn);
-                        break;
-                    }
-                }
-            }
-        }
-
-        return roots;
+    static Set<String> compute(ModuleFinder finder1, ModuleFinder finder2) {
+        return finder1.findAll().stream()
+                .filter(mref -> !ModuleResolution.doNotResolveByDefault(mref))
+                .map(ModuleReference::descriptor)
+                .filter(descriptor -> finder2.find(descriptor.name()).isPresent()
+                                      && exportsAPI(descriptor))
+                .map(ModuleDescriptor::name)
+                .collect(Collectors.toSet());
     }
 
     /**
      * Returns the default set of root modules for the unnamed module from the
      * modules observable with the given module finder.
+     *
+     * This method is used by the jlink system modules plugin.
      */
     public static Set<String> compute(ModuleFinder finder) {
         return compute(finder, finder);
     }
+
+    /**
+     * Returns true if the given module exports a package to all modules
+     */
+    private static boolean exportsAPI(ModuleDescriptor descriptor) {
+        return descriptor.exports()
+                .stream()
+                .filter(e -> !e.isQualified())
+                .findAny()
+                .isPresent();
+    }
 }
--- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Sat Jun 23 08:03:52 2018 +0100
@@ -280,11 +280,10 @@
 
             // 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. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT
-            // bit set in their ModuleResolution attribute flags are excluded from
-            // the default set of roots.
+            // is implemented by resolving all observable modules that export an
+            // API. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT bit set in
+            // their ModuleResolution attribute flags are excluded from the
+            // default set of roots.
             if (mainModule == null || addAllDefaultModules) {
                 roots.addAll(DefaultRoots.compute(systemModuleFinder, finder));
             }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java	Sat Jun 23 08:03:52 2018 +0100
@@ -81,6 +81,7 @@
 import com.sun.tools.javac.code.Types;
 import com.sun.tools.javac.jvm.ClassWriter;
 import com.sun.tools.javac.jvm.JNIWriter;
+import com.sun.tools.javac.jvm.Target;
 import com.sun.tools.javac.main.Option;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
@@ -144,6 +145,7 @@
     private final JavaFileManager fileManager;
     private final ModuleFinder moduleFinder;
     private final Source source;
+    private final Target target;
     private final boolean allowModules;
     private final boolean allowAccessIntoSystem;
 
@@ -191,6 +193,7 @@
         types = Types.instance(context);
         fileManager = context.get(JavaFileManager.class);
         source = Source.instance(context);
+        target = Target.instance(context);
         allowModules = Feature.MODULES.allowedInSource(source);
         Options options = Options.instance(context);
 
@@ -1234,18 +1237,24 @@
         Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>();
 
         if (rootModules.contains(syms.unnamedModule)) {
-            ModuleSymbol javaSE = syms.getModule(java_se);
             Predicate<ModuleSymbol> jdkModulePred;
-
-            if (javaSE != null && (observable == null || observable.contains(javaSE))) {
+            if (target.allApiModulesAreRoots()) {
                 jdkModulePred = sym -> {
                     sym.complete();
-                    return   !sym.name.startsWith(java_)
-                           && sym.exports.stream().anyMatch(e -> e.modules == null);
+                    return sym.exports.stream().anyMatch(e -> e.modules == null);
                 };
-                enabledRoot.add(javaSE);
             } else {
-                jdkModulePred = sym -> true;
+                ModuleSymbol javaSE = syms.getModule(java_se);
+                if (javaSE != null && (observable == null || observable.contains(javaSE))) {
+                    jdkModulePred = sym -> {
+                        sym.complete();
+                        return !sym.name.startsWith(java_)
+                            && sym.exports.stream().anyMatch(e -> e.modules == null);
+                    };
+                    enabledRoot.add(javaSE);
+                } else {
+                    jdkModulePred = sym -> true;
+                }
             }
 
             Predicate<ModuleSymbol> noIncubatorPred = sym -> {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java	Sat Jun 23 08:03:52 2018 +0100
@@ -160,4 +160,11 @@
     public String multiReleaseValue() {
         return Integer.toString(this.ordinal() - Target.JDK1_1.ordinal() + 1);
     }
+
+    /** All modules that export an API are roots when compiling code in the unnamed
+     *  module and targeting 11 or newer.
+     */
+    public boolean allApiModulesAreRoots() {
+        return compareTo(JDK1_11) >= 0;
+    }
 }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java	Fri Jun 22 17:49:21 2018 -0700
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/JdepsConfiguration.java	Sat Jun 23 08:03:52 2018 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -62,6 +62,7 @@
 import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 public class JdepsConfiguration implements AutoCloseable {
@@ -319,7 +320,6 @@
 
     static class SystemModuleFinder implements ModuleFinder {
         private static final String JAVA_HOME = System.getProperty("java.home");
-        private static final String JAVA_SE = "java.se";
 
         private final FileSystem fileSystem;
         private final Path root;
@@ -444,29 +444,15 @@
         }
 
         public Set<String> defaultSystemRoots() {
-            Set<String> roots = new HashSet<>();
-            boolean hasJava = false;
-            if (systemModules.containsKey(JAVA_SE)) {
-                // java.se is a system module
-                hasJava = true;
-                roots.add(JAVA_SE);
-            }
-
-            for (ModuleReference mref : systemModules.values()) {
-                String mn = mref.descriptor().name();
-                if (hasJava && mn.startsWith("java."))
-                    continue;
-
-                // add as root if observable and exports at least one package
-                ModuleDescriptor descriptor = mref.descriptor();
-                for (ModuleDescriptor.Exports e : descriptor.exports()) {
-                    if (!e.isQualified()) {
-                        roots.add(mn);
-                        break;
-                    }
-                }
-            }
-            return roots;
+            return systemModules.values().stream()
+                .map(ModuleReference::descriptor)
+                .filter(descriptor -> descriptor.exports()
+                        .stream()
+                        .filter(e -> !e.isQualified())
+                        .findAny()
+                        .isPresent())
+                .map(ModuleDescriptor::name)
+                .collect(Collectors.toSet());
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/DefaultModules.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please 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 8197532
+ * @modules jdk.compiler
+ *          jdk.jlink
+ *          jdk.zipfs
+ * @library src /lib/testlibrary
+ * @build java.json/*
+ * @run main DefaultModules
+ * @summary Test that all modules that export an API are in the set of modules
+ *          resolved when compiling or running code on the class path
+ */
+
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.util.spi.ToolProvider;
+
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.OutputAnalyzer;
+
+/**
+ * This test compiles and runs the following tests on the class path:
+ *
+ *   TestRootModules.java.java - tests that every module that exports an API
+ *       is resolved. Also tests that java.se is not resolved.
+ *
+ *   TestJson.java - exercises APIs exported by the java.json module. The
+ *       java.json module is not a Java SE module.
+ */
+
+public class DefaultModules {
+    private static final PrintStream out = System.out;
+
+    public static void main(String[] args) throws Exception {
+        String javaHome = System.getProperty("java.home");
+        String testSrc = System.getProperty("test.src");
+
+        // $JDK_HOME/bin/java TestModules.java
+        String source = Path.of(testSrc, "src", "TestRootModules.java").toString();
+        ProcessTools.executeTestJava(source)
+                .outputTo(System.out)
+                .errorTo(System.err)
+                .shouldHaveExitValue(0);
+
+        /**
+         * Create a run-time image containing java.se, java.json and the javac
+         * compiler. Use the run-time image to compile and run both
+         * TestModules.java and JsonTest.java
+         */
+        if (Files.exists(Path.of(javaHome, "jmods", "java.se.jmod"))) {
+            // jlink --add-modules java.se,java.json,jdk.compiler,jdk.zipfs
+            Path here = Path.of(".");
+            Path image = Files.createTempDirectory(here, "images").resolve("myimage");
+            ToolProvider jlink = ToolProvider.findFirst("jlink")
+                    .orElseThrow(() -> new RuntimeException("jlink not found"));
+            int exitCode = jlink.run(System.out, System.err,
+                    "--module-path", System.getProperty("test.module.path"),
+                    "--add-modules", "java.se,java.json,jdk.compiler,jdk.zipfs",
+                    "--output", image.toString());
+            if (exitCode != 0)
+                throw new RuntimeException("jlink failed");
+
+            // path to java launcher in run-time image
+            String javaLauncher = image.resolve("bin").resolve("java").toString();
+            if (System.getProperty("os.name").startsWith("Windows"))
+                javaLauncher += ".exe";
+
+            // $CUSTOM_JDK/bin/java TestRootModules.java
+            source = Path.of(testSrc, "src", "TestRootModules.java").toString();
+            out.format("Command line: [%s %s]%n", javaLauncher, source);
+            ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
+                    .outputTo(System.out)
+                    .errorTo(System.err)
+                    .shouldHaveExitValue(0);
+
+            // $CUSTOM_JDK/bin/java TestJson.java
+            source = Path.of(testSrc, "src", "TestJson.java").toString();
+            out.format("Command line: [%s %s]%n", javaLauncher, source);
+            ProcessTools.executeProcess(new ProcessBuilder(javaLauncher, source))
+                    .outputTo(System.out)
+                    .errorTo(System.err)
+                    .shouldHaveExitValue(0);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/TestJson.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import javax.json.*;
+import java.io.InputStream;
+
+/**
+ * Exercise APIs exported by the java.json module
+ */
+
+public class TestJson {
+    public static void main(String[] args) {
+        JsonParser parser = Json.createParser(InputStream.nullInputStream());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/TestRootModules.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+
+/**
+ * Test the set of modules in the boot layer includes all modules that export
+ * an API. Also test that java.se is not resolved.
+ */
+
+public class TestRootModules {
+    public static void main(String[] args) {
+        // all modules that export an API should be resolved
+        // For now, this test ignores the ModuleResolution attribute
+        ModuleLayer bootLayer = ModuleLayer.boot();
+        ModuleFinder.ofSystem().findAll().stream()
+            .map(ModuleReference::descriptor)
+            .filter(descriptor -> descriptor.exports()
+                    .stream()
+                    .filter(e -> !e.isQualified())
+                    .findAny()
+                    .isPresent())
+            .map(ModuleDescriptor::name)
+            .forEach(name -> {
+                if (!bootLayer.findModule(name).isPresent())
+                    throw new RuntimeException(name + " not in boot layer");
+            });
+
+        // java.se should not be resolved
+        ModuleLayer.boot()
+                .findModule("java.se")
+                .map(m -> { throw new RuntimeException("java.se should not be resolved"); });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/javax/json/Json.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.json;
+
+import java.io.InputStream;
+
+public class Json {
+    private Json() { }
+
+    public static JsonParser createParser(InputStream in) {
+        return new JsonParser() { };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/javax/json/JsonParser.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package javax.json;
+
+public interface JsonParser {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/jdk/modules/etc/src/java.json/module-info.java	Sat Jun 23 08:03:52 2018 +0100
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+module java.json {
+    exports javax.json;
+}