Path: blob/master/test/hotspot/jtreg/compiler/compilercontrol/share/scenario/Executor.java
41161 views
/*1* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package compiler.compilercontrol.share.scenario;2425import compiler.compilercontrol.share.actions.BaseAction;26import jdk.test.lib.Asserts;27import jdk.test.lib.management.InputArguments;28import jdk.test.lib.process.OutputAnalyzer;29import jdk.test.lib.process.ProcessTools;30import jdk.test.lib.dcmd.CommandExecutor;31import jdk.test.lib.dcmd.PidJcmdExecutor;3233import java.io.BufferedReader;34import java.io.IOException;35import java.io.InputStreamReader;36import java.io.PrintWriter;37import java.lang.reflect.Executable;38import java.net.ServerSocket;39import java.net.Socket;40import java.util.ArrayList;41import java.util.Arrays;42import java.util.Collections;43import java.util.List;44import java.util.Map;4546public class Executor {47private final boolean isValid;48private final List<String> vmOptions;49private final Map<Executable, State> states;50private final List<String> jcmdCommands;51private final String execClass = System.getProperty("compiler."52+ "compilercontrol.share.executor.executeClass",53BaseAction.class.getName());54private OutputAnalyzer[] jcmdOutputAnalyzers;5556/**57* Constructor58*59* @param isValid shows that the input given to the VM is valid and60* VM shouldn't fail61* @param vmOptions a list of VM input options62* @param states a state map, or null for the non-checking execution63* @param jcmdCommands a list of diagnostic commands to be preformed64* on test VM65*/66public Executor(boolean isValid, List<String> vmOptions,67Map<Executable, State> states, List<String> jcmdCommands) {68this.isValid = isValid;69if (vmOptions == null) {70this.vmOptions = new ArrayList<>();71} else {72this.vmOptions = vmOptions;73}74this.states = states;75this.jcmdCommands = jcmdCommands;76}7778/**79* Executes separate VM a gets an OutputAnalyzer instance with the results80* of execution81*/82public List<OutputAnalyzer> execute() {83// Add class name that would be executed in a separate VM84vmOptions.add(execClass);85OutputAnalyzer output;86try (ServerSocket serverSocket = new ServerSocket(0)) {87{88// Get port test VM will connect to89int port = serverSocket.getLocalPort();90if (port == -1) {91throw new Error("Socket is not bound: " + port);92}93vmOptions.add(String.valueOf(port));94if (states != null) {95// add flag to show that there should be state map passed96vmOptions.add("states");97}98// Start separate thread to connect with test VM99new Thread(() -> connectTestVM(serverSocket)).start();100}101// Start a test VM using vm flags from @run and from vm options102String[] vmInputArgs = InputArguments.getVmInputArgs();103String[] cmds = Arrays.copyOf(vmInputArgs,104vmInputArgs.length + vmOptions.size());105System.arraycopy(vmOptions.toArray(), 0, cmds, vmInputArgs.length,106vmOptions.size());107output = ProcessTools.executeTestJvm(cmds);108} catch (Throwable thr) {109throw new Error("Execution failed: " + thr.getMessage(), thr);110}111112List<OutputAnalyzer> outputList = new ArrayList<>();113outputList.add(output);114if (jcmdOutputAnalyzers != null) {115Collections.addAll(outputList, jcmdOutputAnalyzers);116}117return outputList;118}119120/*121* Performs connection with a test VM, sends method states and performs122* JCMD operations on a test VM.123*/124private void connectTestVM(ServerSocket serverSocket) {125/*126* There are no way to prove that accept was invoked before we started127* test VM that connects to this serverSocket. Connection timeout is128* enough129*/130try (131Socket socket = serverSocket.accept();132PrintWriter pw = new PrintWriter(socket.getOutputStream(),133true);134BufferedReader in = new BufferedReader(new InputStreamReader(135socket.getInputStream()))) {136// Get pid of the executed process137int pid = Integer.parseInt(in.readLine());138Asserts.assertNE(pid, 0, "Got incorrect pid");139jcmdOutputAnalyzers = executeJCMD(pid);140if (states != null) {141// serialize and send state map142states.forEach((executable, state) -> {143pw.println("{");144pw.println(executable.toGenericString());145pw.println(state.toString());146pw.println("}");147});148} else {149pw.println();150}151} catch (IOException e) {152// hotspot process may exit because of invalid directives,153// suppress the IOException of closed socket.154if (!e.getMessage().equals("Socket closed")) {155throw new Error("Failed to write data: " + e.getMessage(), e);156}157}158}159160// Executes all diagnostic commands161protected OutputAnalyzer[] executeJCMD(int pid) {162int size = jcmdCommands.size();163OutputAnalyzer[] outputArray = new OutputAnalyzer[size];164CommandExecutor jcmdExecutor = new PidJcmdExecutor(String.valueOf(pid));165for (int i = 0; i < size; i++) {166outputArray[i] = jcmdExecutor.execute(jcmdCommands.get(i));167}168return outputArray;169}170}171172173