JDK 11 jdk.rmic.jmod - RMI Compiler Tool

JDK 11 jdk.rmic.jmod is the JMOD file for JDK 11 RMI (Remote Method Invocation) Compiler Tool tool, which can be invoked by the "rmic" command.

JDK 11 RMI Compiler Tool tool compiled class files are stored in \fyicenter\jdk-11.0.1\jmods\jdk.rmic.jmod.

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

JDK 11 RMI Compiler Tool tool source code files are stored in \fyicenter\jdk-11.0.1\lib\src.zip\jdk.rmic.

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

✍: FYIcenter

sun/tools/java/Environment.java

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

package sun.tools.java;

import java.util.Stack;
import java.io.IOException;
import sun.tools.tree.Context;
//JCOV
import java.io.File;
//end JCOV

/**
 * This class defines the environment for a compilation.
 * It is used to load classes, resolve class names and
 * report errors. It is an abstract class, a subclass
 * must define implementations for some of the functions.<p>
 *
 * An environment has a source object associated with it.
 * This is the thing against which errors are reported, it
 * is usually a file name, a field or a class.<p>
 *
 * Environments can be nested to change the source object.<p>
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @author      Arthur van Hoff
 */

public class Environment implements Constants {
    /**
     * The actual environment to which everything is forwarded.
     */
    Environment env;

    /**
     * External character encoding name
     */
    String encoding;

    /**
     * The object that is currently being parsed/compiled.
     * It is either a file name (String) or a field (MemberDefinition)
     * or a class (ClassDeclaration or ClassDefinition).
     */
    Object source;

    public Environment(Environment env, Object source) {
        if (env != null && env.env != null && env.getClass() == this.getClass())
            env = env.env;      // a small optimization
        this.env = env;
        this.source = source;
    }
    public Environment() {
        this(null, null);
    }

    /**
     * Tells whether an Identifier refers to a package which should be
     * exempt from the "exists" check in Imports#resolve().
     */
    public boolean isExemptPackage(Identifier id) {
        return env.isExemptPackage(id);
    }

    /**
     * Return a class declaration given a fully qualified class name.
     */
    public ClassDeclaration getClassDeclaration(Identifier nm) {
        return env.getClassDeclaration(nm);
    }

    /**
     * Return a class definition given a fully qualified class name.
     * <p>
     * Should be called only with 'internal' class names, i.e., the result
     * of a call to 'resolveName' or a synthetic class name.
     */
    public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound {
        if (nm.isInner()) {
            ClassDefinition c = getClassDefinition(nm.getTopName());
            Identifier tail = nm.getFlatName();
        walkTail:
            while (tail.isQualified()) {
                tail = tail.getTail();
                Identifier head = tail.getHead();
                //System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
                String hname = head.toString();
                // If the name is of the form 'ClassName.N$localName', where N is
                // a number, the field 'N$localName' may not necessarily be a member
                // of the class named by 'ClassName', but might be a member of some
                // inaccessible class contained within it.  We use 'getLocalClass'
                // to do the lookup in this case.  This is part of a fix for bugid
                // 4054523 and 4030421.  See also 'BatchEnvironment.makeClassDefinition'.
                // This should also work for anonymous class names of the form
                // 'ClassName.N'.  Note that the '.' qualifications get converted to
                // '$' characters when determining the external name of the class and
                // the name of the class file.
                if (hname.length() > 0
                    && Character.isDigit(hname.charAt(0))) {
                    ClassDefinition localClass = c.getLocalClass(hname);
                    if (localClass != null) {
                        c = localClass;
                        continue walkTail;
                    }
                } else {
                    for (MemberDefinition f = c.getFirstMatch(head);
                         f != null; f = f.getNextMatch()) {
                        if (f.isInnerClass()) {
                            c = f.getInnerClass();
                            continue walkTail;
                        }
                    }
                }
                throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
            }
            //System.out.println("FOUND " + c + " FOR " + nm);
            return c;
        }
        return getClassDeclaration(nm).getClassDefinition(this);
    }


    /**
     * Return a class declaration given a type. Only works for
     * class types.
     */
    public ClassDeclaration getClassDeclaration(Type t) {
        return getClassDeclaration(t.getClassName());
    }

    /**
     * Return a class definition given a type. Only works for
     * class types.
     */
    public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound {
        return getClassDefinition(t.getClassName());
    }

    /**
     * Check if a class exists (without actually loading it).
     * (Since inner classes cannot in general be examined without
     * loading source, this method does not accept inner names.)
     */
    public boolean classExists(Identifier nm) {
        return env.classExists(nm);
    }

    public final boolean classExists(Type t) {
        return !t.isType(TC_CLASS) || classExists(t.getClassName());
    }

    /**
     * Get the package path for a package
     */
    public Package getPackage(Identifier pkg) throws IOException {
        return env.getPackage(pkg);
    }

    /**
     * Load the definition of a class.
     */
    public void loadDefinition(ClassDeclaration c) {
        env.loadDefinition(c);
    }

    /**
     * Return the source of the environment (ie: the thing being compiled/parsed).
     */
    public final Object getSource() {
        return source;
    }

    /**
     * Resolve a type. Make sure that all the classes referred to by
     * the type have a definition.  Report errors.  Return true if
     * the type is well-formed.  Presently used for types appearing
     * in member declarations, which represent named types internally as
     * qualified identifiers.  Type names appearing in local variable
     * declarations and within expressions are represented as identifier
     * or field expressions, and are resolved by 'toType', which delegates
     * handling of the non-inner portion of the name to this method.
     * <p>
     * In 'toType', the various stages of qualification are represented by
     * separate AST nodes.  Here, we are given a single identifier which
     * contains the entire qualification structure.  It is not possible in
     * general to set the error location to the exact position of a component
     * that is in error, so an error message must refer to the entire qualified
     * name.  An attempt to keep track of the string length of the components of
     * the name and to offset the location accordingly fails because the initial
     * prefix of the name may have been rewritten by an earlier call to
     * 'resolveName'.  See 'SourceMember.resolveTypeStructure'.  The situation
     * is actually even worse than this, because only a single location is
     * passed in for an entire declaration, which may contain many type names.
     * All error messages are thus poorly localized.  These checks should be
     * done while traversing the parse tree for the type, not the type descriptor.
     * <p>
     * DESIGN NOTE:
     * As far as I can tell, the two-stage resolution of names represented in
     * string form is an artifact of the late implementation of inner classes
     * and the use of mangled names internally within the compiler.  All
     * qualified names should have their hiearchical structure made explicit
     * in the parse tree at the phase at which they are presented for static
     * semantic checking.  This would affect class names appearing in 'extends',
     * 'implements', and 'throws' clauses, as well as in member declarations.
     */
    public boolean resolve(long where, ClassDefinition c, Type t) {
        switch (t.getTypeCode()) {
          case TC_CLASS: {
            ClassDefinition def;
            try {
                Identifier nm = t.getClassName();
                if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
                    resolve(nm);        // elicit complaints about ambiguity
                }
                def = getQualifiedClassDefinition(where, nm, c, false);
                if (!c.canAccess(this, def.getClassDeclaration())) {
                    // Reported error location may be imprecise
                    // if the name is qualified.
                    error(where, "cant.access.class", def);
                    return true; // return false later
                }
                def.noteUsedBy(c, where, env);
            } catch (AmbiguousClass ee) {
                error(where, "ambig.class", ee.name1, ee.name2);
                return false;
            } catch (ClassNotFound e) {
                // For now, report "class.and.package" only when the code
                // is going to fail anyway.
                try {
                    if (e.name.isInner() &&
                            getPackage(e.name.getTopName()).exists()) {
                        env.error(where, "class.and.package",
                                  e.name.getTopName());
                    }
                } catch (IOException ee) {
                    env.error(where, "io.exception", "package check");
                }
                // This error message is also emitted for 'new' expressions.
                // error(where, "class.not.found", e.name, "declaration");
                error(where, "class.not.found.no.context", e.name);
                return false;
            }
            return true;
          }

          case TC_ARRAY:
            return resolve(where, c, t.getElementType());

          case TC_METHOD:
            boolean ok = resolve(where, c, t.getReturnType());
            Type args[] = t.getArgumentTypes();
            for (int i = args.length ; i-- > 0 ; ) {
                ok &= resolve(where, c, args[i]);
            }
            return ok;
        }
        return true;
    }

    /**
     * Given its fully-qualified name, verify that a class is defined and accessible.
     * Used to check components of qualified names in contexts where a class is expected.
     * Like 'resolve', but is given a single type name, not a type descriptor.
     */
    public boolean resolveByName(long where, ClassDefinition c, Identifier nm) {
        return resolveByName(where, c, nm, false);
    }

    public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) {
        return resolveByName(where, c, nm, true);
    }

    private boolean resolveByName(long where, ClassDefinition c,
                                 Identifier nm, boolean isExtends) {
        ClassDefinition def;
        try {
            if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
                resolve(nm);    // elicit complaints about ambiguity
            }
            def = getQualifiedClassDefinition(where, nm, c, isExtends);
            ClassDeclaration decl = def.getClassDeclaration();
            if (!((!isExtends && c.canAccess(this, decl))
                  ||
                  (isExtends && c.extendsCanAccess(this, decl)))) {
                error(where, "cant.access.class", def);
                return true; // return false later
            }
        } catch (AmbiguousClass ee) {
            error(where, "ambig.class", ee.name1, ee.name2);
            return false;
        } catch (ClassNotFound e) {
            // For now, report "class.and.package" only when the code
            // is going to fail anyway.
            try {
                if (e.name.isInner() &&
                    getPackage(e.name.getTopName()).exists()) {
                    env.error(where, "class.and.package",
                              e.name.getTopName());
                }
            } catch (IOException ee) {
                env.error(where, "io.exception", "package check");
            }
            error(where, "class.not.found", e.name, "type name");
            return false;
        }
        return true;
    }

    /**
     * Like 'getClassDefinition(env)', but check access on each component.
     * Currently called only by 'resolve' above.  It is doubtful that calls
     * to 'getClassDefinition(env)' are appropriate now.
     */
    public final ClassDefinition
    getQualifiedClassDefinition(long where,
                                Identifier nm,
                                ClassDefinition ctxClass,
                                boolean isExtends) throws ClassNotFound {
        if (nm.isInner()) {
            ClassDefinition c = getClassDefinition(nm.getTopName());
            Identifier tail = nm.getFlatName();
        walkTail:
            while (tail.isQualified()) {
                tail = tail.getTail();
                Identifier head = tail.getHead();
                // System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
                String hname = head.toString();
                // Handle synthesized names of local and anonymous classes.
                // See 'getClassDefinition(env)' above.
                if (hname.length() > 0
                    && Character.isDigit(hname.charAt(0))) {
                    ClassDefinition localClass = c.getLocalClass(hname);
                    if (localClass != null) {
                        c = localClass;
                        continue walkTail;
                    }
                } else {
                    for (MemberDefinition f = c.getFirstMatch(head);
                         f != null; f = f.getNextMatch()) {
                        if (f.isInnerClass()) {
                            ClassDeclaration rdecl = c.getClassDeclaration();
                            c = f.getInnerClass();
                            ClassDeclaration fdecl = c.getClassDeclaration();
                            // This check is presumably applicable even if the
                            // original source-code name (expanded by 'resolveNames')
                            // was a simple, unqualified name.  Hopefully, JLS 2e
                            // will clarify the matter.
                            if ((!isExtends
                                 && !ctxClass.canAccess(env, fdecl))
                                ||
                                (isExtends
                                 && !ctxClass.extendsCanAccess(env, fdecl))) {
                                // Reported error location is imprecise.
                                env.error(where, "no.type.access", head, rdecl, ctxClass);
                            }
                            // The JLS 6.6.2 restrictions on access to protected members
                            // depend in an essential way upon the syntactic form of the name.
                            // Since the compiler has previously expanded the class names
                            // here into fully-qualified form ('resolveNames'), this check
                            // cannot be performed here.  Unfortunately, the original names
                            // are clobbered during 'basicCheck', which is also the phase that
                            // resolves the inheritance structure, required to implement the
                            // access restrictions.  Pending a large-scale revision of the
                            // name-resolution machinery, we forgo this check, with the result
                            // that the JLS 6.6.2 restrictions are not enforced for some cases
                            // of qualified access to inner classes.  Some qualified names are
                            // resolved elsewhere via a different mechanism, and will be
                            // treated correctly -- see 'FieldExpression.checkCommon'.
                            /*---------------------------------------*
                            if (f.isProtected()) {
                                Type rty = Type.tClass(rdecl.getName()); // hack
                                if (!ctxClass.protectedAccess(env, f, rty)) {
                                    // Reported error location is imprecise.
                                    env.error(where, "invalid.protected.type.use",
                                              head, ctxClass, rty);
                                }
                            }
                            *---------------------------------------*/
                            continue walkTail;
                        }
                    }
                }
                throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
            }
            //System.out.println("FOUND " + c + " FOR " + nm);
            return c;
        }
        return getClassDeclaration(nm).getClassDefinition(this);
    }

    /**
     * Resolve the names within a type, returning the adjusted type.
     * Adjust class names to reflect scoping.
     * Do not report errors.
     * <p>
     * NOTE: It would be convenient to check for errors here, such as
     * verifying that each component of a qualified name exists and is
     * accessible.  Why must this be done in a separate phase?
     * <p>
     * If the 'synth' argument is true, indicating that the member whose
     * type is being resolved is synthetic, names are resolved with respect
     * to the package scope.  (Fix for 4097882)
     */
    public Type resolveNames(ClassDefinition c, Type t, boolean synth) {
        if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t);
        switch (t.getTypeCode()) {
          case TC_CLASS: {
            Identifier name = t.getClassName();
            Identifier rname;
            if (synth) {
                rname = resolvePackageQualifiedName(name);
            } else {
                rname = c.resolveName(this, name);
            }
            if (name != rname) {
                t = Type.tClass(rname);
            }
            break;
          }

          case TC_ARRAY:
            t = Type.tArray(resolveNames(c, t.getElementType(), synth));
            break;

          case TC_METHOD: {
            Type ret = t.getReturnType();
            Type rret = resolveNames(c, ret, synth);
            Type args[] = t.getArgumentTypes();
            Type rargs[] = new Type[args.length];
            boolean changed = (ret != rret);
            for (int i = args.length ; i-- > 0 ; ) {
                Type arg = args[i];
                Type rarg = resolveNames(c, arg, synth);
                rargs[i] = rarg;
                if (arg != rarg) {
                    changed = true;
                }
            }
            if (changed) {
                t = Type.tMethod(rret, rargs);
            }
            break;
          }
        }
        return t;
    }

    /**
     * Resolve a class name, using only package and import directives.
     * Report no errors.
     * <p>
     */
    public Identifier resolveName(Identifier name) {
        // This logic is pretty exactly parallel to that of
        // ClassDefinition.resolveName().
        if (name.isQualified()) {
            // Try to resolve the first identifier component,
            // because inner class names take precedence over
            // package prefixes.  (Cf. ClassDefinition.resolveName.)
            Identifier rhead = resolveName(name.getHead());

            if (rhead.hasAmbigPrefix()) {
                // The first identifier component refers to an
                // ambiguous class.  Limp on.  We throw away the
                // rest of the classname as it is irrelevant.
                // (part of solution for 4059855).
                return rhead;
            }

            if (!this.classExists(rhead)) {
                return this.resolvePackageQualifiedName(name);
            }
            try {
                return this.getClassDefinition(rhead).
                    resolveInnerClass(this, name.getTail());
            } catch (ClassNotFound ee) {
                // return partially-resolved name someone else can fail on
                return Identifier.lookupInner(rhead, name.getTail());
            }
        }
        try {
            return resolve(name);
        } catch (AmbiguousClass ee) {
            // Don't force a resolution of the name if it is ambiguous.
            // Forcing the resolution would tack the current package
            // name onto the front of the class, which would be wrong.
            // Instead, mark the name as ambiguous and let a later stage
            // find the error by calling env.resolve(name).
            // (part of solution for 4059855).

            if (name.hasAmbigPrefix()) {
                return name;
            } else {
                return name.addAmbigPrefix();
            }
        } catch (ClassNotFound ee) {
            // last chance to make something halfway sensible
            Imports imports = getImports();
            if (imports != null)
                return imports.forceResolve(this, name);
        }
        return name;
    }

    /**
     * Discover if name consists of a package prefix, followed by the
     * name of a class (that actually exists), followed possibly by
     * some inner class names.  If we can't find a class that exists,
     * return the name unchanged.
     * <p>
     * This routine is used after a class name fails to
     * be resolved by means of imports or inner classes.
     * However, import processing uses this routine directly,
     * since import names must be exactly qualified to start with.
     */
    public final Identifier resolvePackageQualifiedName(Identifier name) {
        Identifier tail = null;
        for (;;) {
            if (classExists(name)) {
                break;
            }
            if (!name.isQualified()) {
                name = (tail == null) ? name : Identifier.lookup(name, tail);
                tail = null;
                break;
            }
            Identifier nm = name.getName();
            tail = (tail == null)? nm: Identifier.lookup(nm, tail);
            name = name.getQualifier();
        }
        if (tail != null)
            name = Identifier.lookupInner(name, tail);
        return name;
    }

    /**
     * Resolve a class name, using only package and import directives.
     */
    public Identifier resolve(Identifier nm) throws ClassNotFound {
        if (env == null)  return nm;    // a pretty useless no-op
        return env.resolve(nm);
    }

    /**
     * Get the imports used to resolve class names.
     */
    public Imports getImports() {
        if (env == null)  return null; // lame default
        return env.getImports();
    }

    /**
     * Create a new class.
     */
    public ClassDefinition makeClassDefinition(Environment origEnv, long where,
                                               IdentifierToken name,
                                               String doc, int modifiers,
                                               IdentifierToken superClass,
                                               IdentifierToken interfaces[],
                                               ClassDefinition outerClass) {
        if (env == null)  return null; // lame default
        return env.makeClassDefinition(origEnv, where, name,
                                       doc, modifiers,
                                       superClass, interfaces, outerClass);
    }

    /**
     * Create a new field.
     */
    public MemberDefinition makeMemberDefinition(Environment origEnv, long where,
                                               ClassDefinition clazz,
                                               String doc, int modifiers,
                                               Type type, Identifier name,
                                               IdentifierToken argNames[],
                                               IdentifierToken expIds[],
                                               Object value) {
        if (env == null)  return null; // lame default
        return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers,
                                       type, name, argNames, expIds, value);
    }

    /**
     * Returns true if the given method is applicable to the given arguments
     */

    public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound {
        Type mType = m.getType();
        if (!mType.isType(TC_METHOD))
            return false;
        Type mArgs[] = mType.getArgumentTypes();
        if (args.length != mArgs.length)
            return false;
        for (int i = args.length ; --i >= 0 ;)
            if (!isMoreSpecific(args[i], mArgs[i]))
                return false;
        return true;
    }


    /**
     * Returns true if "best" is in every argument at least as good as "other"
     */
    public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other)
           throws ClassNotFound {
        Type bestType = best.getClassDeclaration().getType();
        Type otherType = other.getClassDeclaration().getType();
        boolean result = isMoreSpecific(bestType, otherType)
                      && isApplicable(other, best.getType().getArgumentTypes());
        // System.out.println("isMoreSpecific: " + best + "/" + other
        //                      + " => " + result);
        return result;
    }

    /**
     * Returns true if "from" is a more specific type than "to"
     */

    public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound {
        return implicitCast(from, to);
    }

    /**
     * Return true if an implicit cast from this type to
     * the given type is allowed.
     */
    @SuppressWarnings("fallthrough")
    public boolean implicitCast(Type from, Type to) throws ClassNotFound {
        if (from == to)
            return true;

        int toTypeCode = to.getTypeCode();

        switch(from.getTypeCode()) {
        case TC_BYTE:
            if (toTypeCode == TC_SHORT)
                return true;
        case TC_SHORT:
        case TC_CHAR:
            if (toTypeCode == TC_INT) return true;
        case TC_INT:
            if (toTypeCode == TC_LONG) return true;
        case TC_LONG:
            if (toTypeCode == TC_FLOAT) return true;
        case TC_FLOAT:
            if (toTypeCode == TC_DOUBLE) return true;
        case TC_DOUBLE:
        default:
            return false;

        case TC_NULL:
            return to.inMask(TM_REFERENCE);

        case TC_ARRAY:
            if (!to.isType(TC_ARRAY)) {
                return (to == Type.tObject || to == Type.tCloneable
                           || to == Type.tSerializable);
            } else {
                // both are arrays.  recurse down both until one isn't an array
                do {
                    from = from.getElementType();
                    to = to.getElementType();
                } while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY));
                if (  from.inMask(TM_ARRAY|TM_CLASS)
                      && to.inMask(TM_ARRAY|TM_CLASS)) {
                    return isMoreSpecific(from, to);
                } else {
                    return (from.getTypeCode() == to.getTypeCode());
                }
            }

        case TC_CLASS:
            if (toTypeCode == TC_CLASS) {
                ClassDefinition fromDef = getClassDefinition(from);
                ClassDefinition toDef = getClassDefinition(to);
                return toDef.implementedBy(this,
                                           fromDef.getClassDeclaration());
            } else {
                return false;
            }
        }
    }


    /**
     * Return true if an explicit cast from this type to
     * the given type is allowed.
     */
    public boolean explicitCast(Type from, Type to) throws ClassNotFound {
        if (implicitCast(from, to)) {
            return true;
        }
        if (from.inMask(TM_NUMBER)) {
            return to.inMask(TM_NUMBER);
        }
        if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) {
            ClassDefinition fromClass = getClassDefinition(from);
            ClassDefinition toClass = getClassDefinition(to);
            if (toClass.isFinal()) {
                return fromClass.implementedBy(this,
                                               toClass.getClassDeclaration());
            }
            if (fromClass.isFinal()) {
                return toClass.implementedBy(this,
                                             fromClass.getClassDeclaration());
            }

            // The code here used to omit this case.  If both types
            // involved in a cast are interfaces, then JLS 5.5 requires
            // that we do a simple test -- make sure none of the methods
            // in toClass and fromClass have the same signature but
            // different return types.  (bug number 4028359)
            if (toClass.isInterface() && fromClass.isInterface()) {
                return toClass.couldImplement(fromClass);
            }

            return toClass.isInterface() ||
                   fromClass.isInterface() ||
                   fromClass.superClassOf(this, toClass.getClassDeclaration());
        }
        if (to.isType(TC_ARRAY)) {
            if (from.isType(TC_ARRAY))  {
                Type t1 = from.getElementType();
                Type t2 = to.getElementType();
                while ((t1.getTypeCode() == TC_ARRAY)
                       && (t2.getTypeCode() == TC_ARRAY)) {
                    t1 = t1.getElementType();
                    t2 = t2.getElementType();
                }
                if (t1.inMask(TM_ARRAY|TM_CLASS) &&
                    t2.inMask(TM_ARRAY|TM_CLASS)) {
                    return explicitCast(t1, t2);
                }
            } else if (from == Type.tObject || from == Type.tCloneable
                          || from == Type.tSerializable)
                return true;
        }
        return false;
    }

    /**
     * Flags.
     */
    public int getFlags() {
        return env.getFlags();
    }

    /**
     * Debugging flags.  There used to be a method debug()
     * that has been replaced because -g has changed meaning
     * (it now cooperates with -O and line number, variable
     * range and source file info can be toggled separately).
     */
    public final boolean debug_lines() {
        return (getFlags() & F_DEBUG_LINES) != 0;
    }
    public final boolean debug_vars() {
        return (getFlags() & F_DEBUG_VARS) != 0;
    }
    public final boolean debug_source() {
        return (getFlags() & F_DEBUG_SOURCE) != 0;
    }

    /**
     * Optimization flags.  There used to be a method optimize()
     * that has been replaced because -O has changed meaning in
     * javac to be replaced with -O and -O:interclass.
     */
    public final boolean opt() {
        return (getFlags() & F_OPT) != 0;
    }
    public final boolean opt_interclass() {
        return (getFlags() & F_OPT_INTERCLASS) != 0;
    }

    /**
     * Verbose
     */
    public final boolean verbose() {
        return (getFlags() & F_VERBOSE) != 0;
    }

    /**
     * Dump debugging stuff
     */
    public final boolean dump() {
        return (getFlags() & F_DUMP) != 0;
    }

    /**
     * Verbose
     */
    public final boolean warnings() {
        return (getFlags() & F_WARNINGS) != 0;
    }

    /**
     * Dependencies
     */
    public final boolean dependencies() {
        return (getFlags() & F_DEPENDENCIES) != 0;
    }

    /**
     * Print Dependencies to stdout
     */
    public final boolean print_dependencies() {
        return (getFlags() & F_PRINT_DEPENDENCIES) != 0;
    }

    /**
     * Deprecation warnings are enabled.
     */
    public final boolean deprecation() {
        return (getFlags() & F_DEPRECATION) != 0;
    }

    /**
     * Do not support virtual machines before version 1.2.
     * This option is not supported and is only here for testing purposes.
     */
    public final boolean version12() {
        return (getFlags() & F_VERSION12) != 0;
    }

    /**
     * Floating point is strict by default
     */
    public final boolean strictdefault() {
        return (getFlags() & F_STRICTDEFAULT) != 0;
    }

    /**
     * Release resources, if any.
     */
    public void shutdown() {
        if (env != null) {
            env.shutdown();
        }
    }

    /**
     * Issue an error.
     *  source   - the input source, usually a file name string
     *  offset   - the offset in the source of the error
     *  err      - the error number (as defined in this interface)
     *  arg1     - an optional argument to the error (null if not applicable)
     *  arg2     - a second optional argument to the error (null if not applicable)
     *  arg3     - a third optional argument to the error (null if not applicable)
     */
    public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) {
        env.error(source, where, err, arg1, arg2, arg3);
    }
    public final void error(long where, String err, Object arg1, Object arg2, Object arg3) {
        error(source, where, err, arg1, arg2, arg3);
    }
    public final void error(long where, String err, Object arg1, Object arg2) {
        error(source, where, err, arg1, arg2, null);
    }
    public final void error(long where, String err, Object arg1) {
        error(source, where, err, arg1, null, null);
    }
    public final void error(long where, String err) {
        error(source, where, err, null, null, null);
    }

    /**
     * Output a string. This can either be an error message or something
     * for debugging. This should be used instead of println.
     */
    public void output(String msg) {
        env.output(msg);
    }

    private static boolean debugging = (System.getProperty("javac.debug") != null);

    public static void debugOutput(Object msg) {
        if (Environment.debugging)
            System.out.println(msg.toString());
    }

    /**
     * set character encoding name
     */
    public void setCharacterEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * Return character encoding name
     */
    public String getCharacterEncoding() {
        return encoding;
    }

    /**
     * Return major version to use in generated class files.
     */
    public short getMajorVersion() {
        if (env==null) return JAVA_DEFAULT_VERSION;  // needed for javah
        return env.getMajorVersion();
    }

    /**
     * Return minor version to use in generated class files.
     */
    public short getMinorVersion() {
        if (env==null) return JAVA_DEFAULT_MINOR_VERSION;  // needed for javah
        return env.getMinorVersion();
    }

// JCOV
    /**
     *  get coverage flag
     */
    public final boolean coverage() {
        return (getFlags() & F_COVERAGE) != 0;
    }

    /**
     *  get flag of generation the coverage data file
     */
    public final boolean covdata() {
        return (getFlags() & F_COVDATA) != 0;
    }

    /**
     * Return the coverage data file
     */
    public File getcovFile() {
        return env.getcovFile();
    }

// end JCOV

    /**
     * Debug tracing.
     * Currently, this code is used only for tracing the loading and
     * checking of classes, particularly the demand-driven aspects.
     * This code should probably be integrated with 'debugOutput' above,
     * but we need to give more thought to the issue of classifying debugging
     * messages and allowing those only those of interest to be enabled.
     *
     * Calls to these methods are generally conditioned on the final variable
     * 'Constants.tracing', which allows the calls to be completely omitted
     * in a production release to avoid space and time overhead.
     */

    private static boolean dependtrace =
                (System.getProperty("javac.trace.depend") != null);

    public void dtEnter(String s) {
        if (dependtrace) System.out.println(">>> " + s);
    }

    public void dtExit(String s) {
        if (dependtrace) System.out.println("<<< " + s);
    }

    public void dtEvent(String s) {
        if (dependtrace) System.out.println(s);
    }

    /**
     * Enable diagnostic dump of class modifier bits, including those
     * in InnerClasses attributes, as they are written to the classfile.
     * In the future, may also enable dumping field and method modifiers.
     */

    private static boolean dumpmodifiers =
                (System.getProperty("javac.dump.modifiers") != null);

    public boolean dumpModifiers() { return dumpmodifiers; }

}

sun/tools/java/Environment.java

 

JDK 11 jdk.scripting.nashorn.jmod - Scripting Nashorn Module

JDK 11 jdk.pack.jmod - Pack Module

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2018-11-09, 5811👍, 0💬