JDK 11 jdk.jdeps.jmod - JDeps Tool

JDK 11 jdk.jdeps.jmod is the JMOD file for JDK 11 JDeps tool, which can be invoked by the "jdeps" command.

JDK 11 JDeps tool compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\jdk.jdeps.jmod.

JDK 11 JDeps tool compiled class files are also linked and stored in the \fyicenter\jdk-11.0.1\lib\modules JImage file.

JDK 11 JDeps tool source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\jdk.jdeps.

You can click and view the content of each source code file in the list below.

✍: FYIcenter

com/sun/tools/jdeps/JdepsTask.java

/*
 * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.sun.tools.jdeps;

import com.sun.tools.jdeps.Analyzer.Type;
import static com.sun.tools.jdeps.Analyzer.Type.*;
import static com.sun.tools.jdeps.JdepsWriter.*;
import static java.util.stream.Collectors.*;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.module.ResolutionException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.*;
import java.util.jar.JarFile;
import java.util.regex.Pattern;

/**
 * Implementation for the jdeps tool for static class dependency analysis.
 */
class JdepsTask {
    static interface BadArguments {
        String getKey();
        Object[] getArgs();
        boolean showUsage();
    }
    static class BadArgs extends Exception implements BadArguments {
        static final long serialVersionUID = 8765093759964640721L;
        BadArgs(String key, Object... args) {
            super(JdepsTask.getMessage(key, args));
            this.key = key;
            this.args = args;
        }

        BadArgs showUsage(boolean b) {
            showUsage = b;
            return this;
        }
        final String key;
        final Object[] args;
        boolean showUsage;

        @Override
        public String getKey() {
            return key;
        }

        @Override
        public Object[] getArgs() {
            return args;
        }

        @Override
        public boolean showUsage() {
            return showUsage;
        }
    }

    static class UncheckedBadArgs extends RuntimeException implements BadArguments {
        static final long serialVersionUID = -1L;
        final BadArgs cause;
        UncheckedBadArgs(BadArgs cause) {
            super(cause);
            this.cause = cause;
        }
        @Override
        public String getKey() {
            return cause.key;
        }

        @Override
        public Object[] getArgs() {
            return cause.args;
        }

        @Override
        public boolean showUsage() {
            return cause.showUsage;
        }
    }

    static abstract class Option {
        Option(boolean hasArg, String... aliases) {
            this.hasArg = hasArg;
            this.aliases = aliases;
        }

        Option(boolean hasArg, CommandOption cmd) {
            this(hasArg, cmd.names());
        }

        boolean isHidden() {
            return false;
        }

        boolean matches(String opt) {
            for (String a : aliases) {
                if (a.equals(opt))
                    return true;
                if (hasArg && opt.startsWith(a + "="))
                    return true;
            }
            return false;
        }

        boolean ignoreRest() {
            return false;
        }

        abstract void process(JdepsTask task, String opt, String arg) throws BadArgs;
        final boolean hasArg;
        final String[] aliases;
    }

    static abstract class HiddenOption extends Option {
        HiddenOption(boolean hasArg, String... aliases) {
            super(hasArg, aliases);
        }

        boolean isHidden() {
            return true;
        }
    }

    enum CommandOption {
        ANALYZE_DEPS(""),
        GENERATE_DOT_FILE("-dotoutput", "--dot-output"),
        GENERATE_MODULE_INFO("--generate-module-info"),
        GENERATE_OPEN_MODULE("--generate-open-module"),
        LIST_DEPS("--list-deps"),
        LIST_REDUCED_DEPS("--list-reduced-deps"),
        PRINT_MODULE_DEPS("--print-module-deps"),
        CHECK_MODULES("--check");

        private final String[] names;
        CommandOption(String... names) {
            this.names = names;
        }

        String[] names() {
            return names;
        }

        @Override
        public String toString() {
            return names[0];
        }
    }

    static Option[] recognizedOptions = {
        new Option(false, "-h", "-?", "-help", "--help") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.help = true;
            }
        },
        new Option(true, CommandOption.GENERATE_DOT_FILE) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.genDotFile(Paths.get(arg));
            }
        },
        new Option(false, "-s", "-summary") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.showSummary = true;
            }
        },
        new Option(false, "-v", "-verbose",
                                "-verbose:module",
                                "-verbose:package",
                                "-verbose:class") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                switch (opt) {
                    case "-v":
                    case "-verbose":
                        task.options.verbose = VERBOSE;
                        task.options.filterSameArchive = false;
                        task.options.filterSamePackage = false;
                        break;
                    case "-verbose:module":
                        task.options.verbose = MODULE;
                        break;
                    case "-verbose:package":
                        task.options.verbose = PACKAGE;
                        break;
                    case "-verbose:class":
                        task.options.verbose = CLASS;
                        break;
                    default:
                        throw new BadArgs("err.invalid.arg.for.option", opt);
                }
            }
        },
        new Option(false, "-apionly", "--api-only") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.apiOnly = true;
            }
        },

        new Option(false, "-jdkinternals", "--jdk-internals") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.findJDKInternals = true;
                if (task.options.includePattern == null) {
                    task.options.includePattern = Pattern.compile(".*");
                }
            }
        },

        // ---- paths option ----
        new Option(true, "-cp", "-classpath", "--class-path") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.classpath = arg;
            }
        },
        new Option(true, "--module-path") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                task.options.modulePath = arg;
            }
        },
        new Option(true, "--upgrade-module-path") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                task.options.upgradeModulePath = arg;
            }
        },
        new Option(true, "--system") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (arg.equals("none")) {
                    task.options.systemModulePath = null;
                } else {
                    Path path = Paths.get(arg);
                    if (Files.isRegularFile(path.resolve("lib").resolve("modules")))
                        task.options.systemModulePath = arg;
                    else
                        throw new BadArgs("err.invalid.path", arg);
                }
            }
        },
        new Option(true, "--add-modules") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                Set<String> mods = Set.of(arg.split(","));
                task.options.addmods.addAll(mods);
            }
        },
        new Option(true, "--multi-release") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (arg.equalsIgnoreCase("base")) {
                    task.options.multiRelease = JarFile.baseVersion();
                } else {
                    try {
                        int v = Integer.parseInt(arg);
                        if (v < 9) {
                            throw new BadArgs("err.invalid.arg.for.option", arg);
                        }
                    } catch (NumberFormatException x) {
                        throw new BadArgs("err.invalid.arg.for.option", arg);
                    }
                    task.options.multiRelease = Runtime.Version.parse(arg);
                }
            }
        },
        new Option(false, "-q", "-quiet") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.nowarning = true;
            }
        },
        new Option(false, "-version", "--version") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.version = true;
            }
        },

        // ---- module-specific options ----

        new Option(true, "-m", "--module") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (!task.options.rootModules.isEmpty()) {
                    throw new BadArgs("err.option.already.specified", opt);
                }
                task.options.rootModules.add(arg);
                task.options.addmods.add(arg);
            }
        },
        new Option(true, CommandOption.GENERATE_MODULE_INFO) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.genModuleInfo(Paths.get(arg), false);
            }
        },
        new Option(true, CommandOption.GENERATE_OPEN_MODULE) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.genModuleInfo(Paths.get(arg), true);
            }
        },
        new Option(true, CommandOption.CHECK_MODULES) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                Set<String> mods =  Set.of(arg.split(","));
                task.options.addmods.addAll(mods);
                task.command = task.checkModuleDeps(mods);
            }
        },
        new Option(false, CommandOption.LIST_DEPS) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.listModuleDeps(CommandOption.LIST_DEPS);
            }
        },
        new Option(false, CommandOption.LIST_REDUCED_DEPS) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.listModuleDeps(CommandOption.LIST_REDUCED_DEPS);
            }
        },
        new Option(false, CommandOption.PRINT_MODULE_DEPS) {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                if (task.command != null) {
                    throw new BadArgs("err.command.set", task.command, opt);
                }
                task.command = task.listModuleDeps(CommandOption.PRINT_MODULE_DEPS);
            }
        },

        // ---- Target filtering options ----
        new Option(true, "-p", "-package", "--package") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.packageNames.add(arg);
            }
        },
        new Option(true, "-e", "-regex", "--regex") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.regex = Pattern.compile(arg);
            }
        },
        new Option(true, "--require") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.requires.add(arg);
                task.options.addmods.add(arg);
            }
        },
        new Option(true, "-f", "-filter") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.filterRegex = Pattern.compile(arg);
            }
        },
        new Option(false, "-filter:package",
                          "-filter:archive", "-filter:module",
                          "-filter:none") {
            void process(JdepsTask task, String opt, String arg) {
                switch (opt) {
                    case "-filter:package":
                        task.options.filterSamePackage = true;
                        task.options.filterSameArchive = false;
                        break;
                    case "-filter:archive":
                    case "-filter:module":
                        task.options.filterSameArchive = true;
                        task.options.filterSamePackage = false;
                        break;
                    case "-filter:none":
                        task.options.filterSameArchive = false;
                        task.options.filterSamePackage = false;
                        break;
                }
            }
        },

        // ---- Source filtering options ----
        new Option(true, "-include") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                task.options.includePattern = Pattern.compile(arg);
            }
        },

        new Option(false, "-P", "-profile") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                task.options.showProfile = true;
            }
        },

        new Option(false, "-R", "-recursive") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.depth = 0;
                // turn off filtering
                task.options.filterSameArchive = false;
                task.options.filterSamePackage = false;
            }
        },

        new Option(false, "-I", "--inverse") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.inverse = true;
                // equivalent to the inverse of compile-time view analysis
                task.options.compileTimeView = true;
                task.options.filterSamePackage = true;
                task.options.filterSameArchive = true;
            }
        },

        new Option(false, "--compile-time") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.compileTimeView = true;
                task.options.filterSamePackage = true;
                task.options.filterSameArchive = true;
                task.options.depth = 0;
            }
        },

        new HiddenOption(false, "-fullversion") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.fullVersion = true;
            }
        },
        new HiddenOption(false, "-showlabel") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.showLabel = true;
            }
        },
        new HiddenOption(false, "--hide-show-module") {
            void process(JdepsTask task, String opt, String arg) {
                task.options.showModule = false;
            }
        },
        new HiddenOption(true, "-depth") {
            void process(JdepsTask task, String opt, String arg) throws BadArgs {
                try {
                    task.options.depth = Integer.parseInt(arg);
                } catch (NumberFormatException e) {
                    throw new BadArgs("err.invalid.arg.for.option", opt);
                }
            }
        },
    };

    private static final String PROGNAME = "jdeps";
    private final Options options = new Options();
    private final List<String> inputArgs = new ArrayList<>();

    private Command command;
    private PrintWriter log;
    void setLog(PrintWriter out) {
        log = out;
    }

    /**
     * Result codes.
     */
    static final int EXIT_OK = 0,       // Completed with no errors.
                     EXIT_ERROR = 1,    // Completed but reported errors.
                     EXIT_CMDERR = 2,   // Bad command-line arguments
                     EXIT_SYSERR = 3,   // System error or resource exhaustion.
                     EXIT_ABNORMAL = 4; // terminated abnormally

    int run(String... args) {
        if (log == null) {
            log = new PrintWriter(System.out);
        }
        try {
            handleOptions(args);
            if (options.help) {
                showHelp();
            }
            if (options.version || options.fullVersion) {
                showVersion(options.fullVersion);
            }
            if (options.help || options.version || options.fullVersion) {
                return EXIT_OK;
            }
            if (options.numFilters() > 1) {
                reportError("err.invalid.filters");
                return EXIT_CMDERR;
            }

            // default command to analyze dependences
            if (command == null) {
                command = analyzeDeps();
            }
            if (!command.checkOptions()) {
                return EXIT_CMDERR;
            }

            boolean ok = run();
            return ok ? EXIT_OK : EXIT_ERROR;

        } catch (BadArgs|UncheckedBadArgs e) {
            reportError(e.getKey(), e.getArgs());
            if (e.showUsage()) {
                log.println(getMessage("main.usage.summary", PROGNAME));
            }
            return EXIT_CMDERR;
        } catch (ResolutionException e) {
            reportError("err.exception.message", e.getMessage());
            return EXIT_CMDERR;
        } catch (IOException e) {
            e.printStackTrace();
            return EXIT_CMDERR;
        } catch (MultiReleaseException e) {
            reportError(e.getKey(), e.getParams());
            return EXIT_CMDERR;  // could be EXIT_ABNORMAL sometimes
        } finally {
            log.flush();
        }
    }

    boolean run() throws IOException {
        try (JdepsConfiguration config = buildConfig()) {
            if (!options.nowarning) {
                // detect split packages
                config.splitPackages().entrySet()
                      .stream()
                      .sorted(Map.Entry.comparingByKey())
                      .forEach(e -> warning("warn.split.package",
                                            e.getKey(),
                                            e.getValue().stream().collect(joining(" "))));
            }

            // check if any module specified in --add-modules, --require, and -m is missing
            options.addmods.stream()
                .filter(mn -> !JdepsConfiguration.isToken(mn))
                .forEach(mn -> config.findModule(mn).orElseThrow(() ->
                    new UncheckedBadArgs(new BadArgs("err.module.not.found", mn))));

            return command.run(config);
        }
    }

    private JdepsConfiguration buildConfig() throws IOException {
        JdepsConfiguration.Builder builder =
            new JdepsConfiguration.Builder(options.systemModulePath);

        builder.upgradeModulePath(options.upgradeModulePath)
               .appModulePath(options.modulePath)
               .addmods(options.addmods)
               .addmods(command.addModules());

        if (options.classpath != null)
            builder.addClassPath(options.classpath);

        if (options.multiRelease != null)
            builder.multiRelease(options.multiRelease);

        // build the root set of archives to be analyzed
        for (String s : inputArgs) {
            Path p = Paths.get(s);
            if (Files.exists(p)) {
                builder.addRoot(p);
            } else {
                warning("warn.invalid.arg", s);
            }
        }

        return builder.build();
    }

    // ---- factory methods to create a Command

    private AnalyzeDeps analyzeDeps() throws BadArgs {
        return options.inverse ? new InverseAnalyzeDeps()
                               : new AnalyzeDeps();
    }

    private GenDotFile genDotFile(Path dir) throws BadArgs {
        if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
            throw new BadArgs("err.invalid.path", dir.toString());
        }
        return new GenDotFile(dir);
    }

    private GenModuleInfo genModuleInfo(Path dir, boolean openModule) throws BadArgs {
        if (Files.exists(dir) && (!Files.isDirectory(dir) || !Files.isWritable(dir))) {
            throw new BadArgs("err.invalid.path", dir.toString());
        }
        return new GenModuleInfo(dir, openModule);
    }

    private ListModuleDeps listModuleDeps(CommandOption option) throws BadArgs {
        switch (option) {
            case LIST_DEPS:
                return new ListModuleDeps(option, true, false);
            case LIST_REDUCED_DEPS:
                return new ListModuleDeps(option, true, true);
            case PRINT_MODULE_DEPS:
                return new ListModuleDeps(option, false, true, ",");
            default:
                throw new IllegalArgumentException(option.toString());
        }
    }

    private CheckModuleDeps checkModuleDeps(Set<String> mods) throws BadArgs {
        return new CheckModuleDeps(mods);
    }

    abstract class Command {
        final CommandOption option;
        protected Command(CommandOption option) {
            this.option = option;
        }

        /**
         * Returns true if the command-line options are all valid;
         * otherwise, returns false.
         */
        abstract boolean checkOptions();

        /**
         * Do analysis
         */
        abstract boolean run(JdepsConfiguration config) throws IOException;

        /**
         * Includes all modules on system module path and application module path
         *
         * When a named module is analyzed, it will analyze the dependences
         * only.  The method should be overridden when this command should
         * analyze all modules instead.
         */
        Set<String> addModules() {
            return Set.of();
        }

        @Override
        public String toString() {
            return option.toString();
        }
    }


    /**
     * Analyze dependences
     */
    class AnalyzeDeps extends Command {
        JdepsWriter writer;
        AnalyzeDeps() {
            this(CommandOption.ANALYZE_DEPS);
        }

        AnalyzeDeps(CommandOption option) {
            super(option);
        }

        @Override
        boolean checkOptions() {
            if (options.findJDKInternals) {
                // cannot set any filter, -verbose and -summary option
                if (options.showSummary || options.verbose != null) {
                    reportError("err.invalid.options", "-summary or -verbose",
                                "-jdkinternals");
                    return false;
                }
                if (options.hasFilter()) {
                    reportError("err.invalid.options", "--package, --regex, --require",
                                "-jdkinternals");
                    return false;
                }
            }
            if (options.showSummary) {
                // -summary cannot use with -verbose option
                if (options.verbose != null) {
                    reportError("err.invalid.options", "-v, -verbose", "-s, -summary");
                    return false;
                }
            }

            if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
                reportError("err.invalid.arg.for.option", "-m");
            }
            if (inputArgs.isEmpty() && !options.hasSourcePath()) {
                showHelp();
                return false;
            }
            return true;
        }

        /*
         * Default is to show package-level dependencies
         */
        Type getAnalyzerType() {
            if (options.showSummary)
                return Type.SUMMARY;

            if (options.findJDKInternals)
                return Type.CLASS;

            // default to package-level verbose
           return options.verbose != null ? options.verbose : PACKAGE;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            Type type = getAnalyzerType();
            // default to package-level verbose
            JdepsWriter writer = new SimpleWriter(log,
                                                  type,
                                                  options.showProfile,
                                                  options.showModule);

            return run(config, writer, type);
        }

        boolean run(JdepsConfiguration config, JdepsWriter writer, Type type)
            throws IOException
        {
            // analyze the dependencies
            DepsAnalyzer analyzer = new DepsAnalyzer(config,
                                                     dependencyFilter(config),
                                                     writer,
                                                     type,
                                                     options.apiOnly);

            boolean ok = analyzer.run(options.compileTimeView, options.depth);

            // print skipped entries, if any
            if (!options.nowarning) {
                analyzer.archives()
                    .forEach(archive -> archive.reader()
                        .skippedEntries().stream()
                        .forEach(name -> warning("warn.skipped.entry", name)));
            }

            if (options.findJDKInternals && !options.nowarning) {
                Map<String, String> jdkInternals = new TreeMap<>();
                Set<String> deps = analyzer.dependences();
                // find the ones with replacement
                deps.forEach(cn -> replacementFor(cn).ifPresent(
                    repl -> jdkInternals.put(cn, repl))
                );

                if (!deps.isEmpty()) {
                    log.println();
                    warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
                }

                if (!jdkInternals.isEmpty()) {
                    log.println();
                    String internalApiTitle = getMessage("internal.api.column.header");
                    String replacementApiTitle = getMessage("public.api.replacement.column.header");
                    log.format("%-40s %s%n", internalApiTitle, replacementApiTitle);
                    log.format("%-40s %s%n",
                               internalApiTitle.replaceAll(".", "-"),
                               replacementApiTitle.replaceAll(".", "-"));
                    jdkInternals.entrySet().stream()
                        .forEach(e -> {
                            String key = e.getKey();
                            String[] lines = e.getValue().split("\\n");
                            for (String s : lines) {
                                log.format("%-40s %s%n", key, s);
                                key = "";
                            }
                        });
                }
            }
            return ok;
        }
    }


    class InverseAnalyzeDeps extends AnalyzeDeps {
        InverseAnalyzeDeps() {
        }

        @Override
        boolean checkOptions() {
            if (options.depth != 1) {
                reportError("err.invalid.options", "-R", "--inverse");
                return false;
            }

            if (options.numFilters() == 0) {
                reportError("err.filter.not.specified");
                return false;
            }

            if (!super.checkOptions()) {
                return false;
            }

            return true;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            Type type = getAnalyzerType();

            InverseDepsAnalyzer analyzer =
                new InverseDepsAnalyzer(config,
                                        dependencyFilter(config),
                                        writer,
                                        type,
                                        options.apiOnly);
            boolean ok = analyzer.run();

            log.println();
            if (!options.requires.isEmpty())
                log.println(getMessage("inverse.transitive.dependencies.on",
                                       options.requires));
            else
                log.println(getMessage("inverse.transitive.dependencies.matching",
                                       options.regex != null
                                           ? options.regex.toString()
                                           : "packages " + options.packageNames));

            analyzer.inverseDependences()
                    .stream()
                    .sorted(comparator())
                    .map(this::toInversePath)
                    .forEach(log::println);
            return ok;
        }

        private String toInversePath(Deque<Archive> path) {
            return path.stream()
                       .map(Archive::getName)
                       .collect(joining(" <- "));
        }

        /*
         * Returns a comparator for sorting the inversed path, grouped by
         * the first module name, then the shortest path and then sort by
         * the module names of each path
         */
        private Comparator<Deque<Archive>> comparator() {
            return Comparator.<Deque<Archive>, String>
                comparing(deque -> deque.peekFirst().getName())
                    .thenComparingInt(Deque::size)
                    .thenComparing(this::toInversePath);
        }

        /*
         * Returns true if --require is specified so that all modules are
         * analyzed to find all modules that depend on the modules specified in the
         * --require option directly and indirectly
         */
        Set<String> addModules() {
            return options.requires.size() > 0 ? Set.of("ALL-SYSTEM") : Set.of();
        }
    }


    class GenModuleInfo extends Command {
        final Path dir;
        final boolean openModule;
        GenModuleInfo(Path dir, boolean openModule) {
            super(CommandOption.GENERATE_MODULE_INFO);
            this.dir = dir;
            this.openModule = openModule;
        }

        @Override
        boolean checkOptions() {
            if (options.classpath != null) {
                reportError("err.invalid.options", "-classpath",
                            option);
                return false;
            }
            if (options.hasFilter()) {
                reportError("err.invalid.options", "--package, --regex, --require",
                            option);
                return false;
            }
            return true;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            // check if any JAR file contains unnamed package
            for (String arg : inputArgs) {
                try (ClassFileReader reader = ClassFileReader.newInstance(Paths.get(arg))) {
                    Optional<String> classInUnnamedPackage =
                        reader.entries().stream()
                             .filter(n -> n.endsWith(".class"))
                             .filter(cn -> toPackageName(cn).isEmpty())
                             .findFirst();

                    if (classInUnnamedPackage.isPresent()) {
                        if (classInUnnamedPackage.get().equals("module-info.class")) {
                            reportError("err.genmoduleinfo.not.jarfile", arg);
                        } else {
                            reportError("err.genmoduleinfo.unnamed.package", arg);
                        }
                        return false;
                    }
                }
            }

            ModuleInfoBuilder builder
                 = new ModuleInfoBuilder(config, inputArgs, dir, openModule);
            boolean ok = builder.run();

            if (!ok && !options.nowarning) {
                reportError("err.missing.dependences");
                builder.visitMissingDeps(
                        (origin, originArchive, target, targetArchive) -> {
                            if (builder.notFound(targetArchive))
                                log.format("   %-50s -> %-50s %s%n",
                                    origin, target, targetArchive.getName());
                        });
            }
            return ok;
        }

        private String toPackageName(String name) {
            int i = name.lastIndexOf('/');
            return i > 0 ? name.replace('/', '.').substring(0, i) : "";
        }
    }

    class CheckModuleDeps extends Command {
        final Set<String> modules;
        CheckModuleDeps(Set<String> mods) {
            super(CommandOption.CHECK_MODULES);
            this.modules = mods;
        }

        @Override
        boolean checkOptions() {
            if (!inputArgs.isEmpty()) {
                reportError("err.invalid.options", inputArgs, "--check");
                return false;
            }
            return true;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            if (!config.initialArchives().isEmpty()) {
                String list = config.initialArchives().stream()
                                    .map(Archive::getPathName).collect(joining(" "));
                throw new UncheckedBadArgs(new BadArgs("err.invalid.options",
                                                       list, "--check"));
            }
            return new ModuleAnalyzer(config, log, modules).run();
        }

        /*
         * Returns true to analyze all modules
         */
        Set<String> addModules() {
            return Set.of("ALL-SYSTEM", "ALL-MODULE-PATH");
        }
    }

    class ListModuleDeps extends Command {
        final boolean jdkinternals;
        final boolean reduced;
        final String separator;
        ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced) {
            this(option, jdkinternals, reduced, System.getProperty("line.separator"));
        }
        ListModuleDeps(CommandOption option, boolean jdkinternals, boolean reduced, String sep) {
            super(option);
            this.jdkinternals = jdkinternals;
            this.reduced = reduced;
            this.separator = sep;
        }

        @Override
        boolean checkOptions() {
            if (options.showSummary || options.verbose != null) {
                reportError("err.invalid.options", "-summary or -verbose",
                            option);
                return false;
            }
            if (options.findJDKInternals) {
                reportError("err.invalid.options", "-jdkinternals",
                            option);
                return false;
            }

            if (!inputArgs.isEmpty() && !options.rootModules.isEmpty()) {
                reportError("err.invalid.arg.for.option", "-m");
            }
            if (inputArgs.isEmpty() && !options.hasSourcePath()) {
                showHelp();
                return false;
            }
            return true;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            return new ModuleExportsAnalyzer(config,
                                             dependencyFilter(config),
                                             jdkinternals,
                                             reduced,
                                             log,
                                             separator).run();
        }
    }


    class GenDotFile extends AnalyzeDeps {
        final Path dotOutputDir;
        GenDotFile(Path dotOutputDir) {
            super(CommandOption.GENERATE_DOT_FILE);

            this.dotOutputDir = dotOutputDir;
        }

        @Override
        boolean run(JdepsConfiguration config) throws IOException {
            if ((options.showSummary || options.verbose == MODULE) &&
                !options.addmods.isEmpty() && inputArgs.isEmpty()) {
                // generate dot graph from the resolved graph from module
                // resolution.  No class dependency analysis is performed.
                return new ModuleDotGraph(config, options.apiOnly)
                        .genDotFiles(dotOutputDir);
            }

            Type type = getAnalyzerType();
            JdepsWriter writer = new DotFileWriter(dotOutputDir,
                                                   type,
                                                   options.showProfile,
                                                   options.showModule,
                                                   options.showLabel);
            return run(config, writer, type);
        }
    }

    /**
     * Returns a filter used during dependency analysis
     */
    private JdepsFilter dependencyFilter(JdepsConfiguration config) {
        // Filter specified by -filter, -package, -regex, and --require options
        JdepsFilter.Builder builder = new JdepsFilter.Builder();

        // source filters
        builder.includePattern(options.includePattern);

        // target filters
        builder.filter(options.filterSamePackage, options.filterSameArchive);
        builder.findJDKInternals(options.findJDKInternals);

        // --require
        if (!options.requires.isEmpty()) {
            options.requires.stream()
                .forEach(mn -> {
                    Module m = config.findModule(mn).get();
                    builder.requires(mn, m.packages());
                });
        }
        // -regex
        if (options.regex != null)
            builder.regex(options.regex);
        // -package
        if (!options.packageNames.isEmpty())
            builder.packages(options.packageNames);
        // -filter
        if (options.filterRegex != null)
            builder.filter(options.filterRegex);

        return builder.build();
    }

    public void handleOptions(String[] args) throws BadArgs {
        // process options
        for (int i=0; i < args.length; i++) {
            if (args[i].charAt(0) == '-') {
                String name = args[i];
                Option option = getOption(name);
                String param = null;
                if (option.hasArg) {
                    if (name.startsWith("-") && name.indexOf('=') > 0) {
                        param = name.substring(name.indexOf('=') + 1, name.length());
                    } else if (i + 1 < args.length) {
                        param = args[++i];
                    }
                    if (param == null || param.isEmpty() || param.charAt(0) == '-') {
                        throw new BadArgs("err.missing.arg", name).showUsage(true);
                    }
                }
                option.process(this, name, param);
                if (option.ignoreRest()) {
                    i = args.length;
                }
            } else {
                // process rest of the input arguments
                for (; i < args.length; i++) {
                    String name = args[i];
                    if (name.charAt(0) == '-') {
                        throw new BadArgs("err.option.after.class", name).showUsage(true);
                    }
                    inputArgs.add(name);
                }
            }
        }
    }

    private Option getOption(String name) throws BadArgs {
        for (Option o : recognizedOptions) {
            if (o.matches(name)) {
                return o;
            }
        }
        throw new BadArgs("err.unknown.option", name).showUsage(true);
    }

    private void reportError(String key, Object... args) {
        log.println(getMessage("error.prefix") + " " + getMessage(key, args));
    }

    void warning(String key, Object... args) {
        log.println(getMessage("warn.prefix") + " " + getMessage(key, args));
    }

    private void showHelp() {
        log.println(getMessage("main.usage", PROGNAME));
        for (Option o : recognizedOptions) {
            String name = o.aliases[0].substring(1); // there must always be at least one name
            name = name.charAt(0) == '-' ? name.substring(1) : name;
            if (o.isHidden() || name.startsWith("filter:")) {
                continue;
            }
            log.println(getMessage("main.opt." + name));
        }
    }

    private void showVersion(boolean full) {
        log.println(version(full ? "full" : "release"));
    }

    private String version(String key) {
        // key=version:  mm.nn.oo[-milestone]
        // key=full:     mm.mm.oo[-milestone]-build
        if (ResourceBundleHelper.versionRB == null) {
            return System.getProperty("java.version");
        }
        try {
            return ResourceBundleHelper.versionRB.getString(key);
        } catch (MissingResourceException e) {
            return getMessage("version.unknown", System.getProperty("java.version"));
        }
    }

    static String getMessage(String key, Object... args) {
        try {
            return MessageFormat.format(ResourceBundleHelper.bundle.getString(key), args);
        } catch (MissingResourceException e) {
            throw new InternalError("Missing message: " + key);
        }
    }

    private static class Options {
        boolean help;
        boolean version;
        boolean fullVersion;
        boolean showProfile;
        boolean showModule = true;
        boolean showSummary;
        boolean apiOnly;
        boolean showLabel;
        boolean findJDKInternals;
        boolean nowarning = false;
        Analyzer.Type verbose;
        // default filter references from same package
        boolean filterSamePackage = true;
        boolean filterSameArchive = false;
        Pattern filterRegex;
        String classpath;
        int depth = 1;
        Set<String> requires = new HashSet<>();
        Set<String> packageNames = new HashSet<>();
        Pattern regex;             // apply to the dependences
        Pattern includePattern;
        boolean inverse = false;
        boolean compileTimeView = false;
        String systemModulePath = System.getProperty("java.home");
        String upgradeModulePath;
        String modulePath;
        Set<String> rootModules = new HashSet<>();
        Set<String> addmods = new HashSet<>();
        Runtime.Version multiRelease;

        boolean hasSourcePath() {
            return !addmods.isEmpty() || includePattern != null;
        }

        boolean hasFilter() {
            return numFilters() > 0;
        }

        int numFilters() {
            int count = 0;
            if (requires.size() > 0) count++;
            if (regex != null) count++;
            if (packageNames.size() > 0) count++;
            return count;
        }
    }

    private static class ResourceBundleHelper {
        static final ResourceBundle versionRB;
        static final ResourceBundle bundle;
        static final ResourceBundle jdkinternals;

        static {
            Locale locale = Locale.getDefault();
            try {
                bundle = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdeps", locale);
            } catch (MissingResourceException e) {
                throw new InternalError("Cannot find jdeps resource bundle for locale " + locale);
            }
            try {
                versionRB = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.version");
            } catch (MissingResourceException e) {
                throw new InternalError("version.resource.missing");
            }
            try {
                jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
            } catch (MissingResourceException e) {
                throw new InternalError("Cannot find jdkinternals resource bundle");
            }
        }
    }

    /**
     * Returns the recommended replacement API for the given classname;
     * or return null if replacement API is not known.
     */
    private Optional<String> replacementFor(String cn) {
        String name = cn;
        String value = null;
        while (value == null && name != null) {
            try {
                value = ResourceBundleHelper.jdkinternals.getString(name);
            } catch (MissingResourceException e) {
                // go up one subpackage level
                int i = name.lastIndexOf('.');
                name = i > 0 ? name.substring(0, i) : null;
            }
        }
        return Optional.ofNullable(value);
    }
}

com/sun/tools/jdeps/JdepsTask.java

 

JDK 11 jdk.jdi.jmod - JDI Tool

JDK 11 jdk.jconsole.jmod - JConsole Tool

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2018-11-09, 5140👍, 0💬