diff -r 2537564a3031 -r 82e273c4f2b3 langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Tue Nov 22 16:31:03 2016 -0800 +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java Tue Nov 22 19:24:02 2016 -0800 @@ -30,6 +30,7 @@ import java.io.InputStream; import java.io.InterruptedIOException; import java.io.PrintStream; +import java.net.InetAddress; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; @@ -92,7 +93,6 @@ final BiFunction idGenerator; final List extraRemoteVMOptions; final List extraCompilerOptions; - final ExecutionControl.Generator executionControlGenerator; private int nextKeyIndex = 1; @@ -102,13 +102,13 @@ private final Map> keyStatusListeners = new HashMap<>(); private boolean closed = false; - private ExecutionControl executionControl = null; + private final ExecutionControl executionControl; private SourceCodeAnalysisImpl sourceCodeAnalysis = null; private static final String L10N_RB_NAME = "jdk.jshell.resources.l10n"; private static ResourceBundle outputRB = null; - JShell(Builder b) { + JShell(Builder b) throws IllegalStateException { this.in = b.in; this.out = b.out; this.err = b.err; @@ -116,11 +116,18 @@ this.idGenerator = b.idGenerator; this.extraRemoteVMOptions = b.extraRemoteVMOptions; this.extraCompilerOptions = b.extraCompilerOptions; - this.executionControlGenerator = b.executionControlGenerator==null - ? failOverExecutionControlGenerator(JdiDefaultExecutionControl.launch(), - JdiDefaultExecutionControl.listen("localhost"), - JdiDefaultExecutionControl.listen(null)) + ExecutionControl.Generator executionControlGenerator = b.executionControlGenerator==null + ? failOverExecutionControlGenerator( + JdiDefaultExecutionControl.listen(InetAddress.getLoopbackAddress().getHostAddress()), + JdiDefaultExecutionControl.launch(), + JdiDefaultExecutionControl.listen(null) + ) : b.executionControlGenerator; + try { + executionControl = executionControlGenerator.generate(new ExecutionEnvImpl()); + } catch (Throwable ex) { + throw new IllegalStateException("Launching JShell execution engine threw: " + ex.getMessage(), ex); + } this.maps = new SnippetMaps(this); this.keyMap = new KeyMap(this); @@ -331,9 +338,10 @@ * functionality. This creates a remote process for execution. It is * thus important to close the returned instance. * + * @throws IllegalStateException if the {@code JShell} instance could not be created. * @return the state engine */ - public JShell build() { + public JShell build() throws IllegalStateException { return new JShell(this); } } @@ -345,9 +353,10 @@ * That is, create an instance of {@code JShell}. *

* Equivalent to {@link JShell#builder() JShell.builder()}{@link JShell.Builder#build() .build()}. + * @throws IllegalStateException if the {@code JShell} instance could not be created. * @return an instance of {@code JShell}. */ - public static JShell create() { + public static JShell create() throws IllegalStateException { return builder().build(); } @@ -458,6 +467,7 @@ * 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. + * @throws IllegalStateException if this {@code JShell} instance is closed. */ public void addToClasspath(String path) { // Compiler @@ -504,7 +514,11 @@ public void close() { if (!closed) { closeDown(); - executionControl().close(); + try { + executionControl().close(); + } catch (Throwable ex) { + // don't care about exceptions on close + } if (sourceCodeAnalysis != null) { sourceCodeAnalysis.close(); } @@ -733,14 +747,8 @@ } // --- 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; }