src/jdk.jshell/share/classes/jdk/jshell/execution/JDIDefaultExecutionControl.java

Print this page




  60  * @author Robert Field
  61  * @author Jan Lahoda
  62  */
  63 public class JDIDefaultExecutionControl extends JDIExecutionControl {
  64 
  65     private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
  66 
  67     private VirtualMachine vm;
  68     private Process process;
  69 
  70     private final Object STOP_LOCK = new Object();
  71     private boolean userCodeRunning = false;
  72 
  73     /**
  74      * Creates an ExecutionControl instance based on a JDI
  75      * {@code LaunchingConnector}.
  76      *
  77      * @return the generator
  78      */
  79     public static ExecutionControl.Generator launch() {
  80         return env -> create(env, true);
  81     }
  82 
  83     /**
  84      * Creates an ExecutionControl instance based on a JDI
  85      * {@code ListeningConnector}.
  86      *
  87      * @return the generator
  88      */
  89     public static ExecutionControl.Generator listen() {
  90         return env -> create(env, false);










  91     }
  92 
  93     /**
  94      * Creates an ExecutionControl instance based on a JDI
  95      * {@code ListeningConnector} or {@code LaunchingConnector}.
  96      *
  97      * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
  98      * commands and results. This socket also transports the user
  99      * input/output/error.
 100      *
 101      * @param env the context passed by
 102      * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }




 103      * @return the channel
 104      * @throws IOException if there are errors in set-up
 105      */
 106     private static JDIDefaultExecutionControl create(ExecutionEnv env, boolean isLaunch) throws IOException {

 107         try (final ServerSocket listener = new ServerSocket(0)) {
 108             // timeout after 60 seconds
 109             listener.setSoTimeout(60000);
 110             int port = listener.getLocalPort();
 111 
 112             // Set-up the JDI connection
 113             JDIInitiator jdii = new JDIInitiator(port,
 114                     env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch);
 115             VirtualMachine vm = jdii.vm();
 116             Process process = jdii.process();
 117 
 118             // Forward input to the remote agent
 119             Util.forwardInputToRemote(env.userIn(), process.getOutputStream(),
 120                     ex -> debug(ex, "input forwarding failure"));
 121 
 122             List<Consumer<String>> deathListeners = new ArrayList<>();
 123             deathListeners.add(s -> env.closeDown());
 124             Util.detectJDIExitEvent(vm, s -> {
 125                 for (Consumer<String> h : deathListeners) {
 126                     h.accept(s);
 127                 }
 128             });
 129 
 130             // Set-up the commands/reslts on the socket.  Piggy-back snippet
 131             // output.
 132             Socket socket = listener.accept();
 133             // out before in -- match remote creation so we don't hang
 134             ObjectOutput cmdout = new ObjectOutputStream(socket.getOutputStream());




  60  * @author Robert Field
  61  * @author Jan Lahoda
  62  */
  63 public class JDIDefaultExecutionControl extends JDIExecutionControl {
  64 
  65     private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
  66 
  67     private VirtualMachine vm;
  68     private Process process;
  69 
  70     private final Object STOP_LOCK = new Object();
  71     private boolean userCodeRunning = false;
  72 
  73     /**
  74      * Creates an ExecutionControl instance based on a JDI
  75      * {@code LaunchingConnector}.
  76      *
  77      * @return the generator
  78      */
  79     public static ExecutionControl.Generator launch() {
  80         return env -> create(env, true, false);
  81     }
  82 
  83     /**
  84      * Creates an ExecutionControl instance based on a JDI
  85      * {@code ListeningConnector}.
  86      *
  87      * @return the generator
  88      */
  89     public static ExecutionControl.Generator listen() {
  90         return env -> create(env, false, false);
  91     }
  92 
  93     /**
  94      * Creates an ExecutionControl instance based on a JDI
  95      * {@code ListeningConnector} connecting to "localhost".
  96      *
  97      * @return the generator
  98      */
  99     public static ExecutionControl.Generator listenLocalhost() {
 100         return env -> create(env, false, true);
 101     }
 102 
 103     /**
 104      * Creates an ExecutionControl instance based on a JDI
 105      * {@code ListeningConnector} or {@code LaunchingConnector}.
 106      *
 107      * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
 108      * commands and results. This socket also transports the user
 109      * input/output/error.
 110      *
 111      * @param env the context passed by
 112      * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
 113      * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
 114      * otherwise we start explicitly and use ListeningConnector
 115      * @param useLocalhost explicitly use "localhost" rather than discovered
 116      * hostname, applies to listening only (!isLaunch)
 117      * @return the channel
 118      * @throws IOException if there are errors in set-up
 119      */
 120     private static JDIDefaultExecutionControl create(ExecutionEnv env,
 121             boolean isLaunch, boolean useLocalhost) throws IOException {
 122         try (final ServerSocket listener = new ServerSocket(0)) {
 123             // timeout after 60 seconds
 124             listener.setSoTimeout(60000);
 125             int port = listener.getLocalPort();
 126 
 127             // Set-up the JDI connection
 128             JDIInitiator jdii = new JDIInitiator(port,
 129                     env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, useLocalhost);
 130             VirtualMachine vm = jdii.vm();
 131             Process process = jdii.process();
 132 
 133             // Forward input to the remote agent
 134             Util.forwardInputToRemote(env.userIn(), process.getOutputStream(),
 135                     ex -> debug(ex, "input forwarding failure"));
 136 
 137             List<Consumer<String>> deathListeners = new ArrayList<>();
 138             deathListeners.add(s -> env.closeDown());
 139             Util.detectJDIExitEvent(vm, s -> {
 140                 for (Consumer<String> h : deathListeners) {
 141                     h.accept(s);
 142                 }
 143             });
 144 
 145             // Set-up the commands/reslts on the socket.  Piggy-back snippet
 146             // output.
 147             Socket socket = listener.accept();
 148             // out before in -- match remote creation so we don't hang
 149             ObjectOutput cmdout = new ObjectOutputStream(socket.getOutputStream());