langtools/test/jdk/jshell/LocalExecutionControl.java
author rfield
Sat, 21 May 2016 22:32:08 -0700
changeset 38535 4a25025e0b0d
child 38540 0668586535f1
permissions -rw-r--r--
8156101: JShell SPI: Provide a pluggable execution control SPI Reviewed-by: jlahoda
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
38535
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     1
/*
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     2
 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     4
 *
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    10
 *
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    15
 * accompanied this code).
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    16
 *
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    20
 *
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    23
 * questions.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    24
 */
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    25
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    26
import jdk.jshell.spi.ExecutionControl;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    27
import jdk.jshell.spi.ExecutionEnv;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    28
import jdk.jshell.spi.SPIResolutionException;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    29
import jdk.jshell.EvalException;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    30
import jdk.jshell.UnresolvedReferenceException;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    31
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    32
import java.io.File;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    33
import java.lang.reflect.Field;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    34
import java.lang.reflect.InvocationTargetException;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    35
import java.lang.reflect.Method;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    36
import java.net.MalformedURLException;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    37
import java.net.URL;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    38
import java.net.URLClassLoader;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    39
import java.security.CodeSource;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    40
import java.util.Arrays;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    41
import java.util.Collection;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    42
import java.util.HashMap;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    43
import java.util.Map;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    44
import java.util.TreeMap;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    45
import java.util.concurrent.atomic.AtomicReference;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    46
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    47
/**
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    48
 * An implementation of ExecutionControl which executes in the same JVM as the
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    49
 * JShell core.
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    50
 *
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    51
 * @author Grigory Ptashko
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    52
 */
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    53
class LocalExecutionControl implements ExecutionControl {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    54
    private class REPLClassLoader extends URLClassLoader {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    55
        REPLClassLoader() {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    56
            super(new URL[0]);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    57
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    58
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    59
        @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    60
        protected Class<?> findClass(String name) throws ClassNotFoundException {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    61
            debug("findClass %s\n", name);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    62
            byte[] b = execEnv.getClassBytes(name);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    63
            if (b == null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    64
                return super.findClass(name);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    65
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    66
            return super.defineClass(name, b, 0, b.length, (CodeSource)null);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    67
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    68
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    69
        @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    70
        public void addURL(URL url) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    71
            super.addURL(url);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    72
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    73
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    74
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    75
    private ExecutionEnv execEnv;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    76
    private final Object STOP_LOCK = new Object();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    77
    private boolean userCodeRunning = false;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    78
    private REPLClassLoader loader = new REPLClassLoader();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    79
    private final Map<String, Class<?>> klasses = new TreeMap<>();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    80
    private final Map<String, byte[]> classBytes = new HashMap<>();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    81
    private ThreadGroup execThreadGroup;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    82
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    83
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    84
    public void start(ExecutionEnv execEnv) throws Exception {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    85
        this.execEnv = execEnv;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    86
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    87
        debug("Process-local code snippets execution control started");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    88
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    89
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    90
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    91
    public void close() {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    92
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    93
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    94
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    95
    public boolean load(Collection<String> classes) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    96
        try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    97
            loadLocal(classes);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    98
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
    99
            return true;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   100
        } catch (ClassNotFoundException | ClassCastException ex) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   101
            debug(ex, "Exception on load operation");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   102
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   103
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   104
        return false;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   105
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   106
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   107
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   108
    public String invoke(String classname, String methodname) throws EvalException, UnresolvedReferenceException {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   109
        try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   110
            synchronized (STOP_LOCK) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   111
                userCodeRunning = true;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   112
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   113
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   114
            // Invoke executable entry point in loaded code
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   115
            Class<?> klass = klasses.get(classname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   116
            if (klass == null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   117
                debug("Invoke failure: no such class loaded %s\n", classname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   118
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   119
                return "";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   120
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   121
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   122
            Method doitMethod;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   123
            try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   124
                this.getClass().getModule().addReads(klass.getModule());
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   125
                this.getClass().getModule().addExports(SPIResolutionException.class.getPackage()
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   126
                        .getName(), klass.getModule());
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   127
                doitMethod = klass.getDeclaredMethod(methodname, new Class<?>[0]);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   128
                doitMethod.setAccessible(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   129
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   130
                execThreadGroup = new ThreadGroup("JShell process local execution");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   131
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   132
                AtomicReference<InvocationTargetException> iteEx = new AtomicReference<>();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   133
                AtomicReference<IllegalAccessException> iaeEx = new AtomicReference<>();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   134
                AtomicReference<NoSuchMethodException> nmeEx = new AtomicReference<>();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   135
                AtomicReference<Boolean> stopped = new AtomicReference<>(false);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   136
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   137
                Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   138
                    if (e instanceof InvocationTargetException) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   139
                        if (e.getCause() instanceof ThreadDeath) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   140
                            stopped.set(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   141
                        } else {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   142
                            iteEx.set((InvocationTargetException)e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   143
                        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   144
                    } else if (e instanceof IllegalAccessException) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   145
                        iaeEx.set((IllegalAccessException)e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   146
                    } else if (e instanceof NoSuchMethodException) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   147
                        nmeEx.set((NoSuchMethodException)e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   148
                    } else if (e instanceof ThreadDeath) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   149
                        stopped.set(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   150
                    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   151
                });
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   152
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   153
                final Object[] res = new Object[1];
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   154
                Thread snippetThread = new Thread(execThreadGroup, () -> {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   155
                    try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   156
                        res[0] = doitMethod.invoke(null, new Object[0]);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   157
                    } catch (InvocationTargetException e) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   158
                        if (e.getCause() instanceof ThreadDeath) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   159
                            stopped.set(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   160
                        } else {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   161
                            iteEx.set(e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   162
                        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   163
                    } catch (IllegalAccessException e) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   164
                        iaeEx.set(e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   165
                    } catch (ThreadDeath e) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   166
                        stopped.set(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   167
                    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   168
                });
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   169
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   170
                snippetThread.start();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   171
                Thread[] threadList = new Thread[execThreadGroup.activeCount()];
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   172
                execThreadGroup.enumerate(threadList);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   173
                for (Thread thread : threadList) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   174
                    thread.join();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   175
                }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   176
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   177
                if (stopped.get()) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   178
                    debug("Killed.");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   179
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   180
                    return "";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   181
                }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   182
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   183
                if (iteEx.get() != null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   184
                    throw iteEx.get();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   185
                } else if (nmeEx.get() != null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   186
                    throw nmeEx.get();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   187
                } else if (iaeEx.get() != null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   188
                    throw iaeEx.get();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   189
                }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   190
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   191
                return valueString(res[0]);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   192
            } catch (InvocationTargetException ex) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   193
                Throwable cause = ex.getCause();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   194
                StackTraceElement[] elems = cause.getStackTrace();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   195
                if (cause instanceof SPIResolutionException) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   196
                    int id = ((SPIResolutionException)cause).id();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   197
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   198
                    throw execEnv.createUnresolvedReferenceException(id, elems);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   199
                } else {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   200
                    throw execEnv.createEvalException(cause.getMessage() == null ?
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   201
                            "<none>" : cause.getMessage(), cause.getClass().getName(), elems);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   202
                }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   203
            } catch (NoSuchMethodException | IllegalAccessException | InterruptedException ex) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   204
                debug(ex, "Invoke failure");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   205
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   206
        } finally {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   207
            synchronized (STOP_LOCK) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   208
                userCodeRunning = false;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   209
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   210
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   211
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   212
        return "";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   213
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   214
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   215
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   216
    @SuppressWarnings("deprecation")
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   217
    public void stop() {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   218
        synchronized (STOP_LOCK) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   219
            if (!userCodeRunning)
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   220
                return;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   221
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   222
            if (execThreadGroup == null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   223
                debug("Process-local code snippets thread group is null. Aborting stop.");
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   224
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   225
                return;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   226
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   227
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   228
            execThreadGroup.stop();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   229
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   230
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   231
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   232
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   233
    public String varValue(String classname, String varname) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   234
        Class<?> klass = klasses.get(classname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   235
        if (klass == null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   236
            debug("Var value failure: no such class loaded %s\n", classname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   237
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   238
            return "";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   239
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   240
        try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   241
            this.getClass().getModule().addReads(klass.getModule());
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   242
            Field var = klass.getDeclaredField(varname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   243
            var.setAccessible(true);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   244
            Object res = var.get(null);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   245
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   246
            return valueString(res);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   247
        } catch (Exception ex) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   248
            debug("Var value failure: no such field %s.%s\n", classname, varname);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   249
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   250
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   251
        return "";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   252
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   253
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   254
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   255
    public boolean addToClasspath(String cp) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   256
        // Append to the claspath
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   257
        for (String path : cp.split(File.pathSeparator)) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   258
            try {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   259
                loader.addURL(new File(path).toURI().toURL());
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   260
            } catch (MalformedURLException e) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   261
                throw new InternalError("Classpath addition failed: " + cp, e);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   262
            }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   263
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   264
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   265
        return true;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   266
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   267
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   268
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   269
    public boolean redefine(Collection<String> classes) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   270
        return false;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   271
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   272
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   273
    @Override
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   274
    public ClassStatus getClassStatus(String classname) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   275
        if (!classBytes.containsKey(classname)) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   276
            return ClassStatus.UNKNOWN;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   277
        } else if (!Arrays.equals(classBytes.get(classname), execEnv.getClassBytes(classname))) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   278
            return ClassStatus.NOT_CURRENT;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   279
        } else {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   280
            return ClassStatus.CURRENT;
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   281
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   282
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   283
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   284
    private void loadLocal(Collection<String> classes) throws ClassNotFoundException {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   285
        for (String className : classes) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   286
            Class<?> klass = loader.loadClass(className);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   287
            klasses.put(className, klass);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   288
            classBytes.put(className, execEnv.getClassBytes(className));
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   289
            klass.getDeclaredMethods();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   290
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   291
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   292
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   293
    private void debug(String format, Object... args) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   294
        //debug(execEnv.state(), execEnv.userErr(), flags, format, args);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   295
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   296
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   297
    private void debug(Exception ex, String where) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   298
        //debug(execEnv.state(), execEnv.userErr(), ex, where);
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   299
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   300
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   301
    private static String valueString(Object value) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   302
        if (value == null) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   303
            return "null";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   304
        } else if (value instanceof String) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   305
            return "\"" + (String)value + "\"";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   306
        } else if (value instanceof Character) {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   307
            return "'" + value + "'";
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   308
        } else {
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   309
            return value.toString();
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   310
        }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   311
    }
4a25025e0b0d 8156101: JShell SPI: Provide a pluggable execution control SPI
rfield
parents:
diff changeset
   312
}