src/jdk.jshell/share/classes/jdk/jshell/JShell.java

Print this page

        

*** 42,58 **** import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; import jdk.internal.jshell.debug.InternalDebugControl; ! import jdk.internal.jshell.jdi.FailOverExecutionControl; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static jdk.jshell.Util.expunge; - import jdk.jshell.Snippet.Status; - import jdk.internal.jshell.jdi.JDIExecutionControl; - import jdk.jshell.spi.ExecutionEnv; /** * The JShell evaluation state engine. This is the central class in the JShell * API. A {@code JShell} instance holds the evolving compilation and * execution state. The state is changed with the instance methods --- 42,60 ---- import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Supplier; import jdk.internal.jshell.debug.InternalDebugControl; ! import jdk.jshell.Snippet.Status; ! import jdk.jshell.execution.JDIDefaultExecutionControl; ! import jdk.jshell.spi.ExecutionControl.EngineTerminationException; ! import jdk.jshell.spi.ExecutionControl.ExecutionControlException; ! import jdk.jshell.spi.ExecutionEnv; ! import static jdk.jshell.execution.Util.failOverExecutionControlGenerator; import static java.util.stream.Collectors.collectingAndThen; import static java.util.stream.Collectors.toList; import static jdk.jshell.Util.expunge; /** * The JShell evaluation state engine. This is the central class in the JShell * API. A {@code JShell} instance holds the evolving compilation and * execution state. The state is changed with the instance methods
*** 88,108 **** final PrintStream err; final Supplier<String> tempVariableNameGenerator; final BiFunction<Snippet, Integer, String> idGenerator; final List<String> extraRemoteVMOptions; final List<String> extraCompilerOptions; ! final ExecutionControl executionControl; private int nextKeyIndex = 1; final Eval eval; ! private final Map<String, byte[]> classnameToBytes = new HashMap<>(); private final Map<Subscription, Consumer<JShell>> shutdownListeners = new HashMap<>(); private final Map<Subscription, Consumer<SnippetEvent>> keyStatusListeners = new HashMap<>(); private boolean closed = false; ! private boolean executionControlLaunched = false; private SourceCodeAnalysisImpl sourceCodeAnalysis = null; private static final String L10N_RB_NAME = "jdk.jshell.resources.l10n"; private static ResourceBundle outputRB = null; --- 90,110 ---- final PrintStream err; final Supplier<String> tempVariableNameGenerator; final BiFunction<Snippet, Integer, String> idGenerator; final List<String> extraRemoteVMOptions; final List<String> extraCompilerOptions; ! final ExecutionControl.Generator executionControlGenerator; private int nextKeyIndex = 1; final Eval eval; ! final ClassTracker classTracker; private final Map<Subscription, Consumer<JShell>> shutdownListeners = new HashMap<>(); private final Map<Subscription, Consumer<SnippetEvent>> keyStatusListeners = new HashMap<>(); private boolean closed = false; ! private ExecutionControl executionControl = null; private SourceCodeAnalysisImpl sourceCodeAnalysis = null; private static final String L10N_RB_NAME = "jdk.jshell.resources.l10n"; private static ResourceBundle outputRB = null;
*** 112,132 **** this.err = b.err; this.tempVariableNameGenerator = b.tempVariableNameGenerator; this.idGenerator = b.idGenerator; this.extraRemoteVMOptions = b.extraRemoteVMOptions; this.extraCompilerOptions = b.extraCompilerOptions; ! this.executionControl = b.executionControl==null ! ? new FailOverExecutionControl( ! new JDIExecutionControl(), ! new JDIExecutionControl(false)) ! : b.executionControl; this.maps = new SnippetMaps(this); this.keyMap = new KeyMap(this); this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); } /** * Builder for {@code JShell} instances. * Create custom instances of {@code JShell} by using the setter --- 114,135 ---- this.err = b.err; this.tempVariableNameGenerator = b.tempVariableNameGenerator; this.idGenerator = b.idGenerator; this.extraRemoteVMOptions = b.extraRemoteVMOptions; this.extraCompilerOptions = b.extraCompilerOptions; ! this.executionControlGenerator = b.executionControlGenerator==null ! ? failOverExecutionControlGenerator( ! JDIDefaultExecutionControl.launch(), ! JDIDefaultExecutionControl.listen()) ! : b.executionControlGenerator; this.maps = new SnippetMaps(this); this.keyMap = new KeyMap(this); this.outerMap = new OuterWrapMap(this); this.taskFactory = new TaskFactory(this); this.eval = new Eval(this); + this.classTracker = new ClassTracker(); } /** * Builder for {@code JShell} instances. * Create custom instances of {@code JShell} by using the setter
*** 152,162 **** PrintStream err = System.err; Supplier<String> tempVariableNameGenerator = null; BiFunction<Snippet, Integer, String> idGenerator = null; List<String> extraRemoteVMOptions = new ArrayList<>(); List<String> extraCompilerOptions = new ArrayList<>(); ! ExecutionControl executionControl; Builder() { } /** * Sets the input for the running evaluation (it's {@code System.in}). Note: --- 155,165 ---- PrintStream err = System.err; Supplier<String> tempVariableNameGenerator = null; BiFunction<Snippet, Integer, String> idGenerator = null; List<String> extraRemoteVMOptions = new ArrayList<>(); List<String> extraCompilerOptions = new ArrayList<>(); ! ExecutionControl.Generator executionControlGenerator; Builder() { } /** * Sets the input for the running evaluation (it's {@code System.in}). Note:
*** 308,323 **** /** * Sets the custom engine for execution. Snippet execution will be * provided by the specified {@link ExecutionControl} instance. * ! * @param execEngine the execution engine * @return the {@code Builder} instance (for use in chained * initialization) */ ! public Builder executionEngine(ExecutionControl execEngine) { ! this.executionControl = execEngine; return this; } /** * Builds a JShell state engine. This is the entry-point to all JShell --- 311,326 ---- /** * Sets the custom engine for execution. Snippet execution will be * provided by the specified {@link ExecutionControl} instance. * ! * @param executionControlGenerator the execution engine generator * @return the {@code Builder} instance (for use in chained * initialization) */ ! public Builder executionEngine(ExecutionControl.Generator executionControlGenerator) { ! this.executionControlGenerator = executionControlGenerator; return this; } /** * Builds a JShell state engine. This is the entry-point to all JShell
*** 395,405 **** * allowed and are errors. * If a previous definition of a declaration is overwritten then there will * be an event showing its status changed to OVERWRITTEN, this will not * occur for dropped, rejected, or already overwritten declarations. * <p> ! * The execution environment is out of process. If the evaluated code * causes the execution environment to terminate, this {@code JShell} * instance will be closed but the calling process and VM remain valid. * @param input The input String to evaluate * @return the list of events directly or indirectly caused by this evaluation. * @throws IllegalStateException if this {@code JShell} instance is closed. --- 398,409 ---- * allowed and are errors. * If a previous definition of a declaration is overwritten then there will * be an event showing its status changed to OVERWRITTEN, this will not * occur for dropped, rejected, or already overwritten declarations. * <p> ! * If execution environment is out of process, as is the default case, then ! * if the evaluated code * causes the execution environment to terminate, this {@code JShell} * instance will be closed but the calling process and VM remain valid. * @param input The input String to evaluate * @return the list of events directly or indirectly caused by this evaluation. * @throws IllegalStateException if this {@code JShell} instance is closed.
*** 445,456 **** * Note that the unnamed package is not accessible from the package in which * {@link JShell#eval(String)} code is placed. * @param path the path to add to the classpath. */ public void addToClasspath(String path) { ! taskFactory.addToClasspath(path); // Compiler ! executionControl().addToClasspath(path); // Runtime if (sourceCodeAnalysis != null) { sourceCodeAnalysis.classpathChanged(); } } --- 449,466 ---- * Note that the unnamed package is not accessible from the package in which * {@link JShell#eval(String)} code is placed. * @param path the path to add to the classpath. */ public void addToClasspath(String path) { ! // Compiler ! taskFactory.addToClasspath(path); ! // Runtime ! try { ! executionControl().addToClasspath(path); ! } catch (ExecutionControlException ex) { ! debug(ex, "on addToClasspath(" + path + ")"); ! } if (sourceCodeAnalysis != null) { sourceCodeAnalysis.classpathChanged(); } }
*** 466,477 **** * The attempt to stop the user's code may fail in some case, which may include * when the execution is blocked on an I/O operation, or when the user's code is * catching the {@link ThreadDeath} exception. */ public void stop() { ! if (executionControl != null) executionControl.stop(); } /** * Close this state engine. Frees resources. Should be called when this * state engine is no longer needed. --- 476,492 ---- * The attempt to stop the user's code may fail in some case, which may include * when the execution is blocked on an I/O operation, or when the user's code is * catching the {@link ThreadDeath} exception. */ public void stop() { ! if (executionControl != null) { ! try { executionControl.stop(); + } catch (ExecutionControlException ex) { + debug(ex, "on stop()"); + } + } } /** * Close this state engine. Frees resources. Should be called when this * state engine is no longer needed.
*** 620,630 **** checkValidSnippet(snippet); if (snippet.status() != Status.VALID) { throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } ! String value = executionControl().varValue(snippet.classFullName(), snippet.name()); return expunge(value); } /** * Register a callback to be called when the Status of a snippet changes. --- 635,653 ---- checkValidSnippet(snippet); if (snippet.status() != Status.VALID) { throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } ! String value; ! try { ! value = executionControl().varValue(snippet.classFullName(), snippet.name()); ! } catch (EngineTerminationException ex) { ! throw new IllegalStateException(ex.getMessage()); ! } catch (ExecutionControlException ex) { ! debug(ex, "In varValue()"); ! return "[" + ex.getMessage() + "]"; ! } return expunge(value); } /** * Register a callback to be called when the Status of a snippet changes.
*** 704,751 **** public List<String> extraRemoteVMOptions() { return extraRemoteVMOptions; } @Override - public byte[] getClassBytes(String classname) { - return classnameToBytes.get(classname); - } - - @Override - public EvalException createEvalException(String message, String exceptionClass, StackTraceElement[] stackElements) { - return new EvalException(message, exceptionClass, stackElements); - } - - @Override - public UnresolvedReferenceException createUnresolvedReferenceException(int id, StackTraceElement[] stackElements) { - DeclarationSnippet sn = (DeclarationSnippet) maps.getSnippetDeadOrAlive(id); - return new UnresolvedReferenceException(sn, stackElements); - } - - @Override public void closeDown() { JShell.this.closeDown(); } } // --- private / package-private implementation support --- ExecutionControl executionControl() { ! if (!executionControlLaunched) { try { ! executionControlLaunched = true; ! executionControl.start(new ExecutionEnvImpl()); } catch (Throwable ex) { throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex); } } return executionControl; } - void setClassnameToBytes(String classname, byte[] bytes) { - classnameToBytes.put(classname, bytes); - } - void debug(int flags, String format, Object... args) { InternalDebugControl.debug(this, err, flags, format, args); } void debug(Exception ex, String where) { --- 727,754 ---- public List<String> extraRemoteVMOptions() { return extraRemoteVMOptions; } @Override public void closeDown() { JShell.this.closeDown(); } + } // --- private / package-private implementation support --- ExecutionControl executionControl() { ! if (executionControl == null) { try { ! executionControl = executionControlGenerator.generate(new ExecutionEnvImpl()); } catch (Throwable ex) { throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex); } } return executionControl; } void debug(int flags, String format, Object... args) { InternalDebugControl.debug(this, err, flags, format, args); } void debug(Exception ex, String where) {