--- old/src/jdk.jshell/share/classes/jdk/jshell/JShell.java 2016-07-12 22:46:51.113841589 -0700 +++ new/src/jdk.jshell/share/classes/jdk/jshell/JShell.java 2016-07-12 22:46:50.982838220 -0700 @@ -44,13 +44,15 @@ import java.util.function.Supplier; import jdk.internal.jshell.debug.InternalDebugControl; -import jdk.internal.jshell.jdi.FailOverExecutionControl; +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; -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 @@ -90,17 +92,17 @@ final BiFunction idGenerator; final List extraRemoteVMOptions; final List extraCompilerOptions; - final ExecutionControl executionControl; + final ExecutionControl.Generator executionControlGenerator; private int nextKeyIndex = 1; final Eval eval; - private final Map classnameToBytes = new HashMap<>(); + final ClassTracker classTracker; private final Map> shutdownListeners = new HashMap<>(); private final Map> keyStatusListeners = new HashMap<>(); private boolean closed = false; - private boolean executionControlLaunched = false; + private ExecutionControl executionControl = null; private SourceCodeAnalysisImpl sourceCodeAnalysis = null; private static final String L10N_RB_NAME = "jdk.jshell.resources.l10n"; @@ -114,17 +116,18 @@ 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.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(); } /** @@ -154,7 +157,7 @@ BiFunction idGenerator = null; List extraRemoteVMOptions = new ArrayList<>(); List extraCompilerOptions = new ArrayList<>(); - ExecutionControl executionControl; + ExecutionControl.Generator executionControlGenerator; Builder() { } @@ -310,12 +313,12 @@ * Sets the custom engine for execution. Snippet execution will be * provided by the specified {@link ExecutionControl} instance. * - * @param execEngine the execution engine + * @param executionControlGenerator the execution engine generator * @return the {@code Builder} instance (for use in chained * initialization) */ - public Builder executionEngine(ExecutionControl execEngine) { - this.executionControl = execEngine; + public Builder executionEngine(ExecutionControl.Generator executionControlGenerator) { + this.executionControlGenerator = executionControlGenerator; return this; } @@ -397,7 +400,8 @@ * be an event showing its status changed to OVERWRITTEN, this will not * occur for dropped, rejected, or already overwritten declarations. *

- * The execution environment is out of process. If the evaluated code + * 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 @@ -447,8 +451,14 @@ * @param path the path to add to the classpath. */ public void addToClasspath(String path) { - taskFactory.addToClasspath(path); // Compiler - executionControl().addToClasspath(path); // Runtime + // Compiler + taskFactory.addToClasspath(path); + // Runtime + try { + executionControl().addToClasspath(path); + } catch (ExecutionControlException ex) { + debug(ex, "on addToClasspath(" + path + ")"); + } if (sourceCodeAnalysis != null) { sourceCodeAnalysis.classpathChanged(); } @@ -468,8 +478,13 @@ * catching the {@link ThreadDeath} exception. */ public void stop() { - if (executionControl != null) - executionControl.stop(); + if (executionControl != null) { + try { + executionControl.stop(); + } catch (ExecutionControlException ex) { + debug(ex, "on stop()"); + } + } } /** @@ -622,7 +637,15 @@ throw new IllegalArgumentException( messageFormat("jshell.exc.var.not.valid", snippet, snippet.status())); } - String value = executionControl().varValue(snippet.classFullName(), snippet.name()); + 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); } @@ -706,33 +729,17 @@ } @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) { + if (executionControl == null) { try { - executionControlLaunched = true; - executionControl.start(new ExecutionEnvImpl()); + executionControl = executionControlGenerator.generate(new ExecutionEnvImpl()); } catch (Throwable ex) { throw new InternalError("Launching execution engine threw: " + ex.getMessage(), ex); } @@ -740,10 +747,6 @@ 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); }