JDK 11 jdk.jartool.jmod - JAR Tool

JDK 11 jdk.jartool.jmod is the JMOD file for JDK 11 JAR tool, which can be invoked by the "jar" command.

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

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

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

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

✍: FYIcenter

sun/tools/jar/FingerPrint.java

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

package sun.tools.jar;

import jdk.internal.org.objectweb.asm.*;

import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * A FingerPrint is an abstract representation of a JarFile entry that contains
 * information to determine if the entry represents a class or a
 * resource, and whether two entries are identical.  If the FingerPrint represents
 * a class, it also contains information to (1) describe the public API;
 * (2) compare the public API of this class with another class;  (3) determine
 * whether or not it's a nested class and, if so, the name of the associated
 * outer class; and (4) for an canonically ordered set of classes determine
 * if the class versions are compatible.  A set of classes is canonically
 * ordered if the classes in the set have the same name, and the base class
 * precedes the versioned classes and if each versioned class with version
 * {@code n} precedes classes with versions {@code > n} for all versions
 * {@code n}.
 */
final class FingerPrint {
    private static final MessageDigest MD;

    private final String basename;
    private final String entryName;
    private final int mrversion;

    private final byte[] sha1;
    private final ClassAttributes attrs;
    private final boolean isClassEntry;

    static {
        try {
            MD = MessageDigest.getInstance("SHA-1");
        } catch (NoSuchAlgorithmException x) {
            // log big problem?
            throw new RuntimeException(x);
        }
    }

    public FingerPrint(String basename, String entryName, int mrversion, byte[] bytes)
            throws IOException {
        this.basename = basename;
        this.entryName = entryName;
        this.mrversion = mrversion;
        if (isCafeBabe(bytes)) {
            isClassEntry = true;
            sha1 = sha1(bytes, 8);  // skip magic number and major/minor version
            attrs = getClassAttributes(bytes);
        } else {
            isClassEntry = false;
            sha1 = null;
            attrs = null;
        }
    }

    public boolean isClass() {
        return isClassEntry;
    }

    public boolean isNestedClass() {
        return attrs.nestedClass;
    }

    public boolean isPublicClass() {
        return attrs.publicClass;
    }

    public boolean isIdentical(FingerPrint that) {
        if (that == null) return false;
        if (this == that) return true;
        return isEqual(this.sha1, that.sha1);
    }

    public boolean isCompatibleVersion(FingerPrint that) {
        return attrs.version >= that.attrs.version;
    }

    public boolean isSameAPI(FingerPrint that) {
        if (that == null) return false;
        return attrs.equals(that.attrs);
    }

    public String basename() {
        return basename;
    }

    public String entryName() {
        return entryName;
    }

    public String className() {
        return attrs.name;
    }

    public int mrversion() {
        return mrversion;
    }

    public String outerClassName() {
        return attrs.outerClassName;
    }

    private byte[] sha1(byte[] entry) {
        MD.update(entry);
        return MD.digest();
    }

    private byte[] sha1(byte[] entry, int offset) {
        MD.update(entry, offset, entry.length - offset);
        return MD.digest();
    }

    private boolean isEqual(byte[] sha1_1, byte[] sha1_2) {
        return MessageDigest.isEqual(sha1_1, sha1_2);
    }

    private static final byte[] cafeBabe = {(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe};

    private boolean isCafeBabe(byte[] bytes) {
        if (bytes.length < 4) return false;
        for (int i = 0; i < 4; i++) {
            if (bytes[i] != cafeBabe[i]) {
                return false;
            }
        }
        return true;
    }

    private ClassAttributes getClassAttributes(byte[] bytes) {
        ClassReader rdr = new ClassReader(bytes);
        ClassAttributes attrs = new ClassAttributes();
        rdr.accept(attrs, 0);
        return attrs;
    }

    private static final class Field {
        private final int access;
        private final String name;
        private final String desc;

        Field(int access, String name, String desc) {
            this.access = access;
            this.name = name;
            this.desc = desc;
        }

        @Override
        public boolean equals(Object that) {
            if (that == null) return false;
            if (this == that) return true;
            if (!(that instanceof Field)) return false;
            Field field = (Field)that;
            return (access == field.access) && name.equals(field.name)
                    && desc.equals(field.desc);
        }

        @Override
        public int hashCode() {
            int result = 17;
            result = 37 * result + access;
            result = 37 * result + name.hashCode();
            result = 37 * result + desc.hashCode();
            return result;
        }
    }

    private static final class Method {
        private final int access;
        private final String name;
        private final String desc;
        private final Set<String> exceptions;

        Method(int access, String name, String desc, Set<String> exceptions) {
            this.access = access;
            this.name = name;
            this.desc = desc;
            this.exceptions = exceptions;
        }

        @Override
        public boolean equals(Object that) {
            if (that == null) return false;
            if (this == that) return true;
            if (!(that instanceof Method)) return false;
            Method method = (Method)that;
            return (access == method.access) && name.equals(method.name)
                    && desc.equals(method.desc)
                    && exceptions.equals(method.exceptions);
        }

        @Override
        public int hashCode() {
            int result = 17;
            result = 37 * result + access;
            result = 37 * result + name.hashCode();
            result = 37 * result + desc.hashCode();
            result = 37 * result + exceptions.hashCode();
            return result;
        }
    }

    private static final class ClassAttributes extends ClassVisitor {
        private String name;
        private String outerClassName;
        private String superName;
        private int version;
        private int access;
        private boolean publicClass;
        private boolean nestedClass;
        private final Set<Field> fields = new HashSet<>();
        private final Set<Method> methods = new HashSet<>();

        public ClassAttributes() {
            super(Opcodes.ASM6);
        }

        private boolean isPublic(int access) {
            return ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC)
                    || ((access & Opcodes.ACC_PROTECTED) == Opcodes.ACC_PROTECTED);
        }

        @Override
        public void visit(int version, int access, String name, String signature,
                          String superName, String[] interfaces) {
            this.version = version;
            this.access = access;
            this.name = name;
            this.nestedClass = name.contains("$");
            this.superName = superName;
            this.publicClass = isPublic(access);
        }

        @Override
        public void visitOuterClass(String owner, String name, String desc) {
            if (!this.nestedClass) return;
            this.outerClassName = owner;
        }

        @Override
        public void visitInnerClass(String name, String outerName, String innerName,
                                    int access) {
            if (!this.nestedClass) return;
            if (outerName == null) return;
            if (!this.name.equals(name)) return;
            if (this.outerClassName == null) this.outerClassName = outerName;
        }

        @Override
        public FieldVisitor visitField(int access, String name, String desc,
                                       String signature, Object value) {
            if (isPublic(access)) {
                fields.add(new Field(access, name, desc));
            }
            return null;
        }

        @Override
        public MethodVisitor visitMethod(int access, String name, String desc,
                                         String signature, String[] exceptions) {
            if (isPublic(access)) {
                Set<String> exceptionSet = new HashSet<>();
                if (exceptions != null) {
                    for (String e : exceptions) {
                        exceptionSet.add(e);
                    }
                }
                // treat type descriptor as a proxy for signature because signature
                // is usually null, need to strip off the return type though
                int n;
                if (desc != null && (n = desc.lastIndexOf(')')) != -1) {
                    desc = desc.substring(0, n + 1);
                    methods.add(new Method(access, name, desc, exceptionSet));
                }
            }
            return null;
        }

        @Override
        public void visitEnd() {
            this.nestedClass = this.outerClassName != null;
        }

        @Override
        public boolean equals(Object that) {
            if (that == null) return false;
            if (this == that) return true;
            if (!(that instanceof ClassAttributes)) return false;
            ClassAttributes clsAttrs = (ClassAttributes)that;
            boolean superNameOkay = superName != null
                    ? superName.equals(clsAttrs.superName) : true;
            return access == clsAttrs.access
                    && superNameOkay
                    && fields.equals(clsAttrs.fields)
                    && methods.equals(clsAttrs.methods);
        }

        @Override
        public int hashCode() {
            int result = 17;
            result = 37 * result + access;
            result = 37 * result + superName != null ? superName.hashCode() : 0;
            result = 37 * result + fields.hashCode();
            result = 37 * result + methods.hashCode();
            return result;
        }
    }
}

sun/tools/jar/FingerPrint.java

 

JDK 11 jdk.javadoc.jmod - Java Document Tool

JDK 11 jdk.internal.vm.compiler.management.jmod - Internal VM Compiler Management Module

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2020-07-22, 2922👍, 0💬