JDK 11 jdk.jshell.jmod - JShell Tool

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

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

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

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

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

✍: FYIcenter

jdk/jshell/Unit.java

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

package jdk.jshell;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
import jdk.jshell.ClassTracker.ClassInfo;
import jdk.jshell.Snippet.Kind;
import jdk.jshell.Snippet.Status;
import jdk.jshell.Snippet.SubKind;
import jdk.jshell.TaskFactory.AnalyzeTask;
import jdk.jshell.TaskFactory.CompileTask;
import jdk.jshell.spi.ExecutionControl.ClassBytecodes;
import jdk.jshell.spi.ExecutionControl.ClassInstallException;
import jdk.jshell.spi.ExecutionControl.EngineTerminationException;
import jdk.jshell.spi.ExecutionControl.NotImplementedException;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_EVNT;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_GEN;
import static jdk.internal.jshell.debug.InternalDebugControl.DBG_WRAP;
import static jdk.jshell.Snippet.Status.OVERWRITTEN;
import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED;
import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED;
import static jdk.jshell.Snippet.Status.REJECTED;
import static jdk.jshell.Snippet.Status.VALID;
import static jdk.jshell.Util.PARSED_LOCALE;
import static jdk.jshell.Util.expunge;

/**
 * Tracks the compilation and load of a new or updated snippet.
 * @author Robert Field
 */
final class Unit {

    private final JShell state;
    private final Snippet si;
    private final Snippet siOld;
    private final boolean isDependency;
    private final boolean isNew;
    private final Snippet causalSnippet;
    private final DiagList generatedDiagnostics;

    private int seq;
    private String classNameInitial;
    private Wrap activeGuts;
    private Status status;
    private Status prevStatus;
    private boolean signatureChanged;
    private DiagList compilationDiagnostics;
    private DiagList recompilationDiagnostics = null;
    private List<String> unresolved;
    private SnippetEvent replaceOldEvent;
    private List<SnippetEvent> secondaryEvents;
    private boolean isAttemptingCorral;
    private List<ClassInfo> toRedefine;
    private boolean dependenciesNeeded;

    Unit(JShell state, Snippet si, Snippet causalSnippet,
            DiagList generatedDiagnostics) {
        this.state = state;
        this.si = si;
        this.isDependency = causalSnippet != null;
        this.siOld = isDependency
                ? si
                : state.maps.getSnippet(si.key());
        this.isNew = siOld == null;
        this.causalSnippet = causalSnippet;
        this.generatedDiagnostics = generatedDiagnostics;

        this.seq = isNew? 0 : siOld.sequenceNumber();
        this.classNameInitial = isNew? "<none>" : siOld.className();
        this.prevStatus = (isNew || isDependency)
                ? si.status()
                : siOld.status();
        si.setSequenceNumber(seq);
    }

    // Drop entry
    Unit(JShell state, Snippet si) {
        this.state = state;
        this.si = si;
        this.siOld = null;
        this.isDependency = false;
        this.isNew = false;
        this.causalSnippet = null;
        this.generatedDiagnostics = new DiagList();
        this.prevStatus = si.status();
        si.setDropped();
        this.status = si.status();
    }

    @Override
    public int hashCode() {
        return si.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        return (o instanceof Unit)
                ? si.equals(((Unit) o).si)
                : false;
    }

    Snippet snippet() {
        return si;
    }

    boolean isDependency() {
        return isDependency;
    }

    void initialize() {
        isAttemptingCorral = false;
        dependenciesNeeded = false;
        toRedefine = null; // assure NPE if classToLoad not called
        activeGuts = si.guts();
        markOldDeclarationOverwritten();
    }

    // Set the outer wrap of our Snippet
    void setWrap(Collection<Unit> exceptUnit, Collection<Unit> plusUnfiltered) {
        if (isImport()) {
            si.setOuterWrap(state.outerMap.wrapImport(activeGuts, si));
        } else {
            // Collect Units for be wrapped together.  Just this except for overloaded methods
            List<Unit> units;
            if (snippet().kind() == Kind.METHOD) {
                String name = ((MethodSnippet) snippet()).name();
                units = plusUnfiltered.stream()
                        .filter(u -> u.snippet().kind() == Kind.METHOD &&
                                 ((MethodSnippet) u.snippet()).name().equals(name))
                        .collect(toList());
            } else {
                units = Collections.singletonList(this);
            }
            // Keys to exclude from imports
            Set<Key> except = exceptUnit.stream()
                    .map(u -> u.snippet().key())
                    .collect(toSet());
            // Snippets to add to imports
            Collection<Snippet> plus = plusUnfiltered.stream()
                    .filter(u -> !units.contains(u))
                    .map(Unit::snippet)
                    .collect(toList());
            // Snippets to wrap in an outer
            List<Snippet> snippets = units.stream()
                    .map(Unit::snippet)
                    .collect(toList());
            // Snippet wraps to wrap in an outer
            List<Wrap> wraps = units.stream()
                    .map(u -> u.activeGuts)
                    .collect(toList());
            // Set the outer wrap for this snippet
            si.setOuterWrap(state.outerMap.wrapInClass(except, plus, snippets, wraps));
            state.debug(DBG_WRAP, "++setWrap() %s\n%s\n",
                    si, si.outerWrap().wrapped());
        }
    }

    void setDiagnostics(AnalyzeTask ct) {
        setDiagnostics(ct.getDiagnostics().ofUnit(this));
    }

    void setDiagnostics(DiagList diags) {
        compilationDiagnostics = diags;
        UnresolvedExtractor ue = new UnresolvedExtractor(diags);
        unresolved = ue.unresolved();
        state.debug(DBG_GEN, "++setCompilationInfo() %s\n%s\n-- diags: %s\n",
                si, si.outerWrap().wrapped(), diags);
    }

    private boolean isRecoverable() {
        // Unit failed, use corralling if it is defined on this Snippet,
        // and either all the errors are resolution errors or this is a
        // redeclare of an existing method
        return compilationDiagnostics.hasErrors()
                && si instanceof DeclarationSnippet
                && (isDependency()
                    || (si.subKind() != SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND
                        && compilationDiagnostics.hasResolutionErrorsAndNoOthers()));
    }

    /**
     * If it meets the conditions for corralling, install the corralled wrap
     * @return true is the corralled wrap was installed
     */
    boolean corralIfNeeded(Collection<Unit> working) {
        if (isRecoverable()
                && si.corralled() != null) {
            activeGuts = si.corralled();
            setWrap(working, working);
            return isAttemptingCorral = true;
        }
        return isAttemptingCorral = false;
    }

    void setCorralledDiagnostics(AnalyzeTask cct) {
        // set corralled diagnostics, but don't reset unresolved
        recompilationDiagnostics = cct.getDiagnostics().ofUnit(this);
        state.debug(DBG_GEN, "++recomp %s\n%s\n-- diags: %s\n",
                si, si.outerWrap().wrapped(), recompilationDiagnostics);
    }

    boolean smashingErrorDiagnostics(CompileTask ct) {
        if (isDefined()) {
            // set corralled diagnostics, but don't reset unresolved
            DiagList dl = ct.getDiagnostics().ofUnit(this);
            if (dl.hasErrors()) {
                setDiagnostics(dl);
                status = RECOVERABLE_NOT_DEFINED;
                // overwrite orginal bytes
                state.debug(DBG_GEN, "++smashingErrorDiagnostics %s\n%s\n-- diags: %s\n",
                        si, si.outerWrap().wrapped(), dl);
                return true;
            }
        }
        return false;
    }

    void setStatus(AnalyzeTask at) {
        if (!compilationDiagnostics.hasErrors()) {
            status = VALID;
        } else if (isRecoverable()) {
            if (isAttemptingCorral && !recompilationDiagnostics.hasErrors()) {
                status = RECOVERABLE_DEFINED;
            } else {
                status = RECOVERABLE_NOT_DEFINED;
            }
        } else {
            status = REJECTED;
        }
        checkForOverwrite(at);

        state.debug(DBG_GEN, "setStatus() %s - status: %s\n",
                si, status);
    }

    boolean isDefined() {
        return status.isDefined();
    }

    /**
     * Process the class information from the last compile. Requires loading of
     * returned list.
     *
     * @return the list of classes to load
     */
    Stream<ClassBytecodes> classesToLoad(List<String> classnames) {
        toRedefine = new ArrayList<>();
        List<ClassBytecodes> toLoad = new ArrayList<>();
        if (status.isDefined() && !isImport()) {
            // Classes should only be loaded/redefined if the compile left them
            // in a defined state.  Imports do not have code and are not loaded.
            for (String cn : classnames) {
                ClassInfo ci = state.classTracker.get(cn);
                if (ci.isLoaded()) {
                    if (ci.isCurrent()) {
                        // nothing to do
                    } else {
                        toRedefine.add(ci);
                    }
                } else {
                    // If not loaded, add to the list of classes to load.
                    toLoad.add(ci.toClassBytecodes());
                    dependenciesNeeded = true;
                }
            }
        }
        return toLoad.stream();
    }

    /**
     * Redefine classes needing redefine. classesToLoad() must be called first.
     *
     * @return true if all redefines succeeded (can be vacuously true)
     */
    boolean doRedefines() {
        if (toRedefine.isEmpty()) {
            return true;
        }
        ClassBytecodes[] cbcs = toRedefine.stream()
                .map(ClassInfo::toClassBytecodes)
                .toArray(ClassBytecodes[]::new);
        try {
            state.executionControl().redefine(cbcs);
            state.classTracker.markLoaded(cbcs);
            return true;
        } catch (ClassInstallException ex) {
            state.classTracker.markLoaded(cbcs, ex.installed());
            return false;
        } catch (EngineTerminationException ex) {
            state.closeDown();
            return false;
        } catch (NotImplementedException ex) {
            return false;
        }
    }

    void markForReplacement() {
        // increment for replace class wrapper
        si.setSequenceNumber(++seq);
    }

    private boolean isImport() {
        return si.kind() == Kind.IMPORT;
    }

    private boolean sigChanged() {
        return (status.isDefined() != prevStatus.isDefined())
                || (status.isDefined() && !si.className().equals(classNameInitial))
                || signatureChanged;
    }

    Stream<Unit> effectedDependents() {
        //System.err.printf("effectedDependents sigChanged=%b  dependenciesNeeded=%b   status=%s\n",
        //       sigChanged(), dependenciesNeeded, status);
        return sigChanged() || dependenciesNeeded || status == RECOVERABLE_NOT_DEFINED
                ? dependents()
                : Stream.empty();
    }

    Stream<Unit> dependents() {
        return state.maps.getDependents(si)
                    .stream()
                    .filter(xsi -> xsi != si && xsi.status().isActive())
                    .map(xsi -> new Unit(state, xsi, si, new DiagList()));
    }

    void finish() {
        recordCompilation();
        state.maps.installSnippet(si);
    }

    private void markOldDeclarationOverwritten() {
        if (si != siOld && siOld != null && siOld.status().isActive()) {
            // Mark the old declaraion as replaced
            replaceOldEvent = new SnippetEvent(siOld,
                    siOld.status(), OVERWRITTEN,
                    false, si, null, null);
            siOld.setOverwritten();
        }
    }

    private DiagList computeDiagnostics() {
        DiagList diagnostics = new DiagList();
        DiagList diags = compilationDiagnostics;
        if (status == RECOVERABLE_DEFINED || status == RECOVERABLE_NOT_DEFINED) {
            UnresolvedExtractor ue = new UnresolvedExtractor(diags);
            diagnostics.addAll(ue.otherAll());
        } else {
            unresolved = Collections.emptyList();
            diagnostics.addAll(diags);
        }
        diagnostics.addAll(generatedDiagnostics);
        return diagnostics;
    }

    private void recordCompilation() {
        state.maps.mapDependencies(si);
        DiagList diags = computeDiagnostics();
        si.setCompilationStatus(status, unresolved, diags);
        state.debug(DBG_GEN, "recordCompilation: %s -- status %s, unresolved %s\n",
                si, status, unresolved);
    }

    private void checkForOverwrite(AnalyzeTask at) {
        secondaryEvents = new ArrayList<>();
        if (replaceOldEvent != null) secondaryEvents.add(replaceOldEvent);

        // Defined methods can overwrite methods of other (equivalent) snippets
        if (si.kind() == Kind.METHOD && status.isDefined()) {
            MethodSnippet msi = (MethodSnippet) si;
            msi.setQualifiedParameterTypes(
                    computeQualifiedParameterTypes(at, msi));
            Status overwrittenStatus = overwriteMatchingMethod(msi);
            if (overwrittenStatus != null) {
                prevStatus = overwrittenStatus;
                signatureChanged = true;
            }
        }
    }

    // Check if there is a method whose user-declared parameter types are
    // different (and thus has a different snippet) but whose compiled parameter
    // types are the same. if so, consider it an overwrite replacement.
    private Status overwriteMatchingMethod(MethodSnippet msi) {
        String qpt = msi.qualifiedParameterTypes();
        List<MethodSnippet> matching = state.methods()
                .filter(sn ->
                           sn != null
                        && sn != msi
                        && sn.status().isActive()
                        && sn.name().equals(msi.name())
                        && qpt.equals(sn.qualifiedParameterTypes()))
                .collect(toList());

        // Look through all methods for a method of the same name, with the
        // same computed qualified parameter types
        Status overwrittenStatus = null;
        for (MethodSnippet sn : matching) {
            overwrittenStatus = sn.status();
            SnippetEvent se = new SnippetEvent(
                    sn, overwrittenStatus, OVERWRITTEN,
                    false, msi, null, null);
            sn.setOverwritten();
            secondaryEvents.add(se);
            state.debug(DBG_EVNT,
                    "Overwrite event #%d -- key: %s before: %s status: %s sig: %b cause: %s\n",
                    secondaryEvents.size(), se.snippet(), se.previousStatus(),
                    se.status(), se.isSignatureChange(), se.causeSnippet());
        }
        return overwrittenStatus;
    }

    private String computeQualifiedParameterTypes(AnalyzeTask at, MethodSnippet msi) {
        String rawSig = TreeDissector.createBySnippet(at, msi).typeOfMethod(msi);
        String signature = expunge(rawSig);
        int paren = signature.lastIndexOf(')');

        // Extract the parameter type string from the method signature,
        // if method did not compile use the user-supplied parameter types
        return paren >= 0
                ? signature.substring(0, paren + 1)
                : msi.parameterTypes();
    }

    SnippetEvent event(String value, JShellException exception) {
        boolean wasSignatureChanged = sigChanged();
        state.debug(DBG_EVNT, "Snippet: %s id: %s before: %s status: %s sig: %b cause: %s\n",
                si, si.id(), prevStatus, si.status(), wasSignatureChanged, causalSnippet);
        return new SnippetEvent(si, prevStatus, si.status(),
                wasSignatureChanged, causalSnippet, value, exception);
    }

    List<SnippetEvent> secondaryEvents() {
        return secondaryEvents==null
                ? Collections.emptyList()
                : secondaryEvents;
    }

    @Override
    public String toString() {
        return "Unit(" + si.name() + ")";
    }

    /**
     * Separate out the unresolvedDependencies errors from both the other
     * corralling errors and the overall errors.
     */
    private static class UnresolvedExtractor {

        private static final String RESOLVE_ERROR_SYMBOL = "symbol:";
        private static final String RESOLVE_ERROR_LOCATION = "location:";

        //TODO extract from tree instead -- note: internationalization
        private final Set<String> unresolved = new LinkedHashSet<>();
        private final DiagList otherErrors = new DiagList();
        private final DiagList otherAll = new DiagList();

        UnresolvedExtractor(DiagList diags) {
            for (Diag diag : diags) {
                if (diag.isError()) {
                    if (diag.isResolutionError()) {
                        String m = diag.getMessage(PARSED_LOCALE);
                        int symPos = m.indexOf(RESOLVE_ERROR_SYMBOL);
                        if (symPos >= 0) {
                            m = m.substring(symPos + RESOLVE_ERROR_SYMBOL.length());
                            int symLoc = m.indexOf(RESOLVE_ERROR_LOCATION);
                            if (symLoc >= 0) {
                                m = m.substring(0, symLoc);
                            }
                            m = m.trim();
                            unresolved.add(m);
                            continue;
                        }
                    }
                    otherErrors.add(diag);
                }
                otherAll.add(diag);
            }
        }

        DiagList otherCorralledErrors() {
            return otherErrors;
        }

        DiagList otherAll() {
            return otherAll;
        }

        List<String> unresolved() {
            return new ArrayList<>(unresolved);
        }
    }
}

jdk/jshell/Unit.java

 

JDK 11 jdk.jsobject.jmod - JS Object Module

JDK 11 jdk.jlink.jmod - JLink Tool

Download and Use JDK 11

⇑⇑ FAQ for JDK (Java Development Kit)

2020-06-30, 7875👍, 0💬