langtools/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java
author jlahoda
Fri, 11 Nov 2016 12:54:47 +0100
changeset 41994 e43f670394ca
parent 41941 a935ac3f5274
child 41995 1ac75bf2dc3a
permissions -rw-r--r--
8145838: JShell: restrict RemoteAgent connection socket to localhost Summary: Also reviewed by Chris Ries Reviewed-by: rfield
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     1
/*
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     2
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     4
 *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    10
 *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    15
 * accompanied this code).
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    16
 *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    20
 *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    23
 * questions.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    24
 */
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    25
package jdk.jshell.execution;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    26
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
    27
import java.io.ByteArrayOutputStream;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    28
import java.io.IOException;
40767
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
    29
import java.io.InputStream;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    30
import java.io.ObjectInput;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    31
import java.io.ObjectOutput;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    32
import java.io.OutputStream;
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
    33
import java.net.InetAddress;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    34
import java.net.ServerSocket;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    35
import java.net.Socket;
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
    36
import java.security.SecureRandom;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    37
import java.util.ArrayList;
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
    38
import java.util.Arrays;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    39
import java.util.HashMap;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    40
import java.util.List;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    41
import java.util.Map;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    42
import java.util.function.Consumer;
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
    43
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    44
import com.sun.jdi.BooleanValue;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    45
import com.sun.jdi.ClassNotLoadedException;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    46
import com.sun.jdi.Field;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    47
import com.sun.jdi.IncompatibleThreadStateException;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    48
import com.sun.jdi.InvalidTypeException;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    49
import com.sun.jdi.ObjectReference;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    50
import com.sun.jdi.StackFrame;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    51
import com.sun.jdi.ThreadReference;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    52
import com.sun.jdi.VMDisconnectedException;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    53
import com.sun.jdi.VirtualMachine;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    54
import jdk.jshell.spi.ExecutionControl;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    55
import jdk.jshell.spi.ExecutionEnv;
40767
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
    56
import static jdk.jshell.execution.Util.remoteInputOutput;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    57
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    58
/**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    59
 * The implementation of {@link jdk.jshell.spi.ExecutionControl} that the
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    60
 * JShell-core uses by default.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    61
 * Launches a remote process -- the "remote agent".
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    62
 * Interfaces to the remote agent over a socket and via JDI.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    63
 * Designed to work with {@link RemoteExecutionControl}.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    64
 *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    65
 * @author Robert Field
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    66
 * @author Jan Lahoda
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    67
 */
41941
a935ac3f5274 8161983: JShell API: Clean-up following 8160127 et. al.
rfield
parents: 40767
diff changeset
    68
public class JdiDefaultExecutionControl extends JdiExecutionControl {
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    69
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    70
    private static final String REMOTE_AGENT = RemoteExecutionControl.class.getName();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    71
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    72
    private VirtualMachine vm;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    73
    private Process process;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    74
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    75
    private final Object STOP_LOCK = new Object();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    76
    private boolean userCodeRunning = false;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    77
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    78
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    79
     * Creates an ExecutionControl instance based on a JDI
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    80
     * {@code LaunchingConnector}.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    81
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    82
     * @return the generator
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    83
     */
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    84
    public static ExecutionControl.Generator launch() {
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
    85
        return env -> create(env, true, null);
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    86
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    87
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    88
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    89
     * Creates an ExecutionControl instance based on a JDI
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    90
     * {@code ListeningConnector}.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    91
     *
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
    92
     * @param host explicit hostname to use, if null use discovered
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
    93
     * hostname, applies to listening only (!isLaunch)
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    94
     * @return the generator
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    95
     */
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
    96
    public static ExecutionControl.Generator listen(String host) {
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
    97
        return env -> create(env, false, host);
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    98
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
    99
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   100
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   101
     * Creates an ExecutionControl instance based on a JDI
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   102
     * {@code ListeningConnector} or {@code LaunchingConnector}.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   103
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   104
     * Initialize JDI and use it to launch the remote JVM. Set-up a socket for
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   105
     * commands and results. This socket also transports the user
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   106
     * input/output/error.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   107
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   108
     * @param env the context passed by
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   109
     * {@link jdk.jshell.spi.ExecutionControl#start(jdk.jshell.spi.ExecutionEnv) }
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   110
     * @param isLaunch does JDI do the launch? That is, LaunchingConnector,
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   111
     * otherwise we start explicitly and use ListeningConnector
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   112
     * @param host explicit hostname to use, if null use discovered
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   113
     * hostname, applies to listening only (!isLaunch)
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   114
     * @return the channel
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   115
     * @throws IOException if there are errors in set-up
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   116
     */
40767
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   117
    private static ExecutionControl create(ExecutionEnv env,
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   118
            boolean isLaunch, String host) throws IOException {
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   119
        try (final ServerSocket listener = new ServerSocket(0, 1, InetAddress.getLoopbackAddress())) {
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   120
            // timeout after 60 seconds
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   121
            listener.setSoTimeout(60000);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   122
            int port = listener.getLocalPort();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   123
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   124
            // Set-up the JDI connection
41941
a935ac3f5274 8161983: JShell API: Clean-up following 8160127 et. al.
rfield
parents: 40767
diff changeset
   125
            JdiInitiator jdii = new JdiInitiator(port,
40764
29ded021f809 8164518: JShell: Add failover case of explicitly listening to "localhost"
rfield
parents: 39807
diff changeset
   126
                    env.extraRemoteVMOptions(), REMOTE_AGENT, isLaunch, host);
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   127
            VirtualMachine vm = jdii.vm();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   128
            Process process = jdii.process();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   129
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   130
            OutputStream processOut = process.getOutputStream();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   131
            SecureRandom rng = new SecureRandom();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   132
            byte[] randomBytes = new byte[VERIFY_HASH_LEN];
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   133
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   134
            rng.nextBytes(randomBytes);
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   135
            processOut.write(randomBytes);
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   136
            processOut.flush();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   137
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   138
            List<Consumer<String>> deathListeners = new ArrayList<>();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   139
            deathListeners.add(s -> env.closeDown());
41941
a935ac3f5274 8161983: JShell API: Clean-up following 8160127 et. al.
rfield
parents: 40767
diff changeset
   140
            Util.detectJdiExitEvent(vm, s -> {
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   141
                for (Consumer<String> h : deathListeners) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   142
                    h.accept(s);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   143
                }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   144
            });
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   145
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   146
            ByteArrayOutputStream receivedRandomBytes = new ByteArrayOutputStream();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   147
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   148
            // Set-up the commands/reslts on the socket.  Piggy-back snippet
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   149
            // output.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   150
            Socket socket = listener.accept();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   151
            // out before in -- match remote creation so we don't hang
40767
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   152
            OutputStream out = socket.getOutputStream();
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   153
            Map<String, OutputStream> outputs = new HashMap<>();
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   154
            outputs.put("out", env.userOut());
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   155
            outputs.put("err", env.userErr());
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   156
            outputs.put("echo", new OutputStream() {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   157
                @Override public void write(int b) throws IOException {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   158
                    synchronized (receivedRandomBytes) {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   159
                        receivedRandomBytes.write(b);
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   160
                        receivedRandomBytes.notify();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   161
                    }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   162
                }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   163
            });
40767
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   164
            Map<String, InputStream> input = new HashMap<>();
c7908e8c786b 8131023: JShell: System.in does not work
jlahoda
parents: 40764
diff changeset
   165
            input.put("in", env.userIn());
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   166
            return remoteInputOutput(socket.getInputStream(), out, outputs, input, (objIn, objOut) -> {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   167
                synchronized (receivedRandomBytes) {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   168
                    while (receivedRandomBytes.size() < randomBytes.length) {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   169
                        try {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   170
                            receivedRandomBytes.wait();
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   171
                        } catch (InterruptedException ex) {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   172
                            //ignore
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   173
                        }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   174
                    }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   175
                    if (!Arrays.equals(receivedRandomBytes.toByteArray(), randomBytes)) {
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   176
                        throw new IllegalStateException("Invalid connection!");
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   177
                    }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   178
                }
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   179
                return new JdiDefaultExecutionControl(objOut, objIn, vm, process, deathListeners);
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   180
            });
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   181
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   182
    }
41994
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   183
    //where:
e43f670394ca 8145838: JShell: restrict RemoteAgent connection socket to localhost
jlahoda
parents: 41941
diff changeset
   184
        private static final int VERIFY_HASH_LEN = 20;
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   185
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   186
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   187
     * Create an instance.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   188
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   189
     * @param cmdout the output for commands
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   190
     * @param cmdin the input for responses
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   191
     */
41941
a935ac3f5274 8161983: JShell API: Clean-up following 8160127 et. al.
rfield
parents: 40767
diff changeset
   192
    private JdiDefaultExecutionControl(ObjectOutput cmdout, ObjectInput cmdin,
39807
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   193
            VirtualMachine vm, Process process, List<Consumer<String>> deathListeners) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   194
        super(cmdout, cmdin);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   195
        this.vm = vm;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   196
        this.process = process;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   197
        deathListeners.add(s -> disposeVM());
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   198
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   199
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   200
    @Override
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   201
    public String invoke(String classname, String methodname)
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   202
            throws RunException,
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   203
            EngineTerminationException, InternalException {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   204
        String res;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   205
        synchronized (STOP_LOCK) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   206
            userCodeRunning = true;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   207
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   208
        try {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   209
            res = super.invoke(classname, methodname);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   210
        } finally {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   211
            synchronized (STOP_LOCK) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   212
                userCodeRunning = false;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   213
            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   214
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   215
        return res;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   216
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   217
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   218
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   219
     * Interrupts a running remote invoke by manipulating remote variables
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   220
     * and sending a stop via JDI.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   221
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   222
     * @throws EngineTerminationException the execution engine has terminated
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   223
     * @throws InternalException an internal problem occurred
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   224
     */
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   225
    @Override
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   226
    public void stop() throws EngineTerminationException, InternalException {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   227
        synchronized (STOP_LOCK) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   228
            if (!userCodeRunning) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   229
                return;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   230
            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   231
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   232
            vm().suspend();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   233
            try {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   234
                OUTER:
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   235
                for (ThreadReference thread : vm().allThreads()) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   236
                    // could also tag the thread (e.g. using name), to find it easier
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   237
                    for (StackFrame frame : thread.frames()) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   238
                        if (REMOTE_AGENT.equals(frame.location().declaringType().name()) &&
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   239
                                (    "invoke".equals(frame.location().method().name())
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   240
                                || "varValue".equals(frame.location().method().name()))) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   241
                            ObjectReference thiz = frame.thisObject();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   242
                            Field inClientCode = thiz.referenceType().fieldByName("inClientCode");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   243
                            Field expectingStop = thiz.referenceType().fieldByName("expectingStop");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   244
                            Field stopException = thiz.referenceType().fieldByName("stopException");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   245
                            if (((BooleanValue) thiz.getValue(inClientCode)).value()) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   246
                                thiz.setValue(expectingStop, vm().mirrorOf(true));
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   247
                                ObjectReference stopInstance = (ObjectReference) thiz.getValue(stopException);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   248
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   249
                                vm().resume();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   250
                                debug("Attempting to stop the client code...\n");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   251
                                thread.stop(stopInstance);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   252
                                thiz.setValue(expectingStop, vm().mirrorOf(false));
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   253
                            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   254
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   255
                            break OUTER;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   256
                        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   257
                    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   258
                }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   259
            } catch (ClassNotLoadedException | IncompatibleThreadStateException | InvalidTypeException ex) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   260
                throw new InternalException("Exception on remote stop: " + ex);
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   261
            } finally {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   262
                vm().resume();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   263
            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   264
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   265
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   266
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   267
    @Override
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   268
    public void close() {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   269
        super.close();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   270
        disposeVM();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   271
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   272
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   273
    private synchronized void disposeVM() {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   274
        try {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   275
            if (vm != null) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   276
                vm.dispose(); // This could NPE, so it is caught below
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   277
                vm = null;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   278
            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   279
        } catch (VMDisconnectedException ex) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   280
            // Ignore if already closed
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   281
        } catch (Throwable ex) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   282
            debug(ex, "disposeVM");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   283
        } finally {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   284
            if (process != null) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   285
                process.destroy();
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   286
                process = null;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   287
            }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   288
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   289
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   290
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   291
    @Override
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   292
    protected synchronized VirtualMachine vm() throws EngineTerminationException {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   293
        if (vm == null) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   294
            throw new EngineTerminationException("VM closed");
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   295
        } else {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   296
            return vm;
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   297
        }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   298
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   299
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   300
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   301
     * Log debugging information. Arguments as for {@code printf}.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   302
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   303
     * @param format a format string as described in Format string syntax
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   304
     * @param args arguments referenced by the format specifiers in the format
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   305
     * string.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   306
     */
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   307
    private static void debug(String format, Object... args) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   308
        // Reserved for future logging
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   309
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   310
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   311
    /**
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   312
     * Log a serious unexpected internal exception.
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   313
     *
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   314
     * @param ex the exception
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   315
     * @param where a description of the context of the exception
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   316
     */
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   317
    private static void debug(Throwable ex, String where) {
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   318
        // Reserved for future logging
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   319
    }
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   320
ba0ff343d241 8160127: JShell API: extract abstract JDI and abstract streaming implementations of ExecutionControl
rfield
parents:
diff changeset
   321
}