# HG changeset patch # User jlahoda # Date 1511256405 -3600 # Node ID 7944849362f3c99e5a2127867e06843e908db1fa # Parent 49e605998d2b8306218e6ddc7d843c6c74c45940 8191112: javac OutOfMemoryError caused by \"-Xlint:exports\" option Summary: When validating type visibility, ignore transitive automatic modules dependencies. Reviewed-by: abuckley, jjg diff -r 49e605998d2b -r 7944849362f3 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Tue Nov 21 01:25:36 2017 -0800 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Tue Nov 21 10:26:45 2017 +0100 @@ -3918,6 +3918,8 @@ todo = todo.tail; if (current == whatPackage.modle) return ; //OK + if ((current.flags() & Flags.AUTOMATIC_MODULE) != 0) + continue; //for automatic modules, don't look into their dependencies for (RequiresDirective req : current.requires) { if (req.isTransitive()) { todo = todo.prepend(req.module); diff -r 49e605998d2b -r 7944849362f3 test/langtools/tools/javac/modules/ExportsUnexported.java --- a/test/langtools/tools/javac/modules/ExportsUnexported.java Tue Nov 21 01:25:36 2017 -0800 +++ b/test/langtools/tools/javac/modules/ExportsUnexported.java Tue Nov 21 10:26:45 2017 +0100 @@ -23,6 +23,7 @@ /* * @test + * @bug 8191112 * @summary tests for module declarations * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -31,12 +32,15 @@ * @run main ExportsUnexported */ +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; +import toolbox.JarTask; import toolbox.JavacTask; import toolbox.Task; @@ -374,4 +378,98 @@ throw new Exception("expected output not found"); } + @Test + public void testTransitiveAndAutomaticModules(Path base) throws Exception { + Path modulePath = base.resolve("module-path"); + + Files.createDirectories(modulePath); + + createAutomaticModule(base, + modulePath.resolve("api-one-1.0.jar"), + "package api1; public interface Api1 {}"); + createAutomaticModule(base, + modulePath.resolve("api-two-1.0.jar"), + "package api2; public interface Api2 {}"); + createAutomaticModule(base, + modulePath.resolve("api-three-1.0.jar"), + "package api3; public interface Api3 {}"); + + Path src = base.resolve("src"); + Path src_api = src.resolve("api"); + tb.writeJavaFiles(src_api, + "module api {\n" + + " requires transitive dep;\n" + + " requires transitive api.one;\n" + + " exports api;\n" + + "}\n", + "package api;\n" + + "public class Api extends dep.Dep implements api2.Api2 {}\n"); + Path src_dep = src.resolve("dep"); + tb.writeJavaFiles(src_dep, + "module dep {\n" + + " requires transitive api.one;\n" + + " exports dep;\n" + + "}\n", + "package dep;\n" + + "public class Dep {}\n"); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + List log = new JavacTask(tb) + .options("-XDrawDiagnostics", + "-Werror", + "--module-source-path", src.toString(), + "--module-path", modulePath.toString(), + "-Xlint:exports,-requires-transitive-automatic") + .outdir(classes) + .files(findJavaFiles(src)) + .run(Task.Expect.FAIL) + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "Api.java:2:49: compiler.warn.leaks.not.accessible.not.required.transitive: kindname.interface, api2.Api2, api.two", + "- compiler.err.warnings.and.werror", + "1 error", + "1 warning" + ); + + if (!log.equals(expected)) + throw new Exception("expected output not found"); + } + + private void createAutomaticModule(Path base, Path jar, String content) throws Exception { + Path scratch = base.resolve("scratch"); + Files.createDirectories(scratch); + tb.cleanDirectory(scratch); + tb.writeJavaFiles(scratch, + content); + Path scratchClasses = base.resolve("scratch-classes"); + Files.createDirectories(scratchClasses); + tb.cleanDirectory(scratchClasses); + + String log = new JavacTask(tb) + .options() + .outdir(scratchClasses) + .files(findJavaFiles(scratch)) + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + if (!log.isEmpty()) { + throw new Exception("unexpected output: " + log); + } + + Files.createDirectories(scratchClasses.getParent()); + Files.deleteIfExists(jar); + + new JarTask(tb, jar) + .baseDir(scratchClasses) + .files(Arrays.stream(tb.findFiles(".class", scratchClasses)) + .map(p -> scratchClasses.relativize(p).toString()) + .collect(Collectors.toList()) + .toArray(new String[0])) + .run(); + } + }