Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/share/jdwp/Binder.java
41162 views
/*1* Copyright (c) 2001, 2018, 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 nsk.share.jdwp;2425import nsk.share.*;26import nsk.share.jpda.*;2728import java.io.*;2930/**31* This class provides debugger with connection to debugee VM32* using JDWP protocol.33* <p>34* This class provides abilities to launch and bind to debugee VM35* as described for base <code>DebugeeBinder</code> class,36* using raw JDWP protocol.37* <p>38* When <code>Binder</code> is asked to bind to debugee by invoking39* <code>bindToBebugee()</code> method it launches process40* with debugee VM and makes connection to it using JDWP transport41* corresponding to value of command line options <code>-connector</code>42* and <code>-transport</code>.43* After debugee is launched and connection is established44* <code>Binder</code> constructs <code>Debugee</code> object,45* that provides abilities to interact with debugee VM.46*47* @see Debugee48* @see DebugeeBinder49*/50final public class Binder extends DebugeeBinder {5152/**53* Default message prefix for <code>Binder</code> object.54*/55public static final String LOG_PREFIX = "binder> ";5657/**58* Get version string.59*/60public static String getVersion () {61return "@(#)Binder.java %I% %E%";62}6364// -------------------------------------------------- //6566/**67* Handler of command line arguments.68*/69private ArgumentHandler argumentHandler = null;7071/**72* Return <code>argumentHandler</code> of this binder.73*/74public ArgumentHandler getArgumentHandler() {75return argumentHandler;76}7778// -------------------------------------------------- //7980/**81* Make new <code>Binder</code> object with specified82* <code>argumentHandler</code> and <code>log</code>.83*/84public Binder (ArgumentHandler argumentHandler, Log log) {85super(argumentHandler, log);86this.argumentHandler = argumentHandler;87}8889// -------------------------------------------------- //9091/**92* Start debugee VM and establish JDWP connection to it.93*/94public Debugee bindToDebugee (String classToExecute) {9596Debugee debugee = null;9798prepareForPipeConnection(argumentHandler);99100if (argumentHandler.isLaunchedRemotely()) {101connectToBindServer(classToExecute);102debugee = launchDebugee(classToExecute);103} else {104debugee = launchDebugee(classToExecute);105debugee.redirectOutput(log);106}107108Finalizer finalizer = new Finalizer(debugee);109finalizer.activate();110111Transport transport = debugee.connect();112113return debugee;114}115116/**117* Launch debugee VM for specified class.118*/119public Debugee launchDebugee (String classToExecute) {120121try {122123if (argumentHandler.isLaunchedLocally()) {124LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(this);125String address = debugee.prepareTransport(argumentHandler);126if (address == null)127address = makeTransportAddress();128String[] argsArray = makeCommandLineArgs(classToExecute, address);129debugee.launch(argsArray);130return debugee;131}132133if (argumentHandler.isLaunchedRemotely()) {134RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);135String address = debugee.prepareTransport(argumentHandler);136if (address == null)137address = makeTransportAddress();138String[] argsArray = makeCommandLineArgs(classToExecute, address);139debugee.launch(argsArray);140return debugee;141}142143if (argumentHandler.isLaunchedManually()) {144ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);145String address = debugee.prepareTransport(argumentHandler);146if (address == null)147address = makeTransportAddress();148String cmdLine = makeCommandLineString(classToExecute, address, "\"");149debugee.launch(cmdLine);150return debugee;151}152153throw new TestBug("Unexpected launching mode: "154+ argumentHandler.getLaunchMode());155} catch (IOException e) {156e.printStackTrace(log.getOutStream());157throw new Failure("Caught exception while launching debugee:\n\t" + e);158}159}160161}162163/**164* Mirror of locally launched debugee.165*/166final class LocalLaunchedDebugee extends Debugee {167168/** Enwrap the existing <code>VM</code> mirror. */169public LocalLaunchedDebugee (Binder binder) {170super(binder);171checkTermination = true;172}173174// ---------------------------------------------- //175176public void launch(String[] args) throws IOException {177String cmdLine = ArgumentHandler.joinArguments(args, "\"");178display("Starting java process:\n" + cmdLine);179process = binder.launchProcess(args);180}181182/** Return exit status of the debugee VM. */183public int getStatus () {184return process.exitValue();185}186187/** Check whether the debugee VM has been terminated. */188public boolean terminated () {189if (process == null)190return true;191192try {193int value = process.exitValue();194return true;195} catch (IllegalThreadStateException e) {196return false;197}198}199200// ---------------------------------------------- //201202/** Kill the debugee VM. */203protected void killDebugee () {204super.killDebugee();205if (!terminated()) {206log.display("Killing debugee VM process");207process.destroy();208}209}210211/** Wait until the debugee VM shutdown or crash. */212protected int waitForDebugee () throws InterruptedException {213return process.waitFor();214}215216/** Get a pipe to write to the debugee's stdin stream. */217protected OutputStream getInPipe () {218return process.getOutputStream();219}220221/** Get a pipe to read the debugee's stdout stream. */222protected InputStream getOutPipe () {223return process.getInputStream();224}225226/** Get a pipe to read the debugee's stderr stream. */227protected InputStream getErrPipe () {228return process.getErrorStream();229}230}231232233/**234* Mirror of remotely launched debugee.235*/236final class RemoteLaunchedDebugee extends Debugee {237238/** Enwrap the existing <code>VM</code> mirror. */239public RemoteLaunchedDebugee (Binder binder) {240super(binder);241}242243// ---------------------------------------------- //244245public void launch(String[] args) throws IOException {246String cmdLine = ArgumentHandler.joinArguments(args, "\"");247display("Starting remote java process:\n" + cmdLine);248binder.launchRemoteProcess(args);249}250251/** Return exit status of the debugee VM. */252public int getStatus () {253return binder.getRemoteProcessStatus();254}255256/** Check whether the debugee VM has been terminated. */257public boolean terminated () {258return binder.isRemoteProcessTerminated();259}260261// ---------------------------------------------- //262263/** Kill the debugee VM. */264protected void killDebugee () {265super.killDebugee();266if (!terminated()) {267log.display("Killing debugee VM process");268binder.killRemoteProcess();269}270}271272/** Wait until the debugee VM shutdown or crash. */273protected int waitForDebugee () {274return binder.waitForRemoteProcess();275}276277/** Get a pipe to write to the debugee's stdin stream. */278protected OutputStream getInPipe () {279return null;280}281282/** Get a pipe to read the debugee's stdout stream. */283protected InputStream getOutPipe () {284return null;285}286287/** Get a pipe to read the debugee's stderr stream. */288protected InputStream getErrPipe () {289return null;290}291292public void redirectStdout(OutputStream out) {293}294295public void redirectStdout(Log log, String prefix) {296}297298public void redirectStderr(OutputStream out) {299}300301public void redirectStderr(Log log, String prefix) {302}303}304305306/**307* Mirror of manually launched debugee.308*/309final class ManualLaunchedDebugee extends Debugee {310311private int exitCode = 0;312private boolean finished = false;313private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));314315/** Enwrap the existing <code>VM</code> mirror. */316public ManualLaunchedDebugee (Binder binder) {317super(binder);318}319320// ---------------------------------------------- //321322public void launch(String commandLine) throws IOException {323putMessage("Launch target VM using such command line:\n"324+ commandLine);325String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");326for ( ; ; ) {327if (answer.equals("yes"))328break;329if (answer.equals("no"))330throw new Failure ("Unable to manually launch debugee VM");331answer = askQuestion("Wrong answer. Please type yes or no", "yes");332}333}334335private void putMessage(String msg) {336System.out.println("\n>>> " + msg);337}338339private String askQuestion(String question, String defaultAnswer) {340try {341System.out.print("\n>>> " + question);342System.out.print(" [" + defaultAnswer + "] ");343System.out.flush();344String answer = bin.readLine();345if (answer.equals(""))346return defaultAnswer;347return answer;348} catch (IOException e) {349e.printStackTrace(log.getOutStream());350throw new Failure("Caught exception while reading answer:\n\t" + e);351}352}353354/** Return exit status of the debugee VM. */355public int getStatus () {356if (! terminated()) {357throw new Failure("Unable to get status of debugee VM: process still alive");358}359return exitCode;360}361362/** Check whether the debugee VM has been terminated. */363public boolean terminated () {364if(! finished) {365String answer = askQuestion("Has the VM exited?", "no");366for ( ; ; ) {367if (answer.equals("no"))368return false;369if (answer.equals("yes")) {370finished = true;371waitForDebugee();372break;373}374answer = askQuestion("Wrong answer. Please type yes or no", "yes");375}376}377return finished;378}379380// ---------------------------------------------- //381382/** Kill the debugee VM. */383protected void killDebugee () {384super.killDebugee();385if (!terminated()) {386putMessage("Kill launched VM");387String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");388for ( ; ; ) {389if (answer.equals("yes")) {390finished = true;391break;392}393if (answer.equals("no"))394throw new Failure ("Unable to manually kill debugee VM");395answer = askQuestion("Wrong answer. Please type yes or no", "yes");396}397}398}399400/** Wait until the debugee VM shutdown or crash. */401protected int waitForDebugee () {402putMessage("Wait for launched VM to exit.");403String answer = askQuestion("What is VM exit code?", "95");404for ( ; ; ) {405try {406exitCode = Integer.parseInt(answer);407break;408} catch (NumberFormatException e) {409answer = askQuestion("Wrong answer. Please type integer value", "95");410}411}412finished = true;413return exitCode;414}415416/** Get a pipe to write to the debugee's stdin stream. */417protected OutputStream getInPipe () {418return null;419}420421/** Get a pipe to read the debugee's stdout stream. */422protected InputStream getOutPipe () {423return null;424}425426/** Get a pipe to read the debugee's stderr stream. */427protected InputStream getErrPipe () {428return null;429}430431public void redirectStdout(OutputStream out) {432}433434public void redirectStdout(Log log, String prefix) {435}436437public void redirectStderr(OutputStream out) {438}439440public void redirectStderr(Log log, String prefix) {441}442443public void close() {444try {445bin.close();446} catch (IOException e) {447log.display("WARNING: Caught IOException while closing InputStream");448}449bin = null;450super.close();451}452}453454455