Appendix 1. Additional materials

1.1. How to build JDK module graph

Create module-info.java in some directory.


module viz {
    requires java.se;
}

					

Create class app.App.java (in the app sub-directory)


package app;

import java.lang.module.ModuleDescriptor.Requires;
import java.util.HashSet;
import java.util.Set;

/**
 * This is the main application to generate graph code.
 * 
 * @author Mikalai Zaikin (mzaikin@gmail.com)
 */
public class App {

    public static void main(String[] args) {
        App app = new App();
        
        var edges = app.getEdges();
        var modules = app.getModules();
        
        // System.out.println(modules);
        
        StringBuffer sb = new StringBuffer("digraph Java11 {\n");
        sb.append("    ratio = fill;\n");
        sb.append("    node [style=filled];\n");        
        edges.forEach((e) -> {
            sb.append(String.format("    \"%s\" -> \"%s\";%n", new Object[]{e.getFrom(), e.getTo()}));
        });
        modules.forEach((m) -> {
            sb.append("\""+m+"\" [color=\"" + (m.startsWith("jdk") ? "darkseagreen" : "cyan") + "\"];\n");
        });
        sb.append("}");
        System.out.println(sb);
        
    }
    
    private HashSet<Edge> getEdges() {
        var edges = new HashSet<Edge>();
        Set<Module> modules = ModuleLayer.boot().modules();
        modules.forEach((module) -> {
            String moduleName = module.getName();
            if (!("viz".equals(moduleName))) {
                Set<Requires> requires = module.getDescriptor().requires();
                requires.forEach((require) -> {
                    edges.add(new Edge(moduleName, require.name()));
                });
            }
        });
        return edges;
    }
    
    private HashSet<String> getModules() {
        var mods = new HashSet<String>();
        Set<Module> modules = ModuleLayer.boot().modules();
        for (Module module : modules) {
            String moduleName = module.getName();
            if ("viz".equals(moduleName)) continue;
            mods.add(moduleName);
        }
        return mods;
    }
}

					

Create class app.Edge.java (in the app sub-directory)


package app;

import java.util.Objects;

/**
 * This is the class to encapsulate edge of the graph.
 * 
 * @author Mikalai Zaikin (mzaikin@gmail.com)
 */
public class Edge {

    private String from;
    private String to;

    public Edge(String from, String to) {
        this.from = from;
        this.to = to;
    }

    public String getFrom() {
        return from;
    }

    public void setFrom(String from) {
        this.from = from;
    }

    public String getTo() {
        return to;
    }

    public void setTo(String to) {
        this.to = to;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Edge edge = (Edge) o;
        return Objects.equals(from, edge.from)
                && Objects.equals(to, edge.to);
    }

    @Override
    public int hashCode() {
        return Objects.hash(from, to);
    }

    @Override
    public String toString() {
        return from + "->" + to;
    }
}

					

Run the code from the directory where module-info.class is located:


C:\USERS\IBM_ADMIN\DOCUMENTS\NETBEANSPROJECTS\VIZ\BUILD\MODULES
└───viz
    │   module-info.class
    │
    └───app
            App.class
            Edge.class

					

"C:\Program Files\Java\jdk-11.0.2\bin\java.exe" --module-path . -m viz/app.App
					

There should be similar output:


digraph Java11 {
    ratio = fill;
    node [style=filled];
    "java.management.rmi" -> "java.base";
    "java.sql" -> "java.xml";
    "java.se" -> "java.management.rmi";
    "java.xml.crypto" -> "java.base";
    "java.se" -> "java.scripting";
    "java.sql" -> "java.base";
    "jdk.scripting.nashorn" -> "java.base";
    "jdk.security.jgss" -> "java.security.sasl";
    "java.smartcardio" -> "java.base";
    "jdk.naming.dns" -> "java.naming";
    "java.xml.crypto" -> "java.xml";
    "java.prefs" -> "java.base";
    "java.se" -> "java.rmi";
    "java.sql.rowset" -> "java.base";
    "java.compiler" -> "java.base";
    "jdk.localedata" -> "java.base";
    "jdk.security.auth" -> "java.security.jgss";
    "jdk.naming.rmi" -> "java.rmi";
    "java.desktop" -> "java.prefs";
    "java.prefs" -> "java.xml";
    "java.rmi" -> "java.logging";
    "jdk.security.jgss" -> "java.logging";
    "jdk.jdeps" -> "jdk.compiler";
    "java.se" -> "java.instrument";
    "jdk.accessibility" -> "java.desktop";
    "jdk.jfr" -> "java.base";
    "jdk.accessibility" -> "java.base";
    "java.logging" -> "java.base";
    "jdk.jdeps" -> "java.base";
    "jdk.naming.rmi" -> "java.naming";
    "jdk.jlink" -> "jdk.jdeps";
    "java.se" -> "java.base";
    "jdk.unsupported.desktop" -> "java.desktop";
    "jdk.crypto.cryptoki" -> "jdk.crypto.ec";
    "jdk.security.auth" -> "java.base";
    "java.sql.rowset" -> "java.sql";
    "jdk.compiler" -> "java.base";
    "jdk.jdeps" -> "java.compiler";
    "jdk.internal.opt" -> "java.base";
    "jdk.naming.dns" -> "java.base";
    "java.rmi" -> "java.base";
    "jdk.management.jfr" -> "java.base";
    "jdk.security.jgss" -> "java.security.jgss";
    "java.sql" -> "java.transaction.xa";
    "java.scripting" -> "java.base";
    "java.management" -> "java.base";
    "jdk.dynalink" -> "java.logging";
    "jdk.management.jfr" -> "java.management";
    "java.se" -> "java.sql";
    "java.se" -> "java.transaction.xa";
    "jdk.javadoc" -> "jdk.compiler";
    "jdk.scripting.nashorn" -> "java.scripting";
    "java.se" -> "java.logging";
    "jdk.crypto.mscapi" -> "java.base";
    "java.se" -> "java.compiler";
    "jdk.jlink" -> "jdk.internal.opt";
    "java.sql" -> "java.logging";
    "java.security.jgss" -> "java.naming";
    "jdk.scripting.nashorn" -> "java.logging";
    "jdk.charsets" -> "java.base";
    "java.desktop" -> "java.datatransfer";
    "jdk.crypto.ec" -> "java.base";
    "java.xml.crypto" -> "java.logging";
    "java.sql.rowset" -> "java.logging";
    "jdk.management.jfr" -> "jdk.jfr";
    "jdk.naming.rmi" -> "java.base";
    "jdk.management.jfr" -> "jdk.management";
    "jdk.jartool" -> "java.base";
    "java.naming" -> "java.base";
    "java.transaction.xa" -> "java.base";
    "java.se" -> "java.xml";
    "jdk.javadoc" -> "java.xml";
    "java.datatransfer" -> "java.base";
    "java.se" -> "java.desktop";
    "jdk.management" -> "java.base";
    "jdk.compiler" -> "java.compiler";
    "jdk.crypto.cryptoki" -> "java.base";
    "java.security.sasl" -> "java.base";
    "java.se" -> "java.security.sasl";
    "java.se" -> "java.prefs";
    "java.security.jgss" -> "java.base";
    "jdk.security.auth" -> "java.naming";
    "jdk.jlink" -> "java.base";
    "jdk.zipfs" -> "java.base";
    "java.net.http" -> "java.base";
    "java.desktop" -> "java.xml";
    "java.se" -> "java.sql.rowset";
    "java.management.rmi" -> "java.naming";
    "jdk.security.jgss" -> "java.base";
    "java.desktop" -> "java.base";
    "jdk.scripting.nashorn" -> "jdk.dynalink";
    "jdk.unsupported.desktop" -> "java.base";
    "jdk.management" -> "java.management";
    "java.se" -> "java.management";
    "java.instrument" -> "java.base";
    "java.naming" -> "java.security.sasl";
    "java.xml" -> "java.base";
    "jdk.javadoc" -> "java.base";
    "java.sql.rowset" -> "java.naming";
    "java.se" -> "java.xml.crypto";
    "jdk.javadoc" -> "java.compiler";
    "java.se" -> "java.datatransfer";
    "jdk.dynalink" -> "java.base";
    "java.management.rmi" -> "java.management";
    "java.security.sasl" -> "java.logging";
    "java.se" -> "java.security.jgss";
    "java.se" -> "java.naming";
    "java.se" -> "java.net.http";
    "java.management.rmi" -> "java.rmi";
"jdk.management.jfr" [color="darkseagreen"];
"java.sql" [color="cyan"];
"java.rmi" [color="cyan"];
"jdk.charsets" [color="darkseagreen"];
"java.transaction.xa" [color="cyan"];
"java.xml.crypto" [color="cyan"];
"java.logging" [color="cyan"];
"java.xml" [color="cyan"];
"jdk.jfr" [color="darkseagreen"];
"java.datatransfer" [color="cyan"];
"jdk.crypto.cryptoki" [color="darkseagreen"];
"java.naming" [color="cyan"];
"java.desktop" [color="cyan"];
"java.se" [color="cyan"];
"java.prefs" [color="cyan"];
"java.net.http" [color="cyan"];
"jdk.compiler" [color="darkseagreen"];
"jdk.naming.rmi" [color="darkseagreen"];
"jdk.internal.opt" [color="darkseagreen"];
"java.security.sasl" [color="cyan"];
"jdk.zipfs" [color="darkseagreen"];
"java.base" [color="cyan"];
"jdk.crypto.ec" [color="darkseagreen"];
"jdk.javadoc" [color="darkseagreen"];
"jdk.crypto.mscapi" [color="darkseagreen"];
"java.management" [color="cyan"];
"java.sql.rowset" [color="cyan"];
"jdk.jlink" [color="darkseagreen"];
"java.smartcardio" [color="cyan"];
"jdk.scripting.nashorn" [color="darkseagreen"];
"java.instrument" [color="cyan"];
"java.security.jgss" [color="cyan"];
"jdk.management" [color="darkseagreen"];
"java.compiler" [color="cyan"];
"jdk.security.auth" [color="darkseagreen"];
"java.scripting" [color="cyan"];
"jdk.dynalink" [color="darkseagreen"];
"jdk.unsupported.desktop" [color="darkseagreen"];
"jdk.jdeps" [color="darkseagreen"];
"jdk.accessibility" [color="darkseagreen"];
"jdk.jartool" [color="darkseagreen"];
"java.management.rmi" [color="cyan"];
"jdk.naming.dns" [color="darkseagreen"];
"jdk.security.jgss" [color="darkseagreen"];
"jdk.localedata" [color="darkseagreen"];
}

					

Use this graph text definition to generate image at http://www.webgraphviz.com or http://viz-js.com.

The result will look as follows:

Figure 1.1. Java SE 11 Module Graph

Java SE 11 Module Graph


Professional hosting         Exam 1Z0-817: Upgrade OCP Java 6, 7 & 8 to Java SE 11 Developer Quiz     Exam 1Z0-810: Upgrade to Java SE 8 Programmer Quiz