JDK 11 jdk.jlink.jmod - JLink Tool

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

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

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

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

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

✍: FYIcenter

jdk/tools/jlink/internal/ImageResourcesTree.java

/*
 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */
package jdk.tools.jlink.internal;

import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

/**
 * A class to build a sorted tree of Resource paths as a tree of ImageLocation.
 *
 */
// XXX Public only due to the JImageTask / JImageTask code duplication
public final class ImageResourcesTree {
    public static boolean isTreeInfoResource(String path) {
        return path.startsWith("/packages") || path.startsWith("/modules");
    }

    /**
     * Path item tree node.
     */
    private static class Node {

        private final String name;
        private final Map<String, Node> children = new TreeMap<>();
        private final Node parent;
        private ImageLocationWriter loc;

        private Node(String name, Node parent) {
            this.name = name;
            this.parent = parent;

            if (parent != null) {
                parent.children.put(name, this);
            }
        }

        public String getPath() {
            if (parent == null) {
                return "/";
            }
            return buildPath(this);
        }

        public String getName() {
            return name;
        }

        public Node getChildren(String name) {
            Node item = children.get(name);
            return item;
        }

        private static String buildPath(Node item) {
            if (item == null) {
                return null;
            }
            String path = buildPath(item.parent);
            if (path == null) {
                return item.getName();
            } else {
                return path + "/" + item.getName();
            }
        }
    }

    private static final class ResourceNode extends Node {

        public ResourceNode(String name, Node parent) {
            super(name, parent);
        }
    }

    private static class PackageNode extends Node {
        /**
         * A reference to a package. Empty packages can be located inside one or
         * more modules. A package with classes exist in only one module.
         */
        final static class PackageReference {

            private final String name;
            private final boolean isEmpty;

            PackageReference(String name, boolean isEmpty) {
                this.name = Objects.requireNonNull(name);
                this.isEmpty = isEmpty;
            }

            @Override
            public String toString() {
                return name + "[empty:" + isEmpty + "]";
            }
        }

        private final Map<String, PackageReference> references = new TreeMap<>();

        PackageNode(String name, Node parent) {
            super(name, parent);
        }

        private void addReference(String name, boolean isEmpty) {
            PackageReference ref = references.get(name);
            if (ref == null || ref.isEmpty) {
                references.put(name, new PackageReference(name, isEmpty));
            }
        }

        private void validate() {
            boolean exists = false;
            for (PackageReference ref : references.values()) {
                if (!ref.isEmpty) {
                    if (exists) {
                        throw new RuntimeException("Multiple modules to contain package "
                                + getName());
                    } else {
                        exists = true;
                    }
                }
            }
        }
    }

    /**
     * Tree of nodes.
     */
    private static final class Tree {

        private final Map<String, Node> directAccess = new HashMap<>();
        private final List<String> paths;
        private final Node root;
        private Node modules;
        private Node packages;

        private Tree(List<String> paths) {
            this.paths = paths;
            root = new Node("", null);
            buildTree();
        }

        private void buildTree() {
            modules = new Node("modules", root);
            directAccess.put(modules.getPath(), modules);

            Map<String, Set<String>> moduleToPackage = new TreeMap<>();
            Map<String, Set<String>> packageToModule = new TreeMap<>();

            for (String p : paths) {
                if (!p.startsWith("/")) {
                    continue;
                }
                String[] split = p.split("/");
                // minimum length is 3 items: /<mod>/<pkg>
                if (split.length < 3) {
                    System.err.println("Resources tree, invalid data structure, "
                            + "skipping " + p);
                    continue;
                }
                Node current = modules;
                String module = null;
                for (int i = 0; i < split.length; i++) {
                    // When a non terminal node is marked as being a resource, something is wrong.
                    // It has been observed some badly created jar file to contain
                    // invalid directory entry marled as not directory (see 8131762)
                    if (current instanceof ResourceNode) {
                        System.err.println("Resources tree, invalid data structure, "
                                + "skipping " + p);
                        continue;
                    }
                    String s = split[i];
                    if (!s.isEmpty()) {
                        // First item, this is the module, simply add a new node to the
                        // tree.
                        if (module == null) {
                            module = s;
                        }
                        Node n = current.children.get(s);
                        if (n == null) {
                            if (i == split.length - 1) { // Leaf
                                n = new ResourceNode(s, current);
                                String pkg = toPackageName(n.parent);
                                //System.err.println("Adding a resource node. pkg " + pkg + ", name " + s);
                                if (pkg != null && !pkg.startsWith("META-INF")) {
                                    Set<String> pkgs = moduleToPackage.get(module);
                                    if (pkgs == null) {
                                        pkgs = new TreeSet<>();
                                        moduleToPackage.put(module, pkgs);
                                    }
                                    pkgs.add(pkg);
                                }
                            } else { // put only sub trees, no leaf
                                n = new Node(s, current);
                                directAccess.put(n.getPath(), n);
                                String pkg = toPackageName(n);
                                if (pkg != null && !pkg.startsWith("META-INF")) {
                                    Set<String> mods = packageToModule.get(pkg);
                                    if (mods == null) {
                                        mods = new TreeSet<>();
                                        packageToModule.put(pkg, mods);
                                    }
                                    mods.add(module);
                                }
                            }
                        }
                        current = n;
                    }
                }
            }
            packages = new Node("packages", root);
            directAccess.put(packages.getPath(), packages);
            // The subset of package nodes that have some content.
            // These packages exist only in a single module.
            for (Map.Entry<String, Set<String>> entry : moduleToPackage.entrySet()) {
                for (String pkg : entry.getValue()) {
                    PackageNode pkgNode = new PackageNode(pkg, packages);
                    pkgNode.addReference(entry.getKey(), false);
                    directAccess.put(pkgNode.getPath(), pkgNode);
                }
            }

            // All packages
            for (Map.Entry<String, Set<String>> entry : packageToModule.entrySet()) {
                // Do we already have a package node?
                PackageNode pkgNode = (PackageNode) packages.getChildren(entry.getKey());
                if (pkgNode == null) {
                    pkgNode = new PackageNode(entry.getKey(), packages);
                }
                for (String module : entry.getValue()) {
                    pkgNode.addReference(module, true);
                }
                directAccess.put(pkgNode.getPath(), pkgNode);
            }
            // Validate that the packages are well formed.
            for (Node n : packages.children.values()) {
                ((PackageNode)n).validate();
            }

        }

        public String toResourceName(Node node) {
            if (!node.children.isEmpty()) {
                throw new RuntimeException("Node is not a resource");
            }
            return removeRadical(node);
        }

        public String getModule(Node node) {
            if (node.parent == null || node.getName().equals("modules")
                    || node.getName().startsWith("packages")) {
                return null;
            }
            String path = removeRadical(node);
            // "/xxx/...";
            path = path.substring(1);
            int i = path.indexOf("/");
            if (i == -1) {
                return path;
            } else {
                return path.substring(0, i);
            }
        }

        public String toPackageName(Node node) {
            if (node.parent == null) {
                return null;
            }
            String path = removeRadical(node.getPath(), "/modules/");
            String module = getModule(node);
            if (path.equals(module)) {
                return null;
            }
            String pkg = removeRadical(path, module + "/");
            return pkg.replaceAll("/", ".");
        }

        public String removeRadical(Node node) {
            return removeRadical(node.getPath(), "/modules");
        }

        private String removeRadical(String path, String str) {
            if (!(path.length() < str.length())) {
                path = path.substring(str.length());
            }
            return path;
        }

        public Node getRoot() {
            return root;
        }

        public Map<String, Node> getMap() {
            return directAccess;
        }
    }

    private static final class LocationsAdder {

        private long offset;
        private final List<byte[]> content = new ArrayList<>();
        private final BasicImageWriter writer;
        private final Tree tree;

        LocationsAdder(Tree tree, long offset, BasicImageWriter writer) {
            this.tree = tree;
            this.offset = offset;
            this.writer = writer;
            addLocations(tree.getRoot());
        }

        private int addLocations(Node current) {
            if (current instanceof PackageNode) {
                PackageNode pkgNode = (PackageNode) current;
                int size = pkgNode.references.size() * 8;
                writer.addLocation(current.getPath(), offset, 0, size);
                offset += size;
            } else {
                int[] ret = new int[current.children.size()];
                int i = 0;
                for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
                    ret[i] = addLocations(entry.getValue());
                    i += 1;
                }
                if (current != tree.getRoot() && !(current instanceof ResourceNode)) {
                    int size = ret.length * 4;
                    writer.addLocation(current.getPath(), offset, 0, size);
                    offset += size;
                }
            }
            return 0;
        }

        private List<byte[]> computeContent() {
            // Map used to associate Tree item with locations offset.
            Map<String, ImageLocationWriter> outLocations = new HashMap<>();
            for (ImageLocationWriter wr : writer.getLocations()) {
                outLocations.put(wr.getFullName(), wr);
            }
            // Attach location to node
            for (Map.Entry<String, ImageLocationWriter> entry : outLocations.entrySet()) {
                Node item = tree.getMap().get(entry.getKey());
                if (item != null) {
                    item.loc = entry.getValue();
                }
            }
            computeContent(tree.getRoot(), outLocations);
            return content;
        }

        private int computeContent(Node current, Map<String, ImageLocationWriter> outLocations) {
            if (current instanceof PackageNode) {
                // /packages/<pkg name>
                PackageNode pkgNode = (PackageNode) current;
                int size = pkgNode.references.size() * 8;
                ByteBuffer buff = ByteBuffer.allocate(size);
                buff.order(writer.getByteOrder());
                for (PackageNode.PackageReference mod : pkgNode.references.values()) {
                    buff.putInt(mod.isEmpty ? 1 : 0);
                    buff.putInt(writer.addString(mod.name));
                }
                byte[] arr = buff.array();
                content.add(arr);
                current.loc = outLocations.get(current.getPath());
            } else {
                int[] ret = new int[current.children.size()];
                int i = 0;
                for (java.util.Map.Entry<String, Node> entry : current.children.entrySet()) {
                    ret[i] = computeContent(entry.getValue(), outLocations);
                    i += 1;
                }
                if (ret.length > 0) {
                    int size = ret.length * 4;
                    ByteBuffer buff = ByteBuffer.allocate(size);
                    buff.order(writer.getByteOrder());
                    for (int val : ret) {
                        buff.putInt(val);
                    }
                    byte[] arr = buff.array();
                    content.add(arr);
                } else {
                    if (current instanceof ResourceNode) {
                        // A resource location, remove "/modules"
                        String s = tree.toResourceName(current);
                        current.loc = outLocations.get(s);
                    } else {
                        // empty "/packages" or empty "/modules" paths
                        current.loc = outLocations.get(current.getPath());
                    }
                }
                if (current.loc == null && current != tree.getRoot()) {
                    System.err.println("Invalid path in metadata, skipping " + current.getPath());
                }
            }
            return current.loc == null ? 0 : current.loc.getLocationOffset();
        }
    }

    private final List<String> paths;
    private final LocationsAdder adder;

    public ImageResourcesTree(long offset, BasicImageWriter writer, List<String> paths) {
        this.paths = new ArrayList<>();
        this.paths.addAll(paths);
        Collections.sort(this.paths);
        Tree tree = new Tree(this.paths);
        adder = new LocationsAdder(tree, offset, writer);
    }

    public void addContent(DataOutputStream out) throws IOException {
        List<byte[]> content = adder.computeContent();
        for (byte[] c : content) {
            out.write(c, 0, c.length);
        }
    }
}

jdk/tools/jlink/internal/ImageResourcesTree.java

 

JDK 11 jdk.jshell.jmod - JShell Tool

JDK 11 jdk.jfr.jmod - JFR Module

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2018-11-09, 2648👍, 0💬