Merge
authorrbackman
Thu, 19 Jan 2017 11:10:33 +0100
changeset 43465 033b9f74b930
parent 43463 7a094360fe82 (current diff)
parent 43464 f38fde4a6b52 (diff)
child 43466 add500644443
Merge
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java
hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/LoadedClass.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,64 @@
+package jdk.tools.jaotc;/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+public class LoadedClass {
+    private final String name;
+    private final Class<?> clz;
+
+    public LoadedClass(String name, Class<?> clz) {
+        this.name = name;
+        this.clz = clz;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Class<?> getLoadedClass() {
+        return clz;
+    }
+
+    @Override
+    public String toString() {
+        return name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof LoadedClass)) return false;
+
+        LoadedClass that = (LoadedClass) o;
+
+        if (name != null ? !name.equals(that.name) : that.name != null) return false;
+        return clz != null ? clz.equals(that.clz) : that.clz == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (clz != null ? clz.hashCode() : 0);
+        return result;
+    }
+}
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Jan 19 11:10:33 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,7 @@
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
@@ -51,7 +52,11 @@
 
 import jdk.tools.jaotc.binformat.BinaryContainer;
 import jdk.tools.jaotc.binformat.ByteContainer;
-import jdk.tools.jaotc.collect.ClassCollector;
+import jdk.tools.jaotc.collect.*;
+import jdk.tools.jaotc.collect.classname.ClassNameSourceProvider;
+import jdk.tools.jaotc.collect.directory.DirectorySourceProvider;
+import jdk.tools.jaotc.collect.jar.JarSourceProvider;
+import jdk.tools.jaotc.collect.module.ModuleSourceProvider;
 import jdk.tools.jaotc.utils.Timer;
 
 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
@@ -127,17 +132,7 @@
         abstract void process(Main task, String opt, String arg) throws BadArgs;
     }
 
-    static Option[] recognizedOptions = {new Option("  --module <name>            Module to compile", true, "--module") {
-        @Override
-        void process(Main task, String opt, String arg) {
-            task.options.module = arg;
-        }
-    }, new Option("  --module-path <path>       Specify where to find module to compile", true, "--module-path") {
-        @Override
-        void process(Main task, String opt, String arg) {
-            task.options.modulepath = arg;
-        }
-    }, new Option("  --output <file>            Output file name", true, "--output") {
+    static Option[] recognizedOptions = { new Option("  --output <file>            Output file name", true, "--output") {
         @Override
         void process(Main task, String opt, String arg) {
             String name = arg;
@@ -161,10 +156,25 @@
         void process(Main task, String opt, String arg) {
             task.options.compileWithAssertions = true;
         }
-    }, new Option("  --classpath <path>         Specify where to find user class files", true, "--classpath", "--class-path") {
+    }, new Option("  --classname <class names>> Class names to AOT compile (: separated list)", true, "--classname") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(ClassNameSourceProvider.TYPE, arg));
+        }
+    }, new Option("  --directory <directories>  Directories to search for class files. (: separated list)", true, "--directory") {
         @Override
         void process(Main task, String opt, String arg) {
-            task.options.classpath = arg;
+            task.options.files.addAll(ClassSearch.makeList(DirectorySourceProvider.TYPE, arg));
+        }
+    }, new Option("  --jar <jarfiles>           Jar files to search for class files. (: separated list)", true, "--jar") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(JarSourceProvider.TYPE, arg));
+        }
+    }, new Option("  --module <modules>         module names to AOT compile (: separated list)", true, "--module") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            task.options.files.addAll(ClassSearch.makeList(ModuleSourceProvider.TYPE, arg));
         }
     }, new Option("  --threads <number>         Number of compilation threads to be used", true, "--threads") {
         @Override
@@ -218,6 +228,12 @@
         void process(Main task, String opt, String arg) {
             task.options.version = true;
         }
+    }, new Option("  --search-path <name>       Where to search for jarfiles and modules", true, "--search-path") {
+        @Override
+        void process(Main task, String opt, String arg) {
+            String[] elements = arg.split(":");
+            task.options.searchPath.add(elements);
+        }
     }, new Option("  -J<flag>                   Pass <flag> directly to the runtime system", false, "-J") {
         @Override
         void process(Main task, String opt, String arg) {
@@ -225,12 +241,11 @@
     }};
 
     public static class Options {
-        public List<String> files = new LinkedList<>();
-        public String module = null;
-        public String modulepath = "modules";
+        public List<SearchFor> files = new LinkedList<>();
         public String outputName = "unnamed";
         public String methodList;
-        public String classpath = ".";
+        public List<ClassSource> sources = new ArrayList<>();
+        public SearchPath searchPath = new SearchPath();
 
         /**
          * We don't see scaling beyond 16 threads.
@@ -288,7 +303,9 @@
 
             printlnInfo("Compiling " + options.outputName + "...");
             final long start = System.currentTimeMillis();
-            run();
+            if (!run()) {
+              return EXIT_ABNORMAL;
+            }
             final long end = System.currentTimeMillis();
             printlnInfo("Total time: " + (end - start) + " ms");
 
@@ -331,17 +348,34 @@
     }
 
     @SuppressWarnings("try")
-    private void run() throws Exception {
+    private boolean run() throws Exception {
         openLog();
 
         try {
             CompilationSpec compilationRestrictions = collectSpecifiedMethods();
 
-            Set<Class<?>> classesToCompile;
+            Set<Class<?>> classesToCompile = new HashSet<>();
 
             try (Timer t = new Timer(this, "")) {
-                ClassCollector collector = new ClassCollector(this.options, this);
-                classesToCompile = collector.collectClassesToCompile();
+                FileSupport fileSupport = new FileSupport();
+                ClassSearch lookup = new ClassSearch();
+                lookup.addProvider(new ModuleSourceProvider());
+                lookup.addProvider(new ClassNameSourceProvider(fileSupport));
+                lookup.addProvider(new JarSourceProvider());
+                lookup.addProvider(new DirectorySourceProvider(fileSupport));
+
+                List<LoadedClass> found = null;
+                try {
+                    found = lookup.search(options.files, options.searchPath);
+                } catch (InternalError e) {
+                    reportError(e);
+                    return false;
+                }
+
+                for (LoadedClass loadedClass : found) {
+                    classesToCompile.add(loadedClass.getLoadedClass());
+                }
+
                 printInfo(classesToCompile.size() + " classes found");
             }
 
@@ -464,6 +498,7 @@
         } finally {
             closeLog();
         }
+        return true;
     }
 
     private void addMethods(AOTCompiledClass aotClass, ResolvedJavaMethod[] methods, CompilationSpec compilationRestrictions, GraalFilters filters) {
@@ -527,7 +562,7 @@
                     break;
                 }
             } else {
-                options.files.add(arg);
+                options.files.add(new SearchFor(arg));
             }
         }
     }
@@ -588,6 +623,12 @@
         log.flush();
     }
 
+    private void reportError(Throwable e) {
+        log.println("Error: " + e.getMessage());
+        e.printStackTrace(log);
+        log.flush();
+    }
+
     private void reportError(String key, Object... args) {
         printError(MessageFormat.format(key, args));
     }
@@ -603,9 +644,9 @@
     }
 
     private void showHelp() {
-        log.println("Usage: " + PROGNAME + " <options> <--module name> | <list...>");
+        log.println("Usage: " + PROGNAME + " <options> | <list...>");
         log.println();
-        log.println("  list       A list of class files, jar files or directories which");
+        log.println("  list       A list of class names, jar files or directories which");
         log.println("             contains class files.");
         log.println();
         log.println("where possible options include:");
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassCollector.java	Thu Jan 19 10:30:37 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,332 +0,0 @@
-/*
- * Copyright (c) 2016, 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 jdk.tools.jaotc.collect;
-
-import jdk.tools.jaotc.LogPrinter;
-import jdk.tools.jaotc.Main;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.*;
-import java.nio.file.*;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-
-import static java.nio.file.FileVisitResult.CONTINUE;
-
-public class ClassCollector {
-    private final Main.Options options;
-    private final LogPrinter log;
-
-    public ClassCollector(Main.Options options, LogPrinter log) {
-        this.options = options;
-        this.log = log;
-    }
-
-    /**
-     * Collect all class names passed by the user.
-     *
-     * @return array list of classes
-     */
-    public Set<Class<?>> collectClassesToCompile() {
-        Set<Class<?>> classes = new HashSet<>();
-        List<String> filesToScan = new LinkedList<>(options.files);
-
-        if (options.module != null) {
-            classes.addAll(scanModule(filesToScan));
-        }
-
-        classes.addAll(scanFiles(filesToScan));
-        return classes;
-    }
-
-    private Set<Class<?>> scanModule(List<String> filesToScan) {
-        String module = options.module;
-        // Search module in standard JDK installation.
-        Path dir = getModuleDirectory(options.modulepath, module);
-
-        if (Files.isDirectory(dir)) {
-            return loadFromModuleDirectory(dir);
-        } else {
-            findFilesToScan(filesToScan, module);
-            return new HashSet<>();
-        }
-    }
-
-    private Set<Class<?>> loadFromModuleDirectory(Path dir) {
-        log.printInfo("Scanning module: " + dir + " ...");
-        log.printlnVerbose(" "); // Break line
-
-        FileSystemFinder finder = new FileSystemFinder(dir, pathname -> entryIsClassFile(pathname.toString()));
-        Set<Class<?>> cls = loadWithClassLoader(() -> ClassLoader.getSystemClassLoader(), dir, finder);
-        log.printlnInfo(" " + cls.size() + " classes loaded.");
-        return cls;
-    }
-
-    private void findFilesToScan(List<String> filesToScan, String module) {
-        // Try to search regular directory, .jar or .class files
-        Path path = Paths.get(options.modulepath, module);
-
-        if (Files.isDirectory(path)) {
-            filesToScan.add(".");
-            options.classpath = path.toString();
-        } else if (path.endsWith(".jar") || path.endsWith(".class")) {
-            filesToScan.add(path.toString());
-        } else {
-            path = Paths.get(options.modulepath, module + ".jar");
-            if (Files.exists(path)) {
-                filesToScan.add(path.toString());
-            } else {
-                path = Paths.get(options.modulepath, module + ".class");
-                if (Files.exists(path)) {
-                    filesToScan.add(path.toString());
-                } else {
-                    throw new InternalError("Expecting a .class, .jar or directory: " + path);
-                }
-            }
-        }
-    }
-
-    private boolean entryIsClassFile(String entry) {
-        return entry.endsWith(".class") && !entry.endsWith("module-info.class");
-    }
-
-    private Set<Class<?>> scanFiles(List<String> filesToScan) {
-        Set<Class<?>> classes = new HashSet<>();
-        for (String fileName : filesToScan) {
-            Set<Class<?>> loaded = scanFile(fileName);
-            log.printlnInfo(" " + loaded.size() + " classes loaded.");
-            classes.addAll(loaded);
-        }
-        return classes;
-    }
-
-    interface ClassLoaderFactory {
-        ClassLoader create() throws IOException;
-    }
-
-    private Set<Class<?>> loadWithClassLoader(ClassLoaderFactory factory, Path root, FileSystemFinder finder) {
-        ClassLoader loader = null;
-        try {
-            loader = factory.create();
-            return loadClassFiles(root, finder, loader);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        } finally {
-            if (loader instanceof AutoCloseable) {
-                try {
-                    ((AutoCloseable) loader).close();
-                } catch (Exception e) {
-                    throw new InternalError(e);
-                }
-            }
-        }
-    }
-
-    private Set<Class<?>> scanFile(String fileName) {
-        log.printInfo("Scanning: " + fileName + " ...");
-        log.printlnVerbose(" "); // Break line
-
-        if (fileName.endsWith(".jar")) {
-            return loadFromJarFile(fileName);
-        } else if (fileName.endsWith(".class")) {
-            Set<Class<?>> classes = new HashSet<>();
-            loadFromClassFile(fileName, classes);
-            return classes;
-        } else {
-            return scanClassPath(fileName);
-        }
-    }
-
-    private Set<Class<?>> loadFromJarFile(String fileName) {
-        FileSystem fs = makeFileSystem(fileName);
-        FileSystemFinder finder = new FileSystemFinder(fs.getPath("/"), pathname -> entryIsClassFile(pathname.toString()));
-        return loadWithClassLoader(() -> URLClassLoader.newInstance(buildUrls(fileName)), fs.getPath("/"), finder);
-    }
-
-    private void loadFromClassFile(String fileName, Set<Class<?>> classes) {
-        Class<?> result;
-        File file = new File(options.classpath);
-        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
-            result = loadClassFile(loader, fileName);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-        Class<?> c = result;
-        addClass(classes, fileName, c);
-    }
-
-    private Set<Class<?>> scanClassPath(String fileName) {
-        Path classPath = Paths.get(options.classpath);
-        if (!Files.exists(classPath)) {
-            throw new InternalError("Path does not exist: " + classPath);
-        }
-        if (!Files.isDirectory(classPath)) {
-            throw new InternalError("Path must be a directory: " + classPath);
-        }
-
-        // Combine class path and file name and see what it is.
-        Path combinedPath = Paths.get(options.classpath + File.separator + fileName);
-        if (combinedPath.endsWith(".class")) {
-            throw new InternalError("unimplemented");
-        } else if (Files.isDirectory(combinedPath)) {
-            return scanDirectory(classPath, combinedPath);
-        } else {
-            throw new InternalError("Expecting a .class, .jar or directory: " + fileName);
-        }
-    }
-
-    private FileSystem makeFileSystem(String fileName) {
-        try {
-            return FileSystems.newFileSystem(makeJarFileURI(fileName), new HashMap<>());
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private URI makeJarFileURI(String fileName) {
-        try {
-            return new URI("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/");
-        } catch (URISyntaxException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private PathMatcher combine(PathMatcher m1, PathMatcher m2) {
-        return path -> m1.matches(path) && m2.matches(path);
-    }
-
-    private Set<Class<?>> scanDirectory(Path classPath, Path combinedPath) {
-        String dir = options.classpath;
-
-        FileSystem fileSystem = FileSystems.getDefault();
-        PathMatcher matcher = fileSystem.getPathMatcher("glob:" + "*.class");
-        FileSystemFinder finder = new FileSystemFinder(combinedPath,
-            combine(matcher, pathname -> entryIsClassFile(pathname.toString())));
-
-        File file = new File(dir);
-        try (URLClassLoader loader = URLClassLoader.newInstance(buildUrls(file))) {
-            return loadClassFiles(classPath, finder, loader);
-        } catch (IOException e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private Set<Class<?>> loadClassFiles(Path root, FileSystemFinder finder, ClassLoader loader) {
-        Set<Class<?>> classes = new HashSet<>();
-        for (Path name : finder.done()) {
-            // Now relativize to the class path so we get the actual class names.
-            String entry = root.relativize(name).normalize().toString();
-            Class<?> c = loadClassFile(loader, entry);
-            addClass(classes, entry, c);
-        }
-        return classes;
-    }
-
-    private void addClass(Set<Class<?>> classes, String name, Class<?> c) {
-        if (c != null) {
-            classes.add(c);
-            log.printlnVerbose(" loaded " + name);
-        }
-    }
-
-    private URL[] buildUrls(String fileName) throws MalformedURLException {
-        return new URL[]{ new URL("jar:file:" + Paths.get(fileName).toAbsolutePath() + "!/") };
-    }
-
-    private URL[] buildUrls(File file) throws MalformedURLException {
-        return new URL[] {file.toURI().toURL() };
-    }
-
-    private Path getModuleDirectory(String modulepath, String module) {
-        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        return fs.getPath(modulepath, module);
-    }
-
-    /**
-     * Loads a class with the given file name from the specified {@link URLClassLoader}.
-     */
-    private Class<?> loadClassFile(final ClassLoader loader, final String fileName) {
-        int start = 0;
-        if (fileName.startsWith("/")) {
-            start = 1;
-        }
-        String className = fileName.substring(start, fileName.length() - ".class".length());
-        className = className.replace('/', '.');
-        try {
-            return loader.loadClass(className);
-        } catch (Throwable e) {
-            // If we are running in JCK mode we ignore all exceptions.
-            if (options.ignoreClassLoadingErrors) {
-                log.printError(className + ": " + e);
-                return null;
-            }
-            throw new InternalError(e);
-        }
-    }
-
-    /**
-     * {@link FileVisitor} implementation to find class files recursively.
-     */
-    private static class FileSystemFinder extends SimpleFileVisitor<Path> {
-        private final ArrayList<Path> fileNames = new ArrayList<>();
-        private final PathMatcher filter;
-
-        FileSystemFinder(Path combinedPath, PathMatcher filter) {
-            this.filter = filter;
-            try {
-                Files.walkFileTree(combinedPath, this);
-            } catch (IOException e) {
-                throw new InternalError(e);
-            }
-        }
-
-        /**
-         * Compares the glob pattern against the file name.
-         */
-        void find(Path file) {
-            Path name = file.getFileName();
-            if (name != null && filter.matches(name)) {
-                fileNames.add(file);
-            }
-        }
-
-        List<Path> done() {
-            return fileNames;
-        }
-
-        @Override
-        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
-            find(file);
-            return CONTINUE;
-        }
-
-        @Override
-        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
-            find(dir);
-            return CONTINUE;
-        }
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSearch.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import jdk.tools.jaotc.LoadedClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ClassSearch {
+    private List<SourceProvider> providers = new ArrayList<>();
+
+    public void addProvider(SourceProvider provider) {
+        providers.add(provider);
+    }
+
+    public List<LoadedClass> search(List<SearchFor> search, SearchPath searchPath) {
+        List<LoadedClass> loaded = new ArrayList<>();
+
+        List<ClassSource> sources = new ArrayList<>();
+
+        for (SearchFor entry : search) {
+            sources.add(findSource(entry, searchPath));
+        }
+
+        for (ClassSource source : sources) {
+            source.eachClass((name, loader) -> loaded.add(loadClass(name, loader)));
+        }
+
+        return loaded;
+    }
+
+    private LoadedClass loadClass(String name, ClassLoader loader) {
+        try {
+            Class<?> clzz = loader.loadClass(name);
+            return new LoadedClass(name, clzz);
+        } catch (ClassNotFoundException e) {
+            throw new InternalError("Failed to load with: " + loader, e);
+        }
+    }
+
+    private ClassSource findSource(SearchFor searchFor, SearchPath searchPath) {
+        ClassSource found = null;
+
+        for (SourceProvider provider : providers) {
+            if (!searchFor.isUnknown() && !provider.supports(searchFor.getType())) {
+                continue;
+            }
+
+            ClassSource source = provider.findSource(searchFor.getName(), searchPath);
+            if (source != null) {
+                if (found != null) {
+                    throw new InternalError("Multiple possible sources: " + source + " and: " + found);
+                }
+                found = source;
+            }
+        }
+
+        if (found == null) {
+            throw new InternalError("Failed to find: " + searchFor.toString());
+        }
+        return found;
+    }
+
+    public static List<SearchFor> makeList(String type, String argument) {
+        List<SearchFor> list = new ArrayList<>();
+        String[] elements = argument.split(":");
+        for (String element : elements) {
+            list.add(new SearchFor(element, type));
+        }
+        return list;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public interface ClassSource {
+    static boolean pathIsClassFile(Path entry) {
+        String fileName = entry.getFileName().toString();
+        return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
+    }
+
+    static String makeClassName(Path path) {
+        String fileName = path.toString();
+
+        if (!fileName.endsWith(".class")) {
+            throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
+        }
+
+        int start = 0;
+        if (fileName.startsWith("/")) {
+            start = 1;
+        }
+
+        String className = fileName.substring(start, fileName.length() - ".class".length());
+        className = className.replace('/', '.');
+        return className;
+    }
+
+    void eachClass(BiConsumer<String, ClassLoader> consumer);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.net.*;
+import java.nio.file.*;
+import java.util.HashMap;
+
+public class FileSupport {
+    public boolean exists(Path path)  {
+        return Files.exists(path);
+    }
+
+    public boolean isDirectory(Path path) {
+        return Files.isDirectory(path);
+    }
+
+    private FileSystem makeJarFileSystem(Path path) {
+        try {
+            return FileSystems.newFileSystem(makeJarFileURI(path), new HashMap<>());
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    private URI makeJarFileURI(Path path) {
+        try {
+            return new URI("jar:file:" + path.toAbsolutePath() + "!/");
+        } catch (URISyntaxException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    public ClassLoader createClassLoader(Path path, ClassLoader parent) {
+        try {
+            return URLClassLoader.newInstance(buildUrls(path), parent);
+        } catch (MalformedURLException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+        return URLClassLoader.newInstance(buildUrls(path));
+    }
+
+    private URL[] buildUrls(Path path) throws MalformedURLException {
+        return new URL[] { path.toUri().toURL() };
+    }
+
+    public Path getJarFileSystemRoot(Path jarFile) {
+        FileSystem fileSystem = makeJarFileSystem(jarFile);
+        return fileSystem.getPath("/");
+    }
+
+    public boolean isAbsolute(Path entry) {
+        return entry.isAbsolute();
+    }
+
+    public Path getSubDirectory(FileSystem fileSystem, Path root, Path path) throws IOException {
+        DirectoryStream<Path> paths = fileSystem.provider().newDirectoryStream(root,null);
+        for (Path entry : paths) {
+            Path relative = root.relativize(entry);
+            if (relative.equals(path)) {
+                return entry;
+            }
+        }
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSystemFinder.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.io.IOException;
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+/**
+ * {@link FileVisitor} implementation to find class files recursively.
+ */
+public class FileSystemFinder extends SimpleFileVisitor<Path> implements Iterable<Path> {
+    private final ArrayList<Path> fileNames = new ArrayList<>();
+    private final PathMatcher filter;
+
+    public FileSystemFinder(Path combinedPath, PathMatcher filter) {
+        this.filter = filter;
+        try {
+            Files.walkFileTree(combinedPath, this);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    /**
+     * Compares the glob pattern against the file name.
+     */
+    private void find(Path file) {
+        Path name = file.getFileName();
+        if (name != null && filter.matches(name)) {
+            fileNames.add(file);
+        }
+    }
+
+    @Override
+    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+        find(file);
+        return CONTINUE;
+    }
+
+    @Override
+    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
+        find(dir);
+        return CONTINUE;
+    }
+
+
+    @Override
+    public Iterator<Path> iterator() {
+        return fileNames.iterator();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchFor.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+public class SearchFor {
+    private final String name;
+    private final String type;
+
+    public SearchFor(String name) {
+        this(name, "unknown");
+    }
+
+    public SearchFor(String name, String type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    public boolean isUnknown() {
+        return "unknown".equals(type);
+    }
+
+    public String getType() {
+        return this.type;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    @Override
+    public String toString() {
+        return type + ":" + name;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SearchPath.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SearchPath {
+    private final List<Path> searchPaths = new ArrayList<>();
+    private final FileSupport fileSupport;
+
+    public SearchPath() {
+        this(new FileSupport());
+    }
+
+    public SearchPath(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+    }
+
+    public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+        if (isAbsolute(entry)) {
+            if (exists(entry)) {
+                return entry;
+            }
+            return null;
+        }
+
+        if (exists(entry)) {
+            return entry;
+        }
+
+        for (String searchPath : defaults) {
+            Path newPath = fileSystem.getPath(searchPath, entry.toString());
+            if (exists(newPath)) {
+                return newPath;
+            }
+        }
+
+        for (Path searchPath : searchPaths) {
+            Path newPath = fileSystem.getPath(searchPath.toString(), entry.toString());
+            if (exists(newPath)) {
+                return newPath;
+            }
+        }
+
+        return null;
+    }
+
+    private boolean isAbsolute(Path entry) {
+        return fileSupport.isAbsolute(entry);
+    }
+
+    private boolean exists(Path entry) {
+        return fileSupport.exists(entry);
+    }
+
+    public void add(String... paths) {
+        for (String name : paths) {
+            Path path = Paths.get(name);
+            searchPaths.add(path);
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/SourceProvider.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect;
+
+public interface SourceProvider {
+    ClassSource findSource(String name, SearchPath searchPath);
+
+    boolean supports(String type);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSource.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+
+import java.util.function.BiConsumer;
+
+public class ClassNameSource implements ClassSource {
+    private final String name;
+    private final ClassLoader classLoader;
+
+    public ClassNameSource(String name, ClassLoader classLoader) {
+        this.name = name;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        consumer.accept(name, classLoader);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/classname/ClassNameSourceProvider.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.classname;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ClassNameSourceProvider implements SourceProvider {
+    public final static String TYPE = "classname";
+    private final ClassLoader classLoader;
+
+    public ClassNameSourceProvider(FileSupport fileSupport) {
+        String classPath = System.getProperty("java.class.path");
+        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+        if (classPath != null && !classPath.isEmpty()) {
+            classLoader = systemClassLoader;
+        } else {
+            Path path = Paths.get(".").toAbsolutePath();
+            classLoader = fileSupport.createClassLoader(path, systemClassLoader);
+        }
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        try {
+            classLoader.loadClass(name);
+            return new ClassNameSource(name, classLoader);
+        } catch (ClassNotFoundException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySource.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class DirectorySource implements ClassSource {
+    private final Path directoryPath;
+    private final ClassLoader classLoader;
+
+    public DirectorySource(Path directoryPath, ClassLoader classLoader) {
+        this.directoryPath = directoryPath;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(directoryPath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(directoryPath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "directory:" + directoryPath.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/directory/DirectorySourceProvider.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class DirectorySourceProvider implements SourceProvider {
+    private final FileSupport fileSupport;
+    private final FileSystem fileSystem;
+    public final static String TYPE = "directory";
+
+    public DirectorySourceProvider(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+        fileSystem = FileSystems.getDefault();
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path directoryPath = fileSystem.getPath(name);
+
+        if (!fileSupport.exists(directoryPath)) {
+            return null;
+        }
+        if (!fileSupport.isDirectory(directoryPath)) {
+            return null;
+        }
+
+        try {
+            ClassLoader classLoader = fileSupport.createClassLoader(directoryPath);
+            return new DirectorySource(directoryPath, classLoader);
+        } catch (MalformedURLException e) {
+            return null;
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarFileSource.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class JarFileSource implements ClassSource {
+    private final Path jarFile;
+    private final Path jarRootPath;
+    private final ClassLoader classLoader;
+
+
+    public JarFileSource(Path jarFile, Path jarRootPath, ClassLoader classLoader) {
+        this.jarFile = jarFile;
+        this.jarRootPath = jarRootPath;
+        this.classLoader = classLoader;
+    }
+
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(jarRootPath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(jarRootPath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "jar:" + jarFile.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/jar/JarSourceProvider.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.net.MalformedURLException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.ProviderNotFoundException;
+
+public class JarSourceProvider implements SourceProvider {
+    private final FileSystem fileSystem;
+    private final FileSupport fileSupport;
+    public final static String TYPE = "jar";
+
+    public JarSourceProvider() {
+        this(new FileSupport());
+    }
+
+    public JarSourceProvider(FileSupport fileSupport) {
+        this.fileSupport = fileSupport;
+        fileSystem = FileSystems.getDefault();
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path fileName = fileSystem.getPath(name);
+        Path jarFile = searchPath.find(fileSystem, fileName);
+
+        if (!validPath(jarFile)) {
+            return null;
+        }
+
+        return createSource(jarFile);
+    }
+
+    private ClassSource createSource(Path jarFile) {
+        try {
+            Path jarRootPath = fileSupport.getJarFileSystemRoot(jarFile);
+            if (jarRootPath == null) {
+                return null;
+            }
+            ClassLoader classLoader = fileSupport.createClassLoader(jarFile);
+            return new JarFileSource(jarFile, jarRootPath, classLoader);
+        } catch (ProviderNotFoundException | MalformedURLException e) {
+        }
+        return null;
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+
+    private boolean validPath(Path jarFile) {
+        return jarFile != null && !fileSupport.isDirectory(jarFile);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSource.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSystemFinder;
+
+import java.nio.file.Path;
+import java.util.function.BiConsumer;
+
+public class ModuleSource implements ClassSource {
+    private final Path modulePath;
+    private final ClassLoader classLoader;
+
+    public ModuleSource(Path modulePath, ClassLoader classLoader) {
+        this.modulePath = modulePath;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        FileSystemFinder finder = new FileSystemFinder(modulePath, ClassSource::pathIsClassFile);
+
+        for (Path path : finder) {
+            consumer.accept(ClassSource.makeClassName(modulePath.relativize(path).normalize()), classLoader);
+        }
+    }
+
+    public Path getModulePath() {
+        return modulePath;
+    }
+
+    @Override
+    public String toString() {
+        return "module:" + modulePath.toString();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/module/ModuleSourceProvider.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.collect.module;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.collect.FileSupport;
+import jdk.tools.jaotc.collect.SearchPath;
+import jdk.tools.jaotc.collect.SourceProvider;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+
+public class ModuleSourceProvider implements SourceProvider {
+    private final FileSystem fileSystem;
+    private final ClassLoader classLoader;
+    private final FileSupport fileSupport;
+    public final static String TYPE = "module";
+
+    public ModuleSourceProvider() {
+        this(FileSystems.getFileSystem(URI.create("jrt:/")), ClassLoader.getSystemClassLoader(), new FileSupport());
+    }
+
+    public ModuleSourceProvider(FileSystem fileSystem, ClassLoader classLoader, FileSupport fileSupport) {
+        this.fileSystem = fileSystem;
+        this.classLoader = classLoader;
+        this.fileSupport = fileSupport;
+    }
+
+    @Override
+    public ClassSource findSource(String name, SearchPath searchPath) {
+        Path path = fileSystem.getPath(name);
+        Path dir = fileSystem.getPath("modules");
+
+        if (dir == null || !fileSupport.isDirectory(dir)) {
+            return null;
+        }
+
+        Path found = findModuleDirectory(dir, path);
+
+        if (found == null) {
+            return null;
+        }
+
+        return new ModuleSource(found, classLoader);
+    }
+
+    private Path findModuleDirectory(Path root, Path path) {
+        try {
+            return fileSupport.getSubDirectory(fileSystem, root, path);
+        } catch (IOException e) {
+            throw new InternalError(e);
+        }
+    }
+
+    @Override
+    public boolean supports(String type) {
+        return TYPE.equals(type);
+    }
+}
--- a/hotspot/test/compiler/aot/AotCompiler.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/AotCompiler.java	Thu Jan 19 11:10:33 2017 +0100
@@ -69,7 +69,7 @@
         extraopts.add("-classpath");
         extraopts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
         if (className != null && libName != null) {
-            OutputAnalyzer oa = launchCompiler(libName, className + ".class", extraopts, compileList);
+            OutputAnalyzer oa = launchCompiler(libName, className, extraopts, compileList);
             oa.shouldHaveExitValue(0);
         } else {
             printUsage();
@@ -100,6 +100,7 @@
             args.add("--compile-commands");
             args.add(file.toString());
         }
+        args.add("--classname");
         args.add(item);
         return launchJaotc(args, extraopts);
     }
--- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2016, 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
- * @library / /test/lib /testlibrary
- * @modules java.base/jdk.internal.misc
- * @requires vm.bits == "64" & os.arch == "amd64" & os.family == "linux"
- * @build compiler.aot.cli.jaotc.ClasspathOptionTest
- * @run driver ClassFileInstaller compiler.aot.cli.jaotc.data.HelloWorldOne
- * @run driver compiler.aot.cli.jaotc.ClasspathOptionTest
- * @summary check jaotc can compile class from classpath
- */
-
-package compiler.aot.cli.jaotc;
-
-import compiler.aot.cli.jaotc.data.HelloWorldOne;
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import jdk.test.lib.Asserts;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class ClasspathOptionTest {
-    public static void main(String[] args) {
-        Path cp = Paths.get("testClasspath");
-        try {
-            Files.createDirectory(cp);
-            Files.move(Paths.get("compiler"), cp.resolve("compiler"));
-        } catch (IOException e) {
-            throw new Error("TESTBUG: can't create test data " + e, e);
-        }
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classpath", cp.toString(),
-                JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
-        oa.shouldHaveExitValue(0);
-        File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
-        Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
-        Asserts.assertGT(compiledLibrary.length(), 0L, "Unexpected compiled library size");
-        JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName());
-    }
-}
--- a/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/ClasspathOptionUnknownClassTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -39,7 +39,7 @@
 
 public class ClasspathOptionUnknownClassTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("HelloWorldOne.class");
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classname", "HelloWorldOne");
         Asserts.assertNE(oa.getExitValue(), 0, "Unexpected compilation exit code");
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertFalse(compiledLibrary.exists(), "Compiler library unexpectedly exists");
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileClassTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -41,7 +41,7 @@
 
 public class CompileClassTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JaotcTestHelper
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--classname", JaotcTestHelper
                 .getClassAotCompilationName(HelloWorldOne.class));
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileDirectoryTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -42,7 +42,7 @@
 
 public class CompileDirectoryTest {
     public static void main(String[] args) {
-        OutputAnalyzer oa =JaotcTestHelper.compileLibrary(".");
+        OutputAnalyzer oa =JaotcTestHelper.compileLibrary("--directory", ".");
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/CompileJarTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -48,7 +48,7 @@
 
     public static void main(String[] args) {
         createJar();
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary(JAR_NAME);
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--jar", JAR_NAME);
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/JaotcTestHelper.java	Thu Jan 19 11:10:33 2017 +0100
@@ -71,7 +71,11 @@
         }
     }
 
-    public static String getClassAotCompilationName(Class<?> classToCompile) {
+    public static String getClassAotCompilationFilename(Class<?> classToCompile) {
         return classToCompile.getName().replaceAll("\\.", File.separator) + ".class";
     }
+
+    public static String getClassAotCompilationName(Class<?> classToCompile) {
+        return classToCompile.getName();
+    }
 }
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionNotExistingTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -45,7 +45,7 @@
 
     public static void main(String[] args) {
         OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", "./notExisting.list",
-                COMPILE_ITEM);
+                "--classname", COMPILE_ITEM);
         int exitCode = oa.getExitValue();
         Asserts.assertNE(exitCode, 0, "Unexpected compilation exit code");
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -66,7 +66,7 @@
             throw new Error("TESTBUG: can't write list file " + e, e);
         }
         OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_COMMAND_FILE.toString(),
-                JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
+                "--classname", JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class));
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
         Asserts.assertTrue(compiledLibrary.exists(), "Compiled library file missing");
--- a/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/cli/jaotc/ListOptionWrongFileTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -49,12 +49,15 @@
     private static final String COMPILE_ITEM
             = JaotcTestHelper.getClassAotCompilationName(HelloWorldOne.class);
 
+    private static final String COMPILE_FILE
+            = JaotcTestHelper.getClassAotCompilationFilename(HelloWorldOne.class);
+
     public static void main(String[] args) {
         // expecting wrong file to be read but no compilation directive recognized, so, all compiled
-        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_ITEM, COMPILE_ITEM);
+        OutputAnalyzer oa = JaotcTestHelper.compileLibrary("--compile-commands", COMPILE_FILE, "--classname", COMPILE_ITEM);
         oa.shouldHaveExitValue(0);
         File compiledLibrary = new File(JaotcTestHelper.DEFAULT_LIB_PATH);
-        Asserts.assertTrue(compiledLibrary.exists(), "Expecte compiler library to exist");
+        Asserts.assertTrue(compiledLibrary.exists(), "Expected compiler library to exist");
         JaotcTestHelper.checkLibraryUsage(HelloWorldOne.class.getName(), EXPECTED, null);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSearchTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+
+import jdk.tools.jaotc.LoadedClass;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+public class ClassSearchTest {
+    @Test(expected = InternalError.class)
+    public void itShouldThrowExceptionIfNoProvidersAvailable() {
+        ClassSearch target = new ClassSearch();
+        SearchPath searchPath = new SearchPath();
+        target.search(list("foo"), searchPath);
+    }
+
+    @Test
+    public void itShouldFindAProviderForEachEntry() {
+        Set<String> searched = new HashSet<>();
+        ClassSearch target = new ClassSearch();
+        target.addProvider(new SourceProvider() {
+            @Override
+            public ClassSource findSource(String name, SearchPath searchPath) {
+                searched.add(name);
+                return new NoopSource();
+            }
+        });
+        target.search(list("foo", "bar", "foobar"), null);
+        Assert.assertEquals(hashset("foo", "bar", "foobar"), searched);
+    }
+
+    @Test
+    public void itShouldSearchAllProviders() {
+        Set<String> visited = new HashSet<>();
+        ClassSearch target = new ClassSearch();
+        target.addProvider((name, searchPath) -> {
+            visited.add("1");
+            return null;
+        });
+        target.addProvider((name, searchPath) -> {
+            visited.add("2");
+            return null;
+        });
+
+        try {
+            target.search(list("foo"), null);
+        } catch (InternalError e) {
+            // throws because no provider gives a source
+        }
+
+        Assert.assertEquals(hashset("1", "2"), visited);
+    }
+
+    @Test
+    public void itShouldTryToLoadSaidClassFromClassLoader() {
+        Set<String> loaded = new HashSet<>();
+
+        ClassSearch target = new ClassSearch();
+        target.addProvider(new SourceProvider() {
+            @Override
+            public ClassSource findSource(String name, SearchPath searchPath) {
+                return new ClassSource() {
+                    @Override
+                    public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+                        consumer.accept("foo.Bar", new ClassLoader() {
+                            @Override
+                            public Class<?> loadClass(String name) throws ClassNotFoundException {
+                                loaded.add(name);
+                                return null;
+                            }
+                        });
+                    }
+                };
+            }
+        });
+
+        java.util.List<LoadedClass> search = target.search(list("/tmp/something"), null);
+        Assert.assertEquals(list(new LoadedClass("foo.Bar", null)), search);
+    }
+
+    @Test(expected = InternalError.class)
+    public void itShouldThrowInternalErrorWhenClassLoaderFails() {
+        ClassLoader classLoader = new ClassLoader() {
+            @Override
+            public Class<?> loadClass(String name1) throws ClassNotFoundException {
+                throw new ClassNotFoundException("failed to find " + name1);
+            }
+        };
+
+        ClassSearch target = new ClassSearch();
+        target.addProvider((name, searchPath) -> consumer -> consumer.accept("foo.Bar", classLoader));
+        target.search(list("foobar"), null);
+    }
+
+    private <T> List<T> list(T... entries) {
+        List<T> list = new ArrayList<T>();
+        for (T entry : entries) {
+            list.add(entry);
+        }
+        return list;
+    }
+
+    private <T> Set<T> hashset(T... entries) {
+        Set<T> set = new HashSet<T>();
+        for (T entry : entries) {
+            set.add(entry);
+        }
+        return set;
+    }
+
+    private static class NoopSource implements ClassSource {
+        @Override
+        public void eachClass(BiConsumer<String, ClassLoader> consumer) {
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/ClassSourceTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.nio.file.Paths;
+
+import static jdk.tools.jaotc.collect.ClassSource.makeClassName;
+
+public class ClassSourceTest {
+    @Test(expected=IllegalArgumentException.class)
+    public void itShouldThrowExceptionIfPathDoesntEndWithClass() {
+        makeClassName(Paths.get("Bar.clazz"));
+    }
+
+    @Test
+    public void itShouldReplaceSlashesWithDots() {
+        Assert.assertEquals("foo.Bar", makeClassName(Paths.get("foo/Bar.class")));
+    }
+
+    @Test
+    public void itShouldStripLeadingSlash() {
+        Assert.assertEquals("Hello", makeClassName(Paths.get("/Hello.class")));
+    }
+
+    @Test
+    public void itShouldReplaceMultipleDots() {
+        Assert.assertEquals("some.foo.bar.FooBar", makeClassName(Paths.get("/some/foo/bar/FooBar.class")));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeFileSupport.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.HashSet;
+import java.util.Set;
+
+public class FakeFileSupport extends FileSupport {
+    private final Set<String> exists = new HashSet<>();
+    private final Set<String> directories = new HashSet<>();
+
+    private final Set<String> checkedExists = new HashSet<>();
+    private final Set<String> checkedDirectory = new HashSet<>();
+    private final Set<String> checkedJarFileSystemRoots = new HashSet<>();
+    private final Set<String> classloaderPaths = new HashSet<>();
+
+    private Path jarFileSystemRoot = null;
+    private final ClassLoader classLoader;
+
+    public FakeFileSupport(Set<String> existing, Set<String> directories) {
+        this.exists.addAll(existing);
+        this.directories.addAll(directories);
+
+        classLoader = new ClassLoader() {
+            @Override
+            public Class<?> loadClass(String name) throws ClassNotFoundException {
+                return null;
+            }
+        };
+    }
+
+    public void setJarFileSystemRoot(Path path) {
+        jarFileSystemRoot = path;
+    }
+
+    @Override
+    public boolean exists(Path path) {
+        checkedExists.add(path.toString());
+        return exists.contains(path.toString());
+    }
+
+    @Override
+    public boolean isDirectory(Path path) {
+        checkedDirectory.add(path.toString());
+        return directories.contains(path.toString());
+    }
+
+    @Override
+    public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+        classloaderPaths.add(path.toString());
+        return classLoader;
+    }
+
+    @Override
+    public Path getJarFileSystemRoot(Path jarFile) {
+        checkedJarFileSystemRoots.add(jarFile.toString());
+        return jarFileSystemRoot;
+    }
+
+    @Override
+    public boolean isAbsolute(Path entry) {
+        return entry.toString().startsWith("/");
+    }
+
+    public void addExist(String name) {
+        exists.add(name);
+    }
+
+    public void addDirectory(String name) {
+        directories.add(name);
+    }
+
+    public Set<String> getCheckedExists() {
+        return checkedExists;
+    }
+
+    public Set<String> getCheckedDirectory() {
+        return checkedDirectory;
+    }
+
+    public Set<String> getCheckedJarFileSystemRoots() {
+        return checkedJarFileSystemRoots;
+    }
+
+    public Set<String> getClassloaderPaths() {
+        return classloaderPaths;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/FakeSearchPath.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+import java.nio.file.FileSystem;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class FakeSearchPath extends SearchPath {
+    private Path path = null;
+    public Set<String> entries = set();
+
+    public FakeSearchPath(String name) {
+        if (name != null) {
+            path = Paths.get(name);
+        }
+    }
+
+    @Override
+    public Path find(FileSystem fileSystem, Path entry, String... defaults) {
+        entries.add(entry.toString());
+        return path;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/SearchPathTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+import static org.junit.Assert.*;
+
+public class SearchPathTest {
+    private FakeFileSupport fileSupport;
+    private FileSystem fs;
+
+    @Before
+    public void setUp() throws Exception {
+        fs = FileSystems.getDefault();
+    }
+
+    @Test
+    public void itShouldUsePathIfPathIsAbsoluteAndExisting() {
+        fileSupport = new FakeFileSupport(set("/foo"), set());
+        SearchPath target = new SearchPath(fileSupport);
+        Path foo = Paths.get("/foo");
+        Path result = target.find(fs, foo);
+        assertSame(result, foo);
+    }
+
+    @Test
+    public void itShouldReturnNullIfPathIsAbsoluteAndNonExisting() {
+        fileSupport = new FakeFileSupport(set(), set());
+        SearchPath target = new SearchPath(fileSupport);
+        Path result = target.find(fs, Paths.get("/bar"));
+        assertNull(result);
+    }
+
+    @Test
+    public void itShouldUseRelativeExisting() {
+        fileSupport = new FakeFileSupport(set("hello", "tmp/hello", "search/hello"), set());
+        SearchPath target = new SearchPath(fileSupport);
+        target.add("search");
+        Path hello = Paths.get("hello");
+        Path result = target.find(fs, hello, "tmp");
+        assertSame(result, hello);
+    }
+
+    @Test
+    public void itShouldSearchDefaultsBeforeSearchPaths() {
+        fileSupport = new FakeFileSupport(set("bar/foobar"), set());
+        SearchPath target = new SearchPath(fileSupport);
+        Path result = target.find(fs, Paths.get("foobar"), "default1", "bar");
+        assertEquals("bar/foobar", result.toString());
+        assertEquals(set("foobar", "default1/foobar", "bar/foobar"), fileSupport.getCheckedExists());
+    }
+
+    @Test
+    public void itShouldUseSearchPathsIfNotInDefaults() {
+        fileSupport = new FakeFileSupport(set("bar/tmp/foobar"), set());
+        SearchPath target = new SearchPath(fileSupport);
+        target.add("foo/tmp", "bar/tmp");
+
+        Path result = target.find(fs, Paths.get("foobar"), "foo", "bar");
+        assertEquals("bar/tmp/foobar", result.toString());
+        assertEquals(set("foobar", "foo/foobar", "bar/foobar", "bar/tmp/foobar", "foo/tmp/foobar"), fileSupport.getCheckedExists());
+    }
+
+    @Test
+    public void itShouldReturnNullIfNoExistingPathIsFound() {
+        fileSupport = new FakeFileSupport(set(), set());
+        SearchPath target = new SearchPath(fileSupport);
+        target.add("dir1", "dir2");
+
+        Path result = target.find(fs, Paths.get("entry"), "dir3", "dir4");
+        assertNull(result);
+        assertEquals(set("entry", "dir1/entry", "dir2/entry", "dir3/entry", "dir4/entry"), fileSupport.getCheckedExists());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/Utils.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class Utils {
+    public static <T> Set<T> set(T... entries) {
+        Set<T> set = new HashSet<T>();
+        for (T entry : entries) {
+            set.add(entry);
+        }
+        return set;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/directory/DirectorySourceProviderTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jaotc.test.collect.directory;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.test.collect.FileSupport;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.MalformedURLException;
+import java.nio.file.Path;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class DirectorySourceProviderTest {
+    @Test
+    public void itShouldReturnNullForNonExistantPath() {
+        DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set(), set()));
+        ClassSource result = target.findSource("hello", null);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void itShouldReturnNullForNonDirectory() {
+        DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set()));
+        ClassSource result = target.findSource("foobar", null);
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void itShouldReturnNullForMalformedURI() {
+        Set<String> visited = set();
+        DirectorySourceProvider target = new DirectorySourceProvider(new FakeFileSupport(set("foobar"), set("foobar")) {
+            @Override
+            public ClassLoader createClassLoader(Path path) throws MalformedURLException {
+                visited.add("1");
+                throw new MalformedURLException("...");
+            }
+        });
+        ClassSource result = target.findSource("foobar", null);
+        Assert.assertNull(result);
+        Assert.assertEquals(set("1"), visited);
+    }
+
+    @Test
+    public void itShouldCreateSourceIfNameExistsAndIsADirectory() {
+        FileSupport fileSupport = new FakeFileSupport(set("foo"), set("foo"));
+        DirectorySourceProvider target = new DirectorySourceProvider(fileSupport);
+        ClassSource foo = target.findSource("foo", null);
+        Assert.assertNotNull(foo);
+        Assert.assertEquals("directory:foo", foo.toString());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/jar/JarSourceProviderTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect.jar;
+
+import jdk.tools.jaotc.collect.ClassSource;
+import jdk.tools.jaotc.test.collect.FakeFileSupport;
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.ProviderNotFoundException;
+import java.util.Set;
+
+import static jdk.tools.jaotc.test.collect.Utils.set;
+
+public class JarSourceProviderTest {
+
+    private FakeFileSupport fileSupport;
+    private JarSourceProvider target;
+
+    @Before
+    public void setUp() throws Exception {
+        fileSupport = new FakeFileSupport(set(), set());
+        target = new JarSourceProvider(fileSupport);
+    }
+
+    @Test
+    public void itShouldUseSearchPathToFindPath() {
+        Set<String> visited = set();
+        JarSourceProvider target = new JarSourceProvider(fileSupport);
+        FakeSearchPath searchPath = new FakeSearchPath(null);
+        ClassSource source = target.findSource("hello", searchPath);
+
+        Assert.assertEquals(set("hello"), searchPath.entries);
+    }
+
+    @Test
+    public void itShouldReturnNullIfPathIsNull() {
+        JarSourceProvider target = new JarSourceProvider(fileSupport);
+        ClassSource source = target.findSource("foobar", new FakeSearchPath(null));
+        Assert.assertNull(source);
+    }
+
+    @Test
+    public void itShouldReturnNullIfPathIsDirectory() {
+        fileSupport.addDirectory("hello/foobar");
+        ClassSource source = target.findSource("foobar", new FakeSearchPath("hello/foobar"));
+
+        Assert.assertNull(source);
+        Assert.assertEquals(set("hello/foobar"), fileSupport.getCheckedDirectory());
+    }
+
+    @Test
+    public void itShouldReturnNullIfUnableToMakeJarFileSystem() {
+        fileSupport.setJarFileSystemRoot(null);
+        ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+        Assert.assertEquals(set("foo/bar"), fileSupport.getCheckedJarFileSystemRoots());
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void itShouldReturnNullIfNotValidJarProvider() {
+        fileSupport = new FakeFileSupport(set(), set()) {
+
+            @Override
+            public Path getJarFileSystemRoot(Path jarFile) {
+                super.getJarFileSystemRoot(jarFile);
+                throw new ProviderNotFoundException();
+            }
+        };
+        fileSupport.setJarFileSystemRoot(null);
+        target = new JarSourceProvider(fileSupport);
+
+        ClassSource result = target.findSource("foobar", new FakeSearchPath("foo/bar"));
+
+        Assert.assertEquals(set("foo/bar"), fileSupport.getCheckedJarFileSystemRoots());
+        Assert.assertNull(result);
+    }
+
+    @Test
+    public void itShouldReturnSourceWhenAllIsValid() {
+        fileSupport.setJarFileSystemRoot(Paths.get("some/bar"));
+        ClassSource result = target.findSource("foobar", new FakeSearchPath("this/bar"));
+
+        Assert.assertEquals(set("this/bar"), fileSupport.getClassloaderPaths());
+        Assert.assertEquals("jar:this/bar", result.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/aot/jdk.tools.jaotc.test/src/jdk/tools/jaotc/test/collect/module/ModuleSourceProviderTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jaotc.test.collect.module;
+
+import jdk.tools.jaotc.*;
+import jdk.tools.jaotc.test.collect.FakeSearchPath;
+import jdk.tools.jaotc.test.collect.Utils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.file.FileSystems;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class ModuleSourceProviderTest {
+    private ClassLoader classLoader;
+    private ModuleSourceProvider target;
+
+    @Before
+    public void setUp() {
+        classLoader = new FakeClassLoader();
+        target = new ModuleSourceProvider(FileSystems.getDefault(), classLoader);
+    }
+
+    @Test
+    public void itShouldUseSearchPath() {
+        FakeSearchPath searchPath = new FakeSearchPath("blah/java.base");
+        ModuleSource source = (ModuleSource) target.findSource("java.base", searchPath);
+        assertEquals(Utils.set("java.base"), searchPath.entries);
+        assertEquals("blah/java.base", source.getModulePath().toString());
+        assertEquals("module:blah/java.base", source.toString());
+    }
+
+    @Test
+    public void itShouldReturnNullIfSearchPathReturnsNull() {
+        FakeSearchPath searchPath = new FakeSearchPath(null);
+        ModuleSource source = (ModuleSource) target.findSource("jdk.base", searchPath);
+        assertEquals(Utils.set("jdk.base"), searchPath.entries);
+        assertNull(source);
+    }
+
+    private static class FakeClassLoader extends ClassLoader {
+        @Override
+        public Class<?> loadClass(String name) throws ClassNotFoundException {
+            return null;
+        }
+    }
+}
--- a/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/verification/ClassAndLibraryNotMatchTest.java	Thu Jan 19 11:10:33 2017 +0100
@@ -85,9 +85,8 @@
     }
 
     private void compileAotLibrary() {
-        AotCompiler.launchCompiler(LIB_NAME, HELLO_WORLD_CLASS_NAME + ".class",
-                Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + File.pathSeparator
-                        + Utils.TEST_SRC), null);
+        AotCompiler.launchCompiler(LIB_NAME, HELLO_WORLD_CLASS_NAME,
+                Arrays.asList("-classpath", Utils.TEST_CLASS_PATH + ":."), null);
     }
 
     private void runAndCheckHelloWorld(String checkString) {
--- a/hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java	Thu Jan 19 10:30:37 2017 +0100
+++ b/hotspot/test/compiler/aot/verification/vmflags/BasicFlagsChange.java	Thu Jan 19 11:10:33 2017 +0100
@@ -76,7 +76,7 @@
         extraOpts.add(option);
         extraOpts.add("-classpath");
         extraOpts.add(Utils.TEST_CLASS_PATH + File.pathSeparator + Utils.TEST_SRC);
-        AotCompiler.launchCompiler(libName, className + ".class", extraOpts, null);
+        AotCompiler.launchCompiler(libName, className, extraOpts, null);
     }
 
     private static void runAndCheck(String option, String libName,