Mercurial > hg > openjdk > lambda > langtools
changeset 2598:097bc67c0099 default tip
Merge
author | henryjen |
---|---|
date | Mon, 11 Nov 2013 23:16:35 -0800 |
parents | 6b4d6205366c (diff) be4bcbd410e9 (current diff) |
children | |
files | .hgtags .jcheck/conf test/tools/javac/Diagnostics/compressed/T8012003c.java test/tools/javac/Diagnostics/compressed/T8012003c.out test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java test/tools/javac/defaultMethods/separate/Separate.java test/tools/javac/diags/examples/BadArgTypesInLambda.java test/tools/javac/lambdaShapes/org/openjdk/tests/separate/Compiler.java test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java test/tools/javac/lambdaShapes/org/openjdk/tests/separate/TestHarness.java test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java |
diffstat | 18 files changed, 571 insertions(+), 239 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Thu Oct 31 14:07:48 2013 -0400 +++ b/.hgtags Mon Nov 11 23:16:35 2013 -0800 @@ -239,3 +239,4 @@ af6244ba81b6b8d1bf4ab06587a2067e021e4570 jdk8-b111 954dd199d6ff3e4cfc42b894c1f611150526eecd jdk8-b112 54150586ba785e1eb0c0de8d13906f643f640644 jdk8-b113 +850d2602ae9811687b0f404d05ec3e55df91d9cb jdk8-b114
--- a/src/share/classes/com/sun/tools/jdeps/Analyzer.java Thu Oct 31 14:07:48 2013 -0400 +++ b/src/share/classes/com/sun/tools/jdeps/Analyzer.java Mon Nov 11 23:16:35 2013 -0800 @@ -26,9 +26,11 @@ import com.sun.tools.classfile.Dependency.Location; import com.sun.tools.jdeps.PlatformClassPath.JDKArchive; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; @@ -52,7 +54,7 @@ private final Type type; private final Map<Archive, ArchiveDeps> results = new HashMap<>(); - private final Map<String, Archive> map = new HashMap<>(); + private final Map<Location, Archive> map = new HashMap<>(); private final Archive NOT_FOUND = new Archive(JdepsTask.getMessage("artifact.not.found")); @@ -69,6 +71,17 @@ * Performs the dependency analysis on the given archives. */ public void run(List<Archive> archives) { + // build a map from Location to Archive + for (Archive archive: archives) { + for (Location l: archive.getClasses()) { + if (!map.containsKey(l)) { + map.put(l, archive); + } else { + // duplicated class warning? + } + } + } + // traverse and analyze all dependencies for (Archive archive : archives) { ArchiveDeps deps; if (type == Type.CLASS || type == Type.VERBOSE) { @@ -76,33 +89,9 @@ } else { deps = new PackageVisitor(archive); } - archive.visit(deps); + archive.visitDependences(deps); results.put(archive, deps); } - - // set the required dependencies - for (ArchiveDeps result: results.values()) { - for (Set<String> set : result.deps.values()) { - for (String target : set) { - Archive source = getArchive(target); - if (result.archive != source) { - String profile = ""; - if (source instanceof JDKArchive) { - profile = result.profile != null ? result.profile.toString() : ""; - if (result.getTargetProfile(target) == null) { - profile += ", JDK internal API"; - // override the value if it accesses any JDK internal - result.requireArchives.put(source, profile); - continue; - } - } - if (!result.requireArchives.containsKey(source)) { - result.requireArchives.put(source, profile); - } - } - } - } - } } public boolean hasDependences(Archive archive) { @@ -117,94 +106,143 @@ * Visits the source archive to its destination archive of * a recorded dependency. */ - void visitArchiveDependence(Archive origin, Archive target, String profile); + void visitArchiveDependence(Archive origin, Archive target, Profile profile); /** * Visits a recorded dependency from origin to target which can be * a fully-qualified classname, a package name, a profile or * archive name depending on the Analyzer's type. */ - void visitDependence(String origin, Archive source, String target, Archive archive, String profile); + void visitDependence(String origin, Archive source, String target, Archive archive, Profile profile); } public void visitArchiveDependences(Archive source, Visitor v) { ArchiveDeps r = results.get(source); - for (Map.Entry<Archive,String> e : r.requireArchives.entrySet()) { - v.visitArchiveDependence(r.archive, e.getKey(), e.getValue()); + for (ArchiveDeps.Dep d: r.requireArchives()) { + v.visitArchiveDependence(r.archive, d.archive, d.profile); } } public void visitDependences(Archive source, Visitor v) { ArchiveDeps r = results.get(source); - for (String origin : r.deps.keySet()) { - for (String target : r.deps.get(origin)) { - Archive archive = getArchive(target); - assert source == getArchive(origin); - Profile profile = r.getTargetProfile(target); - + for (Map.Entry<String, SortedSet<ArchiveDeps.Dep>> e: r.deps.entrySet()) { + String origin = e.getKey(); + for (ArchiveDeps.Dep d: e.getValue()) { // filter intra-dependency unless in verbose mode - if (type == Type.VERBOSE || archive != source) { - v.visitDependence(origin, source, target, archive, - profile != null ? profile.toString() : ""); + if (type == Type.VERBOSE || d.archive != source) { + v.visitDependence(origin, source, d.target, d.archive, d.profile); } } } } - public Archive getArchive(String name) { - return map.containsKey(name) ? map.get(name) : NOT_FOUND; - } - + /** + * ArchiveDeps contains the dependencies for an Archive that + * can have one or more classes. + */ private abstract class ArchiveDeps implements Archive.Visitor { final Archive archive; - final Map<Archive,String> requireArchives; - final SortedMap<String, SortedSet<String>> deps; - Profile profile = null; + final SortedMap<String, SortedSet<Dep>> deps; ArchiveDeps(Archive archive) { this.archive = archive; - this.requireArchives = new HashMap<>(); this.deps = new TreeMap<>(); } - void add(String loc) { - Archive a = map.get(loc); - if (a == null) { - map.put(loc, archive); - } else if (a != archive) { - // duplicated class warning? - } - } - - void add(String origin, String target) { - SortedSet<String> set = deps.get(origin); + void add(String origin, String target, Archive targetArchive, String pkgName) { + SortedSet<Dep> set = deps.get(origin); if (set == null) { deps.put(origin, set = new TreeSet<>()); } - if (!set.contains(target)) { - set.add(target); - // find the corresponding profile - Profile p = getTargetProfile(target); - if (profile == null || (p != null && profile.profile < p.profile)) { - profile = p; + Profile p = targetArchive instanceof JDKArchive + ? Profile.getProfile(pkgName) : null; + set.add(new Dep(target, targetArchive, p)); + } + + /** + * Returns the list of Archive dependences. The returned + * list contains one {@code Dep} instance per one archive + * and with the minimum profile this archive depends on. + */ + List<Dep> requireArchives() { + Map<Archive,Profile> map = new HashMap<>(); + for (Set<Dep> set: deps.values()) { + for (Dep d: set) { + if (this.archive != d.archive) { + Profile p = map.get(d.archive); + if (p == null || (d.profile != null && p.profile < d.profile.profile)) { + map.put(d.archive, d.profile); + } + } } } + List<Dep> list = new ArrayList<>(); + for (Map.Entry<Archive,Profile> e: map.entrySet()) { + list.add(new Dep("", e.getKey(), e.getValue())); + } + return list; + } + + /** + * Dep represents a dependence where the target can be + * a classname or packagename and the archive and profile + * the target belongs to. + */ + class Dep implements Comparable<Dep> { + final String target; + final Archive archive; + final Profile profile; + Dep(String target, Archive archive, Profile p) { + this.target = target; + this.archive = archive; + this.profile = p; + } + + @Override + public boolean equals(Object o) { + if (o instanceof Dep) { + Dep d = (Dep)o; + return this.archive == d.archive && this.target.equals(d.target); + } + return false; + } + + @Override + public int hashCode() { + int hash = 3; + hash = 17 * hash + Objects.hashCode(this.archive); + hash = 17 * hash + Objects.hashCode(this.target); + return hash; + } + + @Override + public int compareTo(Dep o) { + if (this.target.equals(o.target)) { + if (this.archive == o.archive) { + return 0; + } else { + return this.archive.getFileName().compareTo(o.archive.getFileName()); + } + } + return this.target.compareTo(o.target); + } } public abstract void visit(Location o, Location t); - public abstract Profile getTargetProfile(String target); } private class ClassVisitor extends ArchiveDeps { ClassVisitor(Archive archive) { super(archive); } - public void visit(Location l) { - add(l.getClassName()); - } + @Override public void visit(Location o, Location t) { - add(o.getClassName(), t.getClassName()); - } - public Profile getTargetProfile(String target) { - int i = target.lastIndexOf('.'); - return (i > 0) ? Profile.getProfile(target.substring(0, i)) : null; + Archive targetArchive = + this.archive.getClasses().contains(t) ? this.archive : map.get(t); + if (targetArchive == null) { + map.put(t, targetArchive = NOT_FOUND); + } + + String origin = o.getClassName(); + String target = t.getClassName(); + add(origin, target, targetArchive, t.getPackageName()); } } @@ -212,18 +250,21 @@ PackageVisitor(Archive archive) { super(archive); } + @Override public void visit(Location o, Location t) { - add(packageOf(o), packageOf(t)); - } - public void visit(Location l) { - add(packageOf(l)); + Archive targetArchive = + this.archive.getClasses().contains(t) ? this.archive : map.get(t); + if (targetArchive == null) { + map.put(t, targetArchive = NOT_FOUND); + } + + String origin = packageOf(o); + String target = packageOf(t); + add(origin, target, targetArchive, t.getPackageName()); } - private String packageOf(Location loc) { - String pkg = loc.getPackageName(); + public String packageOf(Location o) { + String pkg = o.getPackageName(); return pkg.isEmpty() ? "<unnamed>" : pkg; } - public Profile getTargetProfile(String target) { - return Profile.getProfile(target); - } } }
--- a/src/share/classes/com/sun/tools/jdeps/Archive.java Thu Oct 31 14:07:48 2013 -0400 +++ b/src/share/classes/com/sun/tools/jdeps/Archive.java Mon Nov 11 23:16:35 2013 -0800 @@ -67,6 +67,7 @@ deps.put(origin, set); } } + public void addClass(Location origin, Location target) { Set<Location> set = deps.get(origin); if (set == null) { @@ -76,21 +77,27 @@ set.add(target); } - public void visit(Visitor v) { + public Set<Location> getClasses() { + return deps.keySet(); + } + + public void visitDependences(Visitor v) { for (Map.Entry<Location,Set<Location>> e: deps.entrySet()) { - v.visit(e.getKey()); for (Location target : e.getValue()) { v.visit(e.getKey(), target); } } } + public String getPathName() { + return path != null ? path.toString() : filename; + } + public String toString() { - return path != null ? path.toString() : filename; + return filename; } interface Visitor { - void visit(Location loc); void visit(Location origin, Location target); } }
--- a/src/share/classes/com/sun/tools/jdeps/JdepsTask.java Thu Oct 31 14:07:48 2013 -0400 +++ b/src/share/classes/com/sun/tools/jdeps/JdepsTask.java Mon Nov 11 23:16:35 2013 -0800 @@ -190,6 +190,11 @@ task.options.fullVersion = true; } }, + new HiddenOption(false, "-showlabel") { + void process(JdepsTask task, String opt, String arg) { + task.options.showLabel = true; + } + }, new HiddenOption(true, "-depth") { void process(JdepsTask task, String opt, String arg) throws BadArgs { try { @@ -279,12 +284,21 @@ private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException { Path summary = dir.resolve("summary.dot"); - try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary)); - DotFileFormatter formatter = new DotFileFormatter(sw, "summary")) { - for (Archive archive : sourceLocations) { - analyzer.visitArchiveDependences(archive, formatter); + boolean verbose = options.verbose == Analyzer.Type.VERBOSE; + DotGraph<?> graph = verbose ? new DotSummaryForPackage() + : new DotSummaryForArchive(); + for (Archive archive : sourceLocations) { + analyzer.visitArchiveDependences(archive, graph); + if (verbose || options.showLabel) { + // traverse detailed dependences to generate package-level + // summary or build labels for edges + analyzer.visitDependences(archive, graph); } } + try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary))) { + graph.writeTo(sw); + } + // output individual .dot file for each archive if (options.verbose != Analyzer.Type.SUMMARY) { for (Archive archive : sourceLocations) { if (analyzer.hasDependences(archive)) { @@ -365,17 +379,16 @@ } } } + sourceLocations.addAll(archives); List<Archive> classpaths = new ArrayList<>(); // for class file lookup + classpaths.addAll(getClassPathArchives(options.classpath)); if (options.includePattern != null) { - archives.addAll(getClassPathArchives(options.classpath)); - } else { - classpaths.addAll(getClassPathArchives(options.classpath)); + archives.addAll(classpaths); } classpaths.addAll(PlatformClassPath.getArchives()); - // add all archives to the source locations for reporting - sourceLocations.addAll(archives); + // add all classpath archives to the source locations for reporting sourceLocations.addAll(classpaths); // Work queue of names of classfiles to be searched. @@ -557,6 +570,7 @@ boolean showSummary; boolean wildcard; boolean apiOnly; + boolean showLabel; String dotOutputDir; String classpath = ""; int depth = 1; @@ -627,16 +641,34 @@ return result; } + /** + * If the given archive is JDK archive and non-null Profile, + * this method returns the profile name only if -profile option is specified; + * a null profile indicates it accesses a private JDK API and this method + * will return "JDK internal API". + * + * For non-JDK archives, this method returns the file name of the archive. + */ + private String getProfileArchiveInfo(Archive source, Profile profile) { + if (options.showProfile && profile != null) + return profile.toString(); + + if (source instanceof JDKArchive) { + return profile == null ? "JDK internal API (" + source.getFileName() + ")" : ""; + } + return source.getFileName(); + } /** - * Returns the file name of the archive for non-JRE class or - * internal JRE classes. It returns empty string for SE API. + * Returns the profile name or "JDK internal API" for JDK archive; + * otherwise empty string. */ - private static String getArchiveName(Archive source, String profile) { - String name = source.getFileName(); - if (source instanceof JDKArchive) - return profile.isEmpty() ? "JDK internal API (" + name + ")" : ""; - return name; + private String profileName(Archive archive, Profile profile) { + if (archive instanceof JDKArchive) { + return Objects.toString(profile, "JDK internal API"); + } else { + return ""; + } } class RawOutputFormatter implements Analyzer.Visitor { @@ -648,21 +680,18 @@ private String pkg = ""; @Override public void visitDependence(String origin, Archive source, - String target, Archive archive, String profile) { + String target, Archive archive, Profile profile) { if (!origin.equals(pkg)) { pkg = origin; writer.format(" %s (%s)%n", origin, source.getFileName()); } - String name = (options.showProfile && !profile.isEmpty()) - ? profile - : getArchiveName(archive, profile); - writer.format(" -> %-50s %s%n", target, name); + writer.format(" -> %-50s %s%n", target, getProfileArchiveInfo(archive, profile)); } @Override - public void visitArchiveDependence(Archive origin, Archive target, String profile) { - writer.format("%s -> %s", origin, target); - if (options.showProfile && !profile.isEmpty()) { + public void visitArchiveDependence(Archive origin, Archive target, Profile profile) { + writer.format("%s -> %s", origin.getPathName(), target.getPathName()); + if (options.showProfile && profile != null) { writer.format(" (%s)%n", profile); } else { writer.format("%n"); @@ -670,19 +699,14 @@ } } - class DotFileFormatter implements Analyzer.Visitor, AutoCloseable { + class DotFileFormatter extends DotGraph<String> implements AutoCloseable { private final PrintWriter writer; private final String name; - DotFileFormatter(PrintWriter writer, String name) { - this.writer = writer; - this.name = name; - writer.format("digraph \"%s\" {%n", name); - } DotFileFormatter(PrintWriter writer, Archive archive) { this.writer = writer; this.name = archive.getFileName(); writer.format("digraph \"%s\" {%n", name); - writer.format(" // Path: %s%n", archive.toString()); + writer.format(" // Path: %s%n", archive.getPathName()); } @Override @@ -690,39 +714,169 @@ writer.println("}"); } - private final Set<String> edges = new HashSet<>(); - private String node = ""; @Override public void visitDependence(String origin, Archive source, - String target, Archive archive, String profile) { - if (!node.equals(origin)) { - edges.clear(); - node = origin; - } + String target, Archive archive, Profile profile) { // if -P option is specified, package name -> profile will // be shown and filter out multiple same edges. - if (!edges.contains(target)) { - StringBuilder sb = new StringBuilder(); - String name = options.showProfile && !profile.isEmpty() - ? profile - : getArchiveName(archive, profile); - writer.format(" %-50s -> %s;%n", - String.format("\"%s\"", origin), - name.isEmpty() ? String.format("\"%s\"", target) - : String.format("\"%s (%s)\"", target, name)); - edges.add(target); + String name = getProfileArchiveInfo(archive, profile); + writeEdge(writer, new Edge(origin, target, getProfileArchiveInfo(archive, profile))); + } + @Override + public void visitArchiveDependence(Archive origin, Archive target, Profile profile) { + throw new UnsupportedOperationException(); + } + } + + class DotSummaryForArchive extends DotGraph<Archive> { + @Override + public void visitDependence(String origin, Archive source, + String target, Archive archive, Profile profile) { + Edge e = findEdge(source, archive); + assert e != null; + // add the dependency to the label if enabled and not compact1 + if (profile == Profile.COMPACT1) { + return; + } + e.addLabel(origin, target, profileName(archive, profile)); + } + @Override + public void visitArchiveDependence(Archive origin, Archive target, Profile profile) { + // add an edge with the archive's name with no tag + // so that there is only one node for each JDK archive + // while there may be edges to different profiles + Edge e = addEdge(origin, target, ""); + if (target instanceof JDKArchive) { + // add a label to print the profile + if (profile == null) { + e.addLabel("JDK internal API"); + } else if (options.showProfile && !options.showLabel) { + e.addLabel(profile.toString()); + } } } + } + // DotSummaryForPackage generates the summary.dot file for verbose mode + // (-v or -verbose option) that includes all class dependencies. + // The summary.dot file shows package-level dependencies. + class DotSummaryForPackage extends DotGraph<String> { + private String packageOf(String cn) { + int i = cn.lastIndexOf('.'); + return i > 0 ? cn.substring(0, i) : "<unnamed>"; + } + @Override + public void visitDependence(String origin, Archive source, + String target, Archive archive, Profile profile) { + // add a package dependency edge + String from = packageOf(origin); + String to = packageOf(target); + Edge e = addEdge(from, to, getProfileArchiveInfo(archive, profile)); + + // add the dependency to the label if enabled and not compact1 + if (!options.showLabel || profile == Profile.COMPACT1) { + return; + } + + // trim the package name of origin to shorten the label + int i = origin.lastIndexOf('.'); + String n1 = i < 0 ? origin : origin.substring(i+1); + e.addLabel(n1, target, profileName(archive, profile)); + } @Override - public void visitArchiveDependence(Archive origin, Archive target, String profile) { - String name = options.showProfile && !profile.isEmpty() - ? profile : ""; - writer.format(" %-30s -> \"%s\";%n", - String.format("\"%s\"", origin.getFileName()), - name.isEmpty() - ? target.getFileName() - : String.format("%s (%s)", target.getFileName(), name)); + public void visitArchiveDependence(Archive origin, Archive target, Profile profile) { + // nop + } + } + abstract class DotGraph<T> implements Analyzer.Visitor { + private final Set<Edge> edges = new LinkedHashSet<>(); + private Edge curEdge; + public void writeTo(PrintWriter writer) { + writer.format("digraph \"summary\" {%n"); + for (Edge e: edges) { + writeEdge(writer, e); + } + writer.println("}"); + } + + void writeEdge(PrintWriter writer, Edge e) { + writer.format(" %-50s -> \"%s\"%s;%n", + String.format("\"%s\"", e.from.toString()), + e.tag.isEmpty() ? e.to + : String.format("%s (%s)", e.to, e.tag), + getLabel(e)); + } + + Edge addEdge(T origin, T target, String tag) { + Edge e = new Edge(origin, target, tag); + if (e.equals(curEdge)) { + return curEdge; + } + + if (edges.contains(e)) { + for (Edge e1 : edges) { + if (e.equals(e1)) { + curEdge = e1; + } + } + } else { + edges.add(e); + curEdge = e; + } + return curEdge; + } + + Edge findEdge(T origin, T target) { + for (Edge e : edges) { + if (e.from.equals(origin) && e.to.equals(target)) { + return e; + } + } + return null; + } + + String getLabel(Edge e) { + String label = e.label.toString(); + return label.isEmpty() ? "" : String.format("[label=\"%s\",fontsize=9]", label); + } + + class Edge { + final T from; + final T to; + final String tag; // optional tag + final StringBuilder label = new StringBuilder(); + Edge(T from, T to, String tag) { + this.from = from; + this.to = to; + this.tag = tag; + } + void addLabel(String s) { + label.append(s).append("\\n"); + } + void addLabel(String origin, String target, String profile) { + label.append(origin).append(" -> ").append(target); + if (!profile.isEmpty()) { + label.append(" (" + profile + ")"); + } + label.append("\\n"); + } + @Override @SuppressWarnings("unchecked") + public boolean equals(Object o) { + if (o instanceof DotGraph<?>.Edge) { + DotGraph<?>.Edge e = (DotGraph<?>.Edge)o; + return this.from.equals(e.from) && + this.to.equals(e.to) && + this.tag.equals(e.tag); + } + return false; + } + @Override + public int hashCode() { + int hash = 7; + hash = 67 * hash + Objects.hashCode(this.from) + + Objects.hashCode(this.to) + Objects.hashCode(this.tag); + return hash; + } } } }
--- a/src/share/classes/com/sun/tools/jdeps/Profile.java Thu Oct 31 14:07:48 2013 -0400 +++ b/src/share/classes/com/sun/tools/jdeps/Profile.java Mon Nov 11 23:16:35 2013 -0800 @@ -81,8 +81,12 @@ } static class PackageToProfile { + static String[] JAVAX_CRYPTO_PKGS = new String[] { + "javax.crypto", + "javax.crypto.interfaces", + "javax.crypto.spec" + }; static Map<String, Profile> map = initProfiles(); - private static Map<String, Profile> initProfiles() { try { String profilesProps = System.getProperty("jdeps.profiles"); @@ -103,6 +107,9 @@ findProfile(cf); } } + // special case for javax.crypto.* classes that are not + // included in ct.sym since they are in jce.jar + Collections.addAll(Profile.COMPACT1.packages, JAVAX_CRYPTO_PKGS); } } } catch (IOException | ConstantPoolException e) {
--- a/test/tools/javac/ExtDirs/ExtDirTest.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/javac/ExtDirs/ExtDirTest.java Mon Nov 11 23:16:35 2013 -0800 @@ -112,11 +112,6 @@ } void createJars() throws Exception { - -// for i in 1 2 3; do -// if test ! -d ext${i}; then mkdir ext${i}; fi -// cp ${TESTSRC}${FS}ext${i}${FS}*.jar ext${i} -// done sun.tools.jar.Main jarGenerator = new sun.tools.jar.Main(System.out, System.err, "jar"); @@ -155,19 +150,19 @@ void compileWithExtDirs() throws Exception { -//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext1 "${TESTSRC}${FS}ExtDirTest_1.java" +//javac -extdirs ext1 ExtDirTest_1.java ToolBox.JavaToolArgs params = new ToolBox.JavaToolArgs() .setOptions("-d", ".", "-extdirs", "ext1") .setSources(ExtDirTest_1Src); ToolBox.javac(params); -//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext1${PS}ext2 "${TESTSRC}${FS}ExtDirTest_2.java" +//javac -extdirs ext1:ext2 ExtDirTest_2.java params.setOptions("-d", ".", "-extdirs", "ext1" + File.pathSeparator + "ext2") .setSources(ExtDirTest_2Src); ToolBox.javac(params); -//"$javac" ${TESTTOOLVMOPTS} -d . -extdirs ext3 "${TESTSRC}${FS}ExtDirTest_3.java" +//javac -extdirs ext3 ExtDirTest_3.java params.setOptions("-d", ".", "-extdirs", "ext3") .setSources(ExtDirTest_3Src); ToolBox.javac(params);
--- a/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/Compiler.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/Compiler.java Mon Nov 11 23:16:35 2013 -0800 @@ -46,7 +46,7 @@ USECACHE // Keeps results around for reuse. Only use this is // you're sure that each compilation name maps to the // same source code - }; + } private static final AtomicInteger counter = new AtomicInteger(); private static final String targetDir = "gen-separate"; @@ -85,7 +85,7 @@ } public void setFlags(Flags ... flags) { - this.flags = new HashSet<Flags>(Arrays.asList(flags)); + this.flags = new HashSet<>(Arrays.asList(flags)); } public void addPostprocessor(ClassFilePreprocessor cfp) { @@ -131,17 +131,10 @@ outputDirs.put(type.getName(), outDir); Class superClass = type.getSuperclass(); - if (superClass != null) { - for( Map.Entry<String,File> each : compileHierarchy(superClass).entrySet()) { - outputDirs.put(each.getKey(), each.getValue()); - } - } - for (Extends ext : type.getSupertypes()) { - Type iface = ext.getType(); - for( Map.Entry<String,File> each : compileHierarchy(iface).entrySet()) { - outputDirs.put(each.getKey(), each.getValue()); - } - } + if (superClass != null) + outputDirs.putAll(compileHierarchy(superClass)); + for (Extends ext : type.getSupertypes()) + outputDirs.putAll(compileHierarchy(ext.getType())); return outputDirs; } @@ -157,8 +150,12 @@ SourceProcessor accum = (name, src) -> { files.add(new SourceFile(name, src)); }; - for (Type dep : type.typeDependencies()) { - dep.generateAsDependency(accum, type.methodDependencies()); + Collection<Type> deps = type.typeDependencies(type.isFullCompilation()); + for (Type dep : deps) { + if (type.isFullCompilation()) + dep.generate(accum); + else + dep.generateAsDependency(accum, type.methodDependencies()); } type.generate(accum); @@ -185,7 +182,7 @@ StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); } catch (IOException e) { throw new RuntimeException( - "IOException encountered during compilation"); + "IOException encountered during compilation", e); } Boolean result = ct.call(); if (result == Boolean.FALSE) {
--- a/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/SourceModel.java Mon Nov 11 23:16:35 2013 -0800 @@ -48,7 +48,7 @@ generate(pw); return sw.toString(); } - }; + } public static class AccessFlag extends Element { private String flag; @@ -125,6 +125,7 @@ // (and thus will be present in stubs) private Set<Method> methodDependencies; private List<Type> typeDependencies; + private boolean fullCompilation; protected Type(String name, List<AccessFlag> flags, List<TypeParameter> params, @@ -214,6 +215,14 @@ methodDependencies.add(m); } + public boolean isFullCompilation() { + return fullCompilation; + } + + public void setFullCompilation(boolean fullCompilation) { + this.fullCompilation = fullCompilation; + } + // Convenience method for creating an Extends object using this // class and specified type arguments. public Extends with(String ... args) { @@ -255,14 +264,23 @@ pw.println("}"); } - public Collection<Type> typeDependencies() { + public Collection<Type> typeDependencies(boolean recursive) { HashMap<String,Type> dependencies = new HashMap<>(); Type superclass = getSuperclass(); if (superclass != null) { dependencies.put(superclass.getName(), superclass); + if (recursive) { + for (Type t : superclass.typeDependencies(true)) + dependencies.put(t.getName(), t); + } } - for (Extends e : getSupertypes()) + for (Extends e : getSupertypes()) { dependencies.put(e.getType().getName(), e.getType()); + if (recursive) { + for (Type t : e.getType().typeDependencies(true)) + dependencies.put(t.getName(), t); + } + } // Do these last so that they override for (Type t : this.typeDependencies) dependencies.put(t.getName(), t);
--- a/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/TestHarness.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/separate/TestHarness.java Mon Nov 11 23:16:35 2013 -0800 @@ -198,7 +198,7 @@ assertEquals(res, value); } } catch (InvocationTargetException | IllegalAccessException e) { - fail("Unexpected exception thrown: " + e.getCause()); + fail("Unexpected exception thrown: " + e.getCause(), e.getCause()); } } @@ -227,8 +227,7 @@ * a return type of 'int', and no arguments. */ public void assertInvokeVirtualEquals(int value, Class target) { - assertInvokeVirtualEquals( - new Integer(value), target, stdCM, "-1"); + assertInvokeVirtualEquals(value, target, stdCM, "-1"); } /** @@ -260,12 +259,31 @@ Compiler compiler = compilerLocal.get(); compiler.setFlags(compilerFlags()); - assertInvokeInterfaceEquals( - new Integer(value), target, new Extends(iface), stdAM); + assertInvokeInterfaceEquals(value, target, new Extends(iface), stdAM); compiler.cleanup(); } + protected void assertInvokeInterfaceThrows(java.lang.Class<? extends Throwable> errorClass, + Class target, Extends iface, AbstractMethod method, + String... args) { + try { + assertInvokeInterfaceEquals(0, target, iface, method, args); + fail("Expected exception: " + errorClass); + } + catch (AssertionError e) { + Throwable cause = e.getCause(); + if (cause == null) + throw e; + else if ((errorClass.isAssignableFrom(cause.getClass()))) { + // this is success + return; + } + else + throw e; + } + } + /** * Creates a class which calls target::method(args) via invokevirtual, * compiles and loads both the new class and 'target', and then invokes
--- a/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/javac/lambdaShapes/org/openjdk/tests/vm/DefaultMethodsTest.java Mon Nov 11 23:16:35 2013 -0800 @@ -25,18 +25,22 @@ package org.openjdk.tests.vm; -import java.lang.reflect.*; -import java.util.*; -import java.io.File; -import java.io.IOException; - +import org.openjdk.tests.separate.Compiler; +import org.openjdk.tests.separate.TestHarness; import org.testng.annotations.Test; -import org.openjdk.tests.separate.*; -import org.openjdk.tests.separate.Compiler; -import static org.testng.Assert.*; -import static org.openjdk.tests.separate.SourceModel.*; +import static org.openjdk.tests.separate.SourceModel.AbstractMethod; +import static org.openjdk.tests.separate.SourceModel.AccessFlag; import static org.openjdk.tests.separate.SourceModel.Class; +import static org.openjdk.tests.separate.SourceModel.ConcreteMethod; +import static org.openjdk.tests.separate.SourceModel.DefaultMethod; +import static org.openjdk.tests.separate.SourceModel.Extends; +import static org.openjdk.tests.separate.SourceModel.Interface; +import static org.openjdk.tests.separate.SourceModel.MethodParameter; +import static org.openjdk.tests.separate.SourceModel.TypeParameter; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.fail; @Test(groups = "vm") public class DefaultMethodsTest extends TestHarness { @@ -186,7 +190,7 @@ * TEST: D d = new D(); d.m() == 22; * TEST: I i = new D(); i.m() == 22; */ - void testExistingInheritedOverride() { + public void testExistingInheritedOverride() { Interface I = new Interface("I", DefaultMethod.std("99")); Class C = new Class("C", I, ConcreteMethod.std("11")); Class D = new Class("D", C, ConcreteMethod.std("22")); @@ -258,7 +262,6 @@ * TEST: C c = new C(); c.m() throws ICCE */ public void testConflict() { - // debugTest(); Interface I = new Interface("I", DefaultMethod.std("99")); Interface J = new Interface("J", DefaultMethod.std("88")); Class C = new Class("C", I, J); @@ -390,19 +393,16 @@ /** * interface I<T> { default int m(T t) { return 99; } } - * Class C implements I<String> { public int m() { return 88; } } + * Class C implements I<String> { public int m(String s) { return 88; } } * - * TEST: C c = new C(); c.m() == 88; - * TEST: I i = new C(); i.m() == 88; + * TEST: C c = new C(); c.m("string") == 88; + * TEST: I i = new C(); i.m("string") == 88; */ - @Test(enabled=false) public void testSelfFill() { // This test ensures that a concrete method overrides a default method // that matches at the language-level, but has a different method // signature due to erasure. - // debugTest(); - DefaultMethod dm = new DefaultMethod( "int", "m", "return 99;", new MethodParameter("T", "t")); ConcreteMethod cm = new ConcreteMethod( @@ -415,9 +415,11 @@ AbstractMethod pm = new AbstractMethod( "int", "m", new MethodParameter("T", "t")); - assertInvokeVirtualEquals(new Integer(88), C, cm, "-1", "\"string\""); - assertInvokeInterfaceEquals( - new Integer(88), C, I.with("String"), pm, "\"string\""); + assertInvokeVirtualEquals(88, C, cm, "-1", "\"string\""); + assertInvokeInterfaceEquals(99, C, I.with("String"), pm, "\"string\""); + + C.setFullCompilation(true); // Force full bridge generation + assertInvokeInterfaceEquals(88, C, I.with("String"), pm, "\"string\""); } /** @@ -485,7 +487,6 @@ * TEST: J<String,String> j = new C(); j.m("A","B","C") == 88; * TEST: K<String> k = new C(); k.m("A","B","C") == 88; */ - @Test(enabled=false) public void testBridges() { DefaultMethod dm = new DefaultMethod("int", stdMethodName, "return 99;", new MethodParameter("T", "t"), new MethodParameter("V", "v"), @@ -518,13 +519,17 @@ J.with("String", "T"), pm2); Class C = new Class("C", K.with("String"), cm); + // First, without compiler bridges String[] args = new String[] { "\"A\"", "\"B\"", "\"C\"" }; - assertInvokeInterfaceEquals(new Integer(88), C, - I.with("String", "String", "String"), pm0, args); - assertInvokeInterfaceEquals(new Integer(88), C, - J.with("String", "String"), pm1, args); - assertInvokeInterfaceEquals(new Integer(88), C, - K.with("String"), pm2, args); + assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), pm0, args); + assertInvokeInterfaceThrows(AbstractMethodError.class, C, J.with("String", "String"), pm1, args); + assertInvokeInterfaceThrows(AbstractMethodError.class, C, K.with("String"), pm2, args); + + // Then with compiler bridges + C.setFullCompilation(true); + assertInvokeInterfaceEquals(88, C, I.with("String", "String", "String"), pm0, args); + assertInvokeInterfaceEquals(88, C, J.with("String", "String"), pm1, args); + assertInvokeInterfaceEquals(88, C, K.with("String"), pm2, args); } /** @@ -536,8 +541,6 @@ * TEST: I i = new C(); i.m() == 88; */ public void testSuperBasic() { - // debugTest(); - Interface J = new Interface("J", DefaultMethod.std("88")); Interface I = new Interface("I", J, new DefaultMethod( "int", stdMethodName, "return J.super.m();")); @@ -559,8 +562,6 @@ * TODO: add case for K k = new C(); k.m() throws ICCE */ public void testSuperConflict() { - // debugTest(); - Interface K = new Interface("K", DefaultMethod.std("99")); Interface L = new Interface("L", DefaultMethod.std("101")); Interface J = new Interface("J", K, L); @@ -635,8 +636,7 @@ AbstractMethod pm = new AbstractMethod("int", stdMethodName, new MethodParameter("String", "s")); - assertInvokeInterfaceEquals( - new Integer(88), C, new Extends(I), pm, "\"\""); + assertInvokeInterfaceEquals(88, C, new Extends(I), pm, "\"\""); } /** @@ -674,7 +674,6 @@ * class S { Object foo() { return (new D()).m(); } // link sig: ()LInteger; * TEST: S s = new S(); s.foo() == new Integer(99) */ - @Test(enabled=false) public void testCovarBridge() { Interface I = new Interface("I", new DefaultMethod( "Integer", "m", "return new Integer(88);")); @@ -692,7 +691,8 @@ S.addCompilationDependency(Dstub); S.addCompilationDependency(DstubMethod); - assertInvokeVirtualEquals(new Integer(99), S, toCall, "null"); + // NEGATIVE test for separate compilation -- dispatches to I, not C + assertInvokeVirtualEquals(88, S, toCall, "null"); } /** @@ -719,7 +719,7 @@ S.addCompilationDependency(Dstub); S.addCompilationDependency(DstubMethod); - assertInvokeVirtualEquals(new Integer(88), S, toCall, "null"); + assertInvokeVirtualEquals(88, S, toCall, "null"); } /** @@ -757,7 +757,6 @@ * Test that a erased-signature-matching method does not implement * non-language-level matching methods */ - @Test(enabled=false) public void testNonConcreteFill() { AbstractMethod ipm = new AbstractMethod("int", "m", new MethodParameter("T", "t"), @@ -781,13 +780,14 @@ new MethodParameter("T", "t"), new MethodParameter("String", "s"), new MethodParameter("String", "w")); + DefaultMethod kdm = new DefaultMethod("int", "m", "return 99;", + new MethodParameter("T", "t"), + new MethodParameter("String", "v"), + new MethodParameter("String", "w")); Interface K = new Interface("K", new TypeParameter("T"), J.with("T", "String"), - new DefaultMethod("int", "m", "return 99;", - new MethodParameter("T", "t"), - new MethodParameter("String", "v"), - new MethodParameter("String", "w"))); + kdm); Class C = new Class("C", K.with("String"), @@ -797,13 +797,18 @@ new MethodParameter("Object", "v"), new MethodParameter("String", "w"))); + // First, without compiler bridges String a = "\"\""; - assertInvokeInterfaceEquals(99, C, - K.with("String"), kpm, a, a, a); - assertInvokeInterfaceEquals(77, C, - J.with("String", "String"), jpm, a, a, a); - assertInvokeInterfaceEquals(99, C, - I.with("String", "String", "String"), ipm, a, a, a); + assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a); + assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a); + assertInvokeInterfaceThrows(AbstractMethodError.class, C, I.with("String", "String", "String"), ipm, a, a, a); + + // Now, with bridges + J.setFullCompilation(true); + K.setFullCompilation(true); + assertInvokeInterfaceEquals(99, C, K.with("String"), kpm, a, a, a); + assertInvokeInterfaceEquals(77, C, J.with("String", "String"), jpm, a, a, a); + assertInvokeInterfaceEquals(99, C, I.with("String", "String", "String"), ipm, a, a, a); } public void testStrictfpDefault() {
--- a/test/tools/jdeps/Basic.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/jdeps/Basic.java Mon Nov 11 23:16:35 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -23,9 +23,9 @@ /* * @test - * @bug 8003562 8005428 8015912 + * @bug 8003562 8005428 8015912 8027481 * @summary Basic tests for jdeps tool - * @build Test p.Foo + * @build Test p.Foo p.Bar javax.activity.NotCompactProfile * @run main Basic */ @@ -33,10 +33,12 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.regex.*; +import static java.nio.file.StandardCopyOption.*; public class Basic { private static boolean symbolFileExist = initProfiles(); @@ -74,23 +76,25 @@ new String[] {"java.lang", "p"}, new String[] {"compact1", "not found"}); // test a directory + // also test non-SE javax.activity class dependency test(new File(testDir, "p"), - new String[] {"java.lang", "java.util", "java.lang.management"}, - new String[] {"compact1", "compact1", "compact3"}); + new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"}, + new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"}, + new String[] {"-classpath", testDir.getPath()}); // test class-level dependency output test(new File(testDir, "Test.class"), - new String[] {"java.lang.Object", "java.lang.String", "p.Foo"}, - new String[] {"compact1", "compact1", "not found"}, + new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, + new String[] {"compact1", "compact1", "not found", "not found"}, new String[] {"-verbose:class"}); // test -p option test(new File(testDir, "Test.class"), - new String[] {"p.Foo"}, - new String[] {"not found"}, + new String[] {"p.Foo", "p.Bar"}, + new String[] {"not found", "not found"}, new String[] {"-verbose:class", "-p", "p"}); // test -e option test(new File(testDir, "Test.class"), - new String[] {"p.Foo"}, - new String[] {"not found"}, + new String[] {"p.Foo", "p.Bar"}, + new String[] {"not found", "not found"}, new String[] {"-verbose:class", "-e", "p\\..*"}); test(new File(testDir, "Test.class"), new String[] {"java.lang"}, @@ -99,13 +103,34 @@ // test -classpath and -include options test(null, new String[] {"java.lang", "java.util", - "java.lang.management"}, - new String[] {"compact1", "compact1", "compact3"}, + "java.lang.management", "javax.crypto"}, + new String[] {"compact1", "compact1", "compact3", "compact1"}, new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"}); test(new File(testDir, "Test.class"), - new String[] {"java.lang.Object", "java.lang.String", "p.Foo"}, - new String[] {"compact1", "compact1", testDir.getName()}, + new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, + new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()}, new String[] {"-v", "-classpath", testDir.getPath(), "Test.class"}); + + // split package p - move p/Foo.class to dir1 and p/Bar.class to dir2 + Path testClassPath = testDir.toPath(); + Path dirP = testClassPath.resolve("p"); + Path dir1 = testClassPath.resolve("dir1"); + Path subdir1P = dir1.resolve("p"); + Path dir2 = testClassPath.resolve("dir2"); + Path subdir2P = dir2.resolve("p"); + if (!Files.exists(subdir1P)) + Files.createDirectories(subdir1P); + if (!Files.exists(subdir2P)) + Files.createDirectories(subdir2P); + Files.move(dirP.resolve("Foo.class"), subdir1P.resolve("Foo.class"), REPLACE_EXISTING); + Files.move(dirP.resolve("Bar.class"), subdir2P.resolve("Bar.class"), REPLACE_EXISTING); + StringBuilder cpath = new StringBuilder(testDir.toString()); + cpath.append(File.pathSeparator).append(dir1.toString()); + cpath.append(File.pathSeparator).append(dir2.toString()); + test(new File(testDir, "Test.class"), + new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"}, + new String[] {"compact1", "compact1", dir1.toFile().getName(), dir2.toFile().getName()}, + new String[] {"-v", "-classpath", cpath.toString(), "Test.class"}); return errors; } @@ -148,7 +173,7 @@ // Use the linePattern to break the given String into lines, applying // the pattern to each line to see if we have a match private static Map<String,String> findDeps(String out) { - Map<String,String> result = new HashMap<>(); + Map<String,String> result = new LinkedHashMap<>(); Matcher lm = linePattern.matcher(out); // Line matcher Matcher pm = null; // Pattern matcher int lines = 0;
--- a/test/tools/jdeps/Test.java Thu Oct 31 14:07:48 2013 -0400 +++ b/test/tools/jdeps/Test.java Mon Nov 11 23:16:35 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -24,6 +24,7 @@ public class Test { public void test() { p.Foo f = new p.Foo(); + p.Bar b = new p.Bar(); } private String name() { return "this test";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/jdeps/javax/activity/NotCompactProfile.java Mon Nov 11 23:16:35 2013 -0800 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013, 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.activity; + +public class NotCompactProfile { + public static String name() { + return "not Java SE API"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/jdeps/p/Bar.java Mon Nov 11 23:16:35 2013 -0800 @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013, 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 p; + +public class Bar extends javax.activity.NotCompactProfile { + public String bar() { + return "bar"; + } + public javax.crypto.Cipher getCiper() { + return null; + } +}