8154705: invalid use of ALL-MODULE-PATH causes crash
Summary: Introducing Modules.initModules as a clear point where the module graphs is initialized in javac
Reviewed-by: jjg, ksrini
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java Wed Jul 20 12:49:32 2016 -0700
@@ -38,6 +38,7 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -148,7 +149,7 @@
private final String addModsOpt;
private final String limitModsOpt;
- private Set<ModuleSymbol> rootModules = Collections.emptySet();
+ private Set<ModuleSymbol> rootModules = null;
public static Modules instance(Context context) {
Modules instance = context.get(Modules.class);
@@ -194,7 +195,31 @@
System.err.println(msg);
}
+ boolean inInitModules;
+ public void initModules(List<JCCompilationUnit> trees, Collection<String> extraAddMods, Collection<String> extraLimitMods) {
+ Assert.check(!inInitModules);
+ try {
+ inInitModules = true;
+ Assert.checkNull(rootModules);
+ enter(trees, modules -> {
+ Assert.checkNull(rootModules);
+ Assert.checkNull(allModules);
+ this.rootModules = modules;
+ setupAllModules(extraAddMods, extraLimitMods); //initialize the module graph
+ Assert.checkNonNull(allModules);
+ inInitModules = false;
+ }, null);
+ } finally {
+ inInitModules = false;
+ }
+ }
+
public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) {
+ Assert.check(rootModules != null || inInitModules || !allowModules);
+ return enter(trees, modules -> {}, c);
+ }
+
+ private boolean enter(List<JCCompilationUnit> trees, Consumer<Set<ModuleSymbol>> init, ClassSymbol c) {
if (!allowModules) {
for (JCCompilationUnit tree: trees) {
tree.modle = syms.noModule;
@@ -212,10 +237,7 @@
setCompilationUnitModules(trees, roots);
- if (!roots.isEmpty() && this.rootModules.isEmpty()) {
- this.rootModules = roots;
- allModules(); //ensure errors reported
- }
+ init.accept(roots);
for (ModuleSymbol msym: roots) {
msym.complete();
@@ -395,6 +417,7 @@
defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
} else {
Assert.check(rootModules.isEmpty());
+ rootModules.add(defaultModule);
}
if (defaultModule != syms.unnamedModule) {
@@ -462,7 +485,7 @@
msym.requires = List.nil();
msym.uses = List.nil();
} else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
- completeAutomaticModule(msym);
+ setupAutomaticModule(msym);
} else {
msym.module_info.complete();
}
@@ -485,7 +508,7 @@
}
};
- private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
+ private void setupAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
try {
ListBuffer<Directive> directives = new ListBuffer<>();
ListBuffer<ExportsDirective> exports = new ListBuffer<>();
@@ -501,28 +524,9 @@
}
}
- ListBuffer<RequiresDirective> requires = new ListBuffer<>();
-
- //ensure all modules are found:
- moduleFinder.findAllModules();
-
- for (ModuleSymbol ms : allModules()) {
- if (ms == syms.unnamedModule || ms == msym)
- continue;
- Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
- EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class);
- RequiresDirective d = new RequiresDirective(ms, flags);
- directives.add(d);
- requires.add(d);
- }
-
- RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
- directives.add(requiresUnnamed);
- requires.add(requiresUnnamed);
-
msym.exports = exports.toList();
msym.provides = List.nil();
- msym.requires = requires.toList();
+ msym.requires = List.nil();
msym.uses = List.nil();
msym.directives = directives.toList();
msym.flags_field |= Flags.ACYCLIC;
@@ -531,6 +535,31 @@
}
}
+ private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure {
+ ListBuffer<Directive> directives = new ListBuffer<>();
+
+ directives.addAll(msym.directives);
+
+ ListBuffer<RequiresDirective> requires = new ListBuffer<>();
+
+ for (ModuleSymbol ms : allModules()) {
+ if (ms == syms.unnamedModule || ms == msym)
+ continue;
+ Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ?
+ EnumSet.of(RequiresFlag.PUBLIC) : EnumSet.noneOf(RequiresFlag.class);
+ RequiresDirective d = new RequiresDirective(ms, flags);
+ directives.add(d);
+ requires.add(d);
+ }
+
+ RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
+ directives.add(requiresUnnamed);
+ requires.add(requiresUnnamed);
+
+ msym.requires = requires.toList();
+ msym.directives = directives.toList();
+ }
+
private Completer getSourceCompleter(JCCompilationUnit tree) {
return new Completer() {
@Override
@@ -541,8 +570,8 @@
JavaFileObject prev = log.useSource(tree.sourcefile);
try {
tree.defs.head.accept(v);
+ checkCyclicDependencies((JCModuleDecl) tree.defs.head);
completeModule(msym);
- checkCyclicDependencies((JCModuleDecl) tree.defs.head);
} finally {
log.useSource(prev);
msym.flags_field &= ~UNATTRIBUTED;
@@ -660,6 +689,9 @@
public Completer getUsesProvidesCompleter() {
return sym -> {
ModuleSymbol msym = (ModuleSymbol) sym;
+
+ msym.complete();
+
Env<AttrContext> env = typeEnvs.get(msym);
UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env);
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
@@ -823,19 +855,29 @@
}
}
- private Set<ModuleSymbol> allModulesCache;
+ private Set<ModuleSymbol> allModules;
- private Set<ModuleSymbol> allModules() {
- if (allModulesCache != null)
- return allModulesCache;
+ public Set<ModuleSymbol> allModules() {
+ Assert.checkNonNull(allModules);
+ return allModules;
+ }
+
+ private void setupAllModules(Collection<String> extraAddMods, Collection<String> extraLimitMods) {
+ Assert.checkNonNull(rootModules);
+ Assert.checkNull(allModules);
Set<ModuleSymbol> observable;
- if (limitModsOpt == null) {
+ if (limitModsOpt == null && extraLimitMods.isEmpty()) {
observable = null;
} else {
Set<ModuleSymbol> limitMods = new HashSet<>();
- for (String limit : limitModsOpt.split(",")) {
+ if (limitModsOpt != null) {
+ for (String limit : limitModsOpt.split(",")) {
+ limitMods.add(syms.enterModule(names.fromString(limit)));
+ }
+ }
+ for (String limit : extraLimitMods) {
limitMods.add(syms.enterModule(names.fromString(limit)));
}
observable = computeTransitiveClosure(limitMods, null);
@@ -870,8 +912,15 @@
enabledRoot.addAll(rootModules);
- if (addModsOpt != null) {
- for (String added : addModsOpt.split(",")) {
+ if (addModsOpt != null || !extraAddMods.isEmpty()) {
+ Set<String> fullAddMods = new HashSet<>();
+ fullAddMods.addAll(extraAddMods);
+
+ if (addModsOpt != null) {
+ fullAddMods.addAll(Arrays.asList(addModsOpt.split(",")));
+ }
+
+ for (String added : fullAddMods) {
Stream<ModuleSymbol> modules;
switch (added) {
case ALL_SYSTEM:
@@ -900,20 +949,7 @@
result.add(syms.unnamedModule);
- if (!rootModules.isEmpty())
- allModulesCache = result;
-
- return result;
- }
-
- public void enableAllModules() {
- allModulesCache = new HashSet<>();
-
- moduleFinder.findAllModules();
-
- for (ModuleSymbol msym : syms.getAllModules()) {
- allModulesCache.add(msym);
- }
+ allModules = result;
}
private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
@@ -975,6 +1011,15 @@
private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>();
private void completeModule(ModuleSymbol msym) {
+ if (inInitModules) {
+ msym.completer = sym -> completeModule(msym);
+ return ;
+ }
+
+ if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) {
+ completeAutomaticModule(msym);
+ }
+
Assert.checkNonNull(msym.requires);
initAddReads();
@@ -1226,9 +1271,9 @@
queue = queue.tail;
if (!nonSyntheticDeps.add(current))
continue;
+ current.complete();
if ((current.flags() & Flags.ACYCLIC) != 0)
continue;
- current.complete();
Assert.checkNonNull(current.requires, () -> current.toString());
for (RequiresDirective dep : current.requires) {
if (!dep.flags.contains(RequiresFlag.EXTRA))
@@ -1264,5 +1309,7 @@
}
public void newRound() {
+ rootModules = null;
+ allModules = null;
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Jul 20 12:49:32 2016 -0700
@@ -27,6 +27,7 @@
import java.io.*;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -1009,15 +1010,10 @@
}
public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) {
- List<JCCompilationUnit> result = initModules(roots, null);
+ modules.initModules(roots, Collections.emptySet(), Collections.emptySet());
if (roots.isEmpty()) {
enterDone = true;
}
- return result;
- }
-
- List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots, ClassSymbol c) {
- modules.enter(roots, c);
return roots;
}
--- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/main/JavadocTool.java Wed Jul 20 12:49:32 2016 -0700
@@ -28,6 +28,7 @@
import java.io.File;
import java.io.IOException;
import java.util.Collection;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -44,6 +45,7 @@
import com.sun.tools.javac.code.ClassFinder;
import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -52,6 +54,7 @@
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
/**
@@ -183,9 +186,8 @@
// Parse file objects provide via the DocumentationTool API
parse(fileObjects, classTrees, true);
- modules.enter(classTrees.toList(), null);
- syms.unnamedModule.complete(); // TEMP to force reading all named modules
+ modules.initModules(classTrees.toList(), Collections.emptySet(), Collections.emptySet());
// Build up the complete list of any packages to be documented
Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH
@@ -386,8 +388,16 @@
private Location getLocation(String packageName) throws IOException {
if (location == StandardLocation.MODULE_SOURCE_PATH) {
// TODO: handle invalid results
- ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
- return fm.getModuleLocation(location, msym.name.toString());
+ Name pack = names.fromString(packageName);
+
+ for (ModuleSymbol msym : modules.allModules()) {
+ PackageSymbol p = syms.getPackage(msym, pack);
+ if (p != null && !p.members().isEmpty()) {
+ return fm.getModuleLocation(location, msym.name.toString());
+ }
+ }
+
+ return null;
} else {
return location;
}
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/JavadocTool.java Wed Jul 20 12:49:32 2016 -0700
@@ -49,6 +49,7 @@
import com.sun.tools.javac.code.Symbol.Completer;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -56,6 +57,7 @@
import com.sun.tools.javac.util.Abort;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Position;
import jdk.javadoc.doclet.DocletEnvironment;
@@ -187,9 +189,8 @@
// Parse file objects provide via the DocumentationTool API
parse(fileObjects, classTrees, true);
- modules.enter(classTrees.toList(), null);
- syms.unnamedModule.complete(); // TEMP to force reading all named modules
+ modules.initModules(classTrees.toList(), Collections.emptySet(), Collections.emptySet());
// Build up the complete list of any packages to be documented
Location location = modules.multiModuleMode ? StandardLocation.MODULE_SOURCE_PATH
@@ -394,11 +395,16 @@
private Location getLocation(String packageName) throws IOException {
if (location == StandardLocation.MODULE_SOURCE_PATH) {
// TODO: handle invalid results better.
- ModuleSymbol msym = syms.inferModule(names.fromString(packageName));
- if (msym == null) {
- return null;
+ Name pack = names.fromString(packageName);
+
+ for (ModuleSymbol msym : modules.allModules()) {
+ PackageSymbol p = syms.getPackage(msym, pack);
+ if (p != null && !p.members().isEmpty()) {
+ return fm.getModuleLocation(location, msym.name.toString());
+ }
}
- return fm.getModuleLocation(location, msym.name.toString());
+
+ return null;
} else {
return location;
}
--- a/langtools/test/tools/javac/6330997/T6330997.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/6330997/T6330997.java Wed Jul 20 12:49:32 2016 -0700
@@ -44,9 +44,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.List;
import javax.tools.ToolProvider;
public class T6330997 {
@@ -57,8 +55,7 @@
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
Symtab syms = Symtab.instance(task.getContext());
- Modules modules = Modules.instance(task.getContext());
- modules.enter(List.nil(), null);
+ task.ensureEntered();
try {
compiler.resolveIdent(syms.unnamedModule, "T1").complete();
} catch (Exception e) {
--- a/langtools/test/tools/javac/T6435291/T6435291.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/T6435291/T6435291.java Wed Jul 20 12:49:32 2016 -0700
@@ -38,9 +38,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.List;
import javax.tools.ToolProvider;
public class T6435291 {
@@ -48,8 +46,7 @@
javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
Symtab syms = Symtab.instance(task.getContext());
- //initialize unnamed module:
- Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
+ task.ensureEntered();
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
try {
compiler.resolveIdent(syms.unnamedModule, "T").complete();
--- a/langtools/test/tools/javac/api/6400303/T6400303.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/api/6400303/T6400303.java Wed Jul 20 12:49:32 2016 -0700
@@ -41,17 +41,14 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symbol.CompletionFailure;
import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.List;
public class T6400303 {
public static void main(String... args) {
javax.tools.JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
Symtab syms = Symtab.instance(task.getContext());
- //initialize unnamed module:
- Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
+ task.ensureEntered();
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
try {
compiler.resolveIdent(syms.unnamedModule, "Test$1").complete();
--- a/langtools/test/tools/javac/api/TestResolveIdent.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/api/TestResolveIdent.java Wed Jul 20 12:49:32 2016 -0700
@@ -36,9 +36,7 @@
import com.sun.tools.javac.api.JavacTaskImpl;
import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.JavaCompiler;
-import com.sun.tools.javac.util.List;
import java.io.IOException;
import javax.tools.ToolProvider;
@@ -54,8 +52,7 @@
JavacTaskImpl task = (JavacTaskImpl)tool.getTask(null, null, null, null, null, null);
JavaCompiler compiler = JavaCompiler.instance(task.getContext());
Symtab syms = Symtab.instance(task.getContext());
- Modules modules = Modules.instance(task.getContext());
- modules.enter(List.nil(), null);
+ task.ensureEntered();
System.out.println(compiler.resolveIdent(syms.unnamedModule, getDeprecatedClass().getCanonicalName()));
}
--- a/langtools/test/tools/javac/defaultMethods/BadClassfile.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/defaultMethods/BadClassfile.java Wed Jul 20 12:49:32 2016 -0700
@@ -42,11 +42,9 @@
import com.sun.tools.javac.code.ClassFinder.BadClassFile;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symtab;
-import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.JCDiagnostic;
-import com.sun.tools.javac.util.List;
import java.io.File;
import java.util.Arrays;
import java.util.Objects;
@@ -74,8 +72,7 @@
JavacTaskImpl task = (JavacTaskImpl) c.getTask(null, null, null, Arrays.asList("-classpath", System.getProperty("test.classes", ".")), null, null);
Symtab syms = Symtab.instance(task.getContext());
- //initialize unnamed module:
- Modules.instance(task.getContext()).enter(List.nil(), syms.errSymbol);
+ task.ensureEntered();
try {
Symbol clazz = com.sun.tools.javac.main.JavaCompiler.instance(task.getContext()).resolveIdent(syms.unnamedModule, classname);
--- a/langtools/test/tools/javac/lib/combo/ReusableContext.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/javac/lib/combo/ReusableContext.java Wed Jul 20 12:49:32 2016 -0700
@@ -41,6 +41,7 @@
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.CompileStates;
import com.sun.tools.javac.comp.Enter;
+import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -92,6 +93,7 @@
((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
Types.instance(this).newRound();
Check.instance(this).newRound();
+ Modules.instance(this).newRound();
CompileStates.instance(this).clear();
MultiTaskListener.instance(this).clear();
--- a/langtools/test/tools/lib/types/TypeHarness.java Thu Jul 28 16:44:39 2016 +0000
+++ b/langtools/test/tools/lib/types/TypeHarness.java Wed Jul 20 12:49:32 2016 -0700
@@ -41,6 +41,7 @@
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.comp.Infer;
import com.sun.tools.javac.comp.InferenceContext;
+import com.sun.tools.javac.comp.Modules;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
@@ -537,6 +538,7 @@
void clear() {
newRound();
+ Modules.instance(context).newRound();
}
}
// </editor-fold>