--- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java Tue Nov 22 16:31:03 2016 -0800
+++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java Tue Nov 22 19:24:02 2016 -0800
@@ -63,7 +63,10 @@
*/
public class JdiDefaultExecutionControl extends JdiExecutionControl {
- private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
+ /**
+ * Default time-out expressed in milliseconds.
+ */
+ private static final int DEFAULT_TIMEOUT = 5000;
private VirtualMachine vm;
private Process process;
@@ -73,24 +76,60 @@
/**
* Creates an ExecutionControl instance based on a JDI
- * {@code LaunchingConnector}.
+ * {@code LaunchingConnector}. Same as
+ * {@code JdiDefaultExecutionControl.create(defaultRemoteAgent(), true, null, defaultTimeout())}.
*
* @return the generator
*/
public static ExecutionControl.Generator launch() {
- return env -> create(env, true, null);
+ return create(defaultRemoteAgent(), true, null, defaultTimeout());
}
/**
* Creates an ExecutionControl instance based on a JDI
- * {@code ListeningConnector}.
+ * {@code ListeningConnector}. Same as
+ * {@code JdiDefaultExecutionControl.create(defaultRemoteAgent(), false, host, defaultTimeout())}.
*
* @param host explicit hostname to use, if null use discovered
* hostname, applies to listening only (!isLaunch)
* @return the generator
*/
public static ExecutionControl.Generator listen(String host) {
- return env -> create(env, false, host);
+ return create(defaultRemoteAgent(), false, host, defaultTimeout());
+ }
+
+ /**
+ * Creates a JDI based ExecutionControl instance.
+ *
+ * @param remoteAgent the remote agent to launch
+ * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
+ * otherwise we start explicitly and use ListeningConnector
+ * @param host explicit hostname to use, if null use discovered
+ * hostname, applies to listening only (!isLaunch)
+ * @param timeout the start-up time-out in milliseconds
+ * @return the generator
+ */
+ public static ExecutionControl.Generator create(String remoteAgent,
+ boolean isLaunch, String host, int timeout) {
+ return env -> create(env, remoteAgent, isLaunch, host, timeout);
+ }
+
+ /**
+ * Default remote agent.
+ *
+ * @return the name of the standard remote agent
+ */
+ public static String defaultRemoteAgent() {
+ return RemoteExecutionControl.class.getName();
+ }
+
+ /**
+ * Default remote connection time-out
+ *
+ * @return time to wait for connection before failing, expressed in milliseconds.
+ */
+ public static int defaultTimeout() {
+ return DEFAULT_TIMEOUT;
}
/**
@@ -103,6 +142,7 @@
*
* @param env the context passed by
* {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
+ * @param remoteAgent the remote agent to launch
* @param isLaunch does JDI do the launch? That is, LaunchingConnector,
* otherwise we start explicitly and use ListeningConnector
* @param host explicit hostname to use, if null use discovered
@@ -110,16 +150,16 @@
* @return the channel
* @throws IOException if there are errors in set-up
*/
- private static ExecutionControl create(ExecutionEnv env,
- boolean isLaunch, String host) throws IOException {
+ private static ExecutionControl create(ExecutionEnv env, String remoteAgent,
+ boolean isLaunch, String host, int timeout) throws IOException {
try (final ServerSocket listener = new ServerSocket(0, 1, InetAddress.getLoopbackAddress())) {
- // timeout after 60 seconds
- listener.setSoTimeout(60000);
+ // timeout on I/O-socket
+ listener.setSoTimeout(timeout);
int port = listener.getLocalPort();
// Set-up the JDI connection
JdiInitiator jdii = new JdiInitiator(port,
- env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
+ env.extraRemoteVMOptions(), remoteAgent, isLaunch, host, timeout);
VirtualMachine vm = jdii.vm();
Process process = jdii.process();
@@ -197,7 +237,7 @@
for (ThreadReference thread : vm().allThreads()) {
// could also tag the thread (e.g. using name), to find it easier
for (StackFrame frame : thread.frames()) {
- if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
+ if (defaultRemoteAgent().equals(frame.location().declaringType().name()) &&
( "invoke".equals(frame.location().method().name())
|| "varValue".equals(frame.location().method().name()))) {
ObjectReference thiz = frame.thisObject();