66import java .io .ObjectOutput ;
77import java .io .OutputStream ;
88import java .net .InetAddress ;
9- import java .net .InetSocketAddress ;
109import java .net .ServerSocket ;
1110import java .time .Duration ;
11+ import java .util .ArrayList ;
1212import java .util .Collection ;
13+ import java .util .Collections ;
1314import java .util .List ;
1415import java .util .Map ;
1516import java .util .Objects ;
17+ import java .util .concurrent .CopyOnWriteArrayList ;
1618import java .util .function .BiFunction ;
19+ import java .util .function .Consumer ;
1720
1821import com .sun .jdi .VirtualMachine ;
1922import jdk .jshell .execution .JdiInitiator ;
2326import jdk .jshell .spi .ExecutionControlProvider ;
2427import jdk .jshell .spi .ExecutionEnv ;
2528import jsheets .evaluation .shell .environment .ClassFileStore ;
29+ import jsheets .evaluation .shell .environment .EmptyClassFileStore ;
2630
2731import static jdk .jshell .execution .Util .remoteInputOutput ;
2832
@@ -31,6 +35,10 @@ public final class ForkingExecutionControlProvider
3135
3236 private static final Duration defaultTimeout = Duration .ofMillis (3000 );
3337
38+ public static ForkingExecutionControlProvider create () {
39+ return create (List .of (), EmptyClassFileStore .create ());
40+ }
41+
3442 public static ForkingExecutionControlProvider create (
3543 Collection <String > rawVirtualMachineOptions ,
3644 ClassFileStore classFileStore
@@ -91,10 +99,10 @@ private Box initiate(int port) {
9199 /* port */ port ,
92100 /* options */ rawVirtualMachineOptions ,
93101 /* remoteAgentClassName */ remoteAgentClassName ,
94- /* controlledLaunch */ true ,
95- /* host */ host ,
102+ /* controlledLaunch */ false ,
103+ /* host */ "" ,
96104 /* timeout */ (int ) timeout .toMillis (),
97- /* connectorOptions*/ Map . of ()
105+ /* connectorOptions*/ Collections . emptyMap ()
98106 );
99107 return new Box (
100108 initiator .vm (),
@@ -118,20 +126,32 @@ private ExecutionControl accept(
118126 ExecutionEnv environment ,
119127 Box box
120128 ) throws IOException {
129+ var hooks = registerCloseHooks (box .machine ());
121130 var socket = listener .accept ();
122131 var output = socket .getOutputStream ();
123132 return remoteInputOutput (
124133 socket .getInputStream (),
125134 output ,
126135 createOutputs (environment ),
127136 createInputs (environment ),
128- createControl (box , environment )
137+ createControl (box , environment , hooks )
129138 );
130139 }
131140
141+ private Collection <Consumer <String >> registerCloseHooks (VirtualMachine machine ) {
142+ var hooks = new CopyOnWriteArrayList <Consumer <String >>();
143+ Util .detectJdiExitEvent (machine , event -> {
144+ for (var hook : hooks ) {
145+ hook .accept (event );
146+ }
147+ });
148+ return hooks ;
149+ }
150+
132151 private BiFunction <ObjectInput , ObjectOutput , ExecutionControl > createControl (
133152 Box box ,
134- ExecutionEnv environment
153+ ExecutionEnv environment ,
154+ Collection <Consumer <String >> hooks
135155 ) {
136156 return (input , output ) -> {
137157 var control = new ForkedExecutionControl (
@@ -142,7 +162,8 @@ private BiFunction<ObjectInput, ObjectOutput, ExecutionControl> createControl(
142162 remoteAgentClassName ,
143163 classFileStore
144164 );
145- registerCloseHooks (box .machine (), environment , control );
165+ hooks .add (event -> environment .closeDown ());
166+ hooks .add (event -> control .disposeMachine ());
146167 return control ;
147168 };
148169 }
@@ -157,15 +178,4 @@ private Map<String, OutputStream> createOutputs(ExecutionEnv environment) {
157178 private Map <String , InputStream > createInputs (ExecutionEnv environment ) {
158179 return Map .of ("in" , environment .userIn ());
159180 }
160-
161- private void registerCloseHooks (
162- VirtualMachine machine ,
163- ExecutionEnv environment ,
164- ForkedExecutionControl control
165- ) {
166- Util .detectJdiExitEvent (machine , event -> {
167- environment .closeDown ();
168- control .disposeMachine ();
169- });
170- }
171181}
0 commit comments