8333117: Remove support of remote and manual debuggee launchers
Reviewed-by: cjplummer
This commit is contained in:
parent
9ef86da5f8
commit
99e4d77aac
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -30,55 +30,15 @@ import nsk.share.jdi.ArgumentHandler;
|
|||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface defining methods to control mirror of debuggee (i.e. debugged VM).
|
* Class defining methods to control mirror of debuggee (i.e. debugged VM).
|
||||||
*/
|
*/
|
||||||
public interface Debuggee {
|
public class Debuggee extends LocalProcess {
|
||||||
|
|
||||||
/** Default prefix for log messages. */
|
/** Default prefix for log messages. */
|
||||||
public static final String LOG_PREFIX = "debuggee> ";
|
public static final String LOG_PREFIX = "debuggee> ";
|
||||||
public static final String DEBUGEE_STDOUT_LOG_PREFIX = "debuggee.stdout> ";
|
public static final String DEBUGEE_STDOUT_LOG_PREFIX = "debuggee.stdout> ";
|
||||||
public static final String DEBUGEE_STDERR_LOG_PREFIX = "debuggee.stderr> ";
|
public static final String DEBUGEE_STDERR_LOG_PREFIX = "debuggee.stderr> ";
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch debuggee.
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void launch (String[] args) throws IOException;
|
|
||||||
|
|
||||||
/** Return exit status. */
|
|
||||||
public int getStatus ();
|
|
||||||
|
|
||||||
/** Check whether the process has been terminated. */
|
|
||||||
public boolean terminated();
|
|
||||||
|
|
||||||
/** Kill the debuggee VM. */
|
|
||||||
public void killDebuggee ();
|
|
||||||
|
|
||||||
/** Wait until the debuggee VM shutdown or crash. */
|
|
||||||
public int waitForDebuggee () throws InterruptedException;
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debuggee's stdin stream. */
|
|
||||||
public OutputStream getInPipe ();
|
|
||||||
|
|
||||||
/** Get a pipe to read the debuggee's stdout stream. */
|
|
||||||
public InputStream getOutPipe ();
|
|
||||||
|
|
||||||
/** Get a pipe to read the debuggee's stderr stream. */
|
|
||||||
public InputStream getErrPipe ();
|
|
||||||
|
|
||||||
/** Redirect stdout stream to <code>Log</code> */
|
|
||||||
public void redirectStdout(Log log, String prefix);
|
|
||||||
|
|
||||||
/** Redirect stderr stream to <code>Log</code> */
|
|
||||||
public void redirectStderr(Log log, String prefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of locally launched debuggee.
|
|
||||||
*/
|
|
||||||
final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
|
||||||
|
|
||||||
private IORedirector stdoutRedirector = null;
|
private IORedirector stdoutRedirector = null;
|
||||||
private IORedirector stderrRedirector = null;
|
private IORedirector stderrRedirector = null;
|
||||||
private IORedirector stdinRedirector = null;
|
private IORedirector stdinRedirector = null;
|
||||||
@ -90,7 +50,7 @@ final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
|||||||
private Launcher launcher = null;
|
private Launcher launcher = null;
|
||||||
|
|
||||||
/** Enwrap the existing <code>VM</code> mirror. */
|
/** Enwrap the existing <code>VM</code> mirror. */
|
||||||
LocalLaunchedDebuggee (Launcher launcher) {
|
Debuggee(Launcher launcher) {
|
||||||
super();
|
super();
|
||||||
this.launcher = launcher;
|
this.launcher = launcher;
|
||||||
}
|
}
|
||||||
@ -235,70 +195,3 @@ final class LocalLaunchedDebuggee extends LocalProcess implements Debuggee {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of remotely launched debuggee.
|
|
||||||
*/
|
|
||||||
final class RemoteLaunchedDebuggee implements Debuggee {
|
|
||||||
|
|
||||||
/** Launcher that creates this debuggee. */
|
|
||||||
private Launcher launcher = null;
|
|
||||||
|
|
||||||
/** Enwrap the existing <code>VM</code> mirror. */
|
|
||||||
RemoteLaunchedDebuggee (Launcher launcher) {
|
|
||||||
super();
|
|
||||||
this.launcher = launcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch debugee on remote host via <code>Launcher</code> object.
|
|
||||||
*/
|
|
||||||
public void launch(String[] args) throws IOException {
|
|
||||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
|
||||||
launcher.display("Starting remote java process:\n" + cmdLine);
|
|
||||||
launcher.launchRemoteProcess(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return exit status of the debuggee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
return launcher.getRemoteProcessStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debuggee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
return launcher.isRemoteProcessTerminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debuggee VM. */
|
|
||||||
public void killDebuggee () {
|
|
||||||
launcher.killRemoteProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debuggee VM shutdown or crash. */
|
|
||||||
public int waitForDebuggee () {
|
|
||||||
return launcher.waitForRemoteProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debuggee's stdin stream. */
|
|
||||||
public OutputStream getInPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debuggee's stdout stream. */
|
|
||||||
public InputStream getOutPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debuggee's stderr stream. */
|
|
||||||
public InputStream getErrPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -103,52 +103,21 @@ public class Launcher extends DebugeeBinder {
|
|||||||
|
|
||||||
String[] jdbCmdArgs = makeJdbCmdLine(classToExecute);
|
String[] jdbCmdArgs = makeJdbCmdLine(classToExecute);
|
||||||
|
|
||||||
if (argumentHandler.isLaunchedLocally()) {
|
if (argumentHandler.isDefaultConnector()) {
|
||||||
|
localDefaultLaunch(jdbCmdArgs, classToExecute);
|
||||||
if (argumentHandler.isDefaultConnector()) {
|
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||||
|
localRawLaunch(jdbCmdArgs, classToExecute);
|
||||||
localDefaultLaunch(jdbCmdArgs, classToExecute);
|
} else if (argumentHandler.isLaunchingConnector()) {
|
||||||
|
localLaunch(jdbCmdArgs, classToExecute);
|
||||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
} else if (argumentHandler.isAttachingConnector()) {
|
||||||
|
localLaunchAndAttach(jdbCmdArgs, classToExecute);
|
||||||
localRawLaunch(jdbCmdArgs, classToExecute);
|
} else if (argumentHandler.isListeningConnector()) {
|
||||||
|
localLaunchAndListen(jdbCmdArgs, classToExecute);
|
||||||
} else if (argumentHandler.isLaunchingConnector()) {
|
|
||||||
|
|
||||||
localLaunch(jdbCmdArgs, classToExecute);
|
|
||||||
|
|
||||||
} else if (argumentHandler.isAttachingConnector()) {
|
|
||||||
|
|
||||||
localLaunchAndAttach(jdbCmdArgs, classToExecute);
|
|
||||||
|
|
||||||
} else if (argumentHandler.isListeningConnector()) {
|
|
||||||
|
|
||||||
localLaunchAndListen(jdbCmdArgs, classToExecute);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new TestBug("Unexpected connector type for local launch mode"
|
|
||||||
+ argumentHandler.getConnectorType());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (argumentHandler.isLaunchedRemotely()) {
|
|
||||||
|
|
||||||
connectToBindServer(classToExecute);
|
|
||||||
|
|
||||||
if (argumentHandler.isAttachingConnector()) {
|
|
||||||
|
|
||||||
remoteLaunchAndAttach(jdbCmdArgs, classToExecute);
|
|
||||||
|
|
||||||
} else if (argumentHandler.isListeningConnector()) {
|
|
||||||
|
|
||||||
remoteLaunchAndListen(jdbCmdArgs, classToExecute);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw new TestBug("Unexpected connector type for remote launch mode"
|
|
||||||
+ argumentHandler.getConnectorType());
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
throw new Failure("Unexpected launching mode: " + argumentHandler.getLaunchMode());
|
throw new TestBug("Unexpected connector type for local launch mode"
|
||||||
|
+ argumentHandler.getConnectorType());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -198,11 +167,7 @@ public class Launcher extends DebugeeBinder {
|
|||||||
if (argumentHandler.isRawLaunchingConnector()) {
|
if (argumentHandler.isRawLaunchingConnector()) {
|
||||||
|
|
||||||
if (argumentHandler.isSocketTransport()) {
|
if (argumentHandler.isSocketTransport()) {
|
||||||
if (argumentHandler.isLaunchedLocally()) {
|
connectorAddress = argumentHandler.getTransportPort();
|
||||||
connectorAddress = argumentHandler.getTransportPort();
|
|
||||||
} else {
|
|
||||||
connectorAddress = argumentHandler.getDebugeeHost() + ":" + argumentHandler.getTransportPort();
|
|
||||||
}
|
|
||||||
} else if (argumentHandler.isShmemTransport() ) {
|
} else if (argumentHandler.isShmemTransport() ) {
|
||||||
connectorAddress = argumentHandler.getTransportSharedName();
|
connectorAddress = argumentHandler.getTransportSharedName();
|
||||||
} else {
|
} else {
|
||||||
@ -247,8 +212,6 @@ public class Launcher extends DebugeeBinder {
|
|||||||
|
|
||||||
if (argumentHandler.isSocketTransport()) {
|
if (argumentHandler.isSocketTransport()) {
|
||||||
connect.append("port=" + argumentHandler.getTransportPort().trim());
|
connect.append("port=" + argumentHandler.getTransportPort().trim());
|
||||||
if (argumentHandler.isLaunchedRemotely())
|
|
||||||
connect.append(",hostname=" + argumentHandler.getDebugeeHost().trim());
|
|
||||||
} else if (argumentHandler.isShmemTransport()) {
|
} else if (argumentHandler.isShmemTransport()) {
|
||||||
connect.append("name=" + argumentHandler.getTransportSharedName().trim());
|
connect.append("name=" + argumentHandler.getTransportSharedName().trim());
|
||||||
} else {
|
} else {
|
||||||
@ -324,7 +287,7 @@ public class Launcher extends DebugeeBinder {
|
|||||||
private void localLaunchAndAttach
|
private void localLaunchAndAttach
|
||||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
||||||
|
|
||||||
debuggee = new LocalLaunchedDebuggee(this);
|
debuggee = new Debuggee(this);
|
||||||
String address = makeTransportAddress();
|
String address = makeTransportAddress();
|
||||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
||||||
debuggee.launch(javaCmdArgs);
|
debuggee.launch(javaCmdArgs);
|
||||||
@ -346,57 +309,12 @@ public class Launcher extends DebugeeBinder {
|
|||||||
String address = jdb.waitForListeningJdb();
|
String address = jdb.waitForListeningJdb();
|
||||||
display("Listening address found: " + address);
|
display("Listening address found: " + address);
|
||||||
|
|
||||||
debuggee = new LocalLaunchedDebuggee(this);
|
debuggee = new Debuggee(this);
|
||||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
||||||
debuggee.launch(javaCmdArgs);
|
debuggee.launch(javaCmdArgs);
|
||||||
|
|
||||||
// jdb.waitForPrompt(0, false);
|
// jdb.waitForPrompt(0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Run test in remote mode using attaching connector.
|
|
||||||
*/
|
|
||||||
private void remoteLaunchAndAttach
|
|
||||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
|
||||||
|
|
||||||
debuggee = new RemoteLaunchedDebuggee(this);
|
|
||||||
String address = makeTransportAddress();
|
|
||||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute, address);
|
|
||||||
try {
|
|
||||||
debuggee.launch(javaCmdArgs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new Failure("Caught exception while launching debuggee VM process:\n\t"
|
|
||||||
+ e);
|
|
||||||
};
|
|
||||||
|
|
||||||
display("Start jdb attaching to remote debuggee");
|
|
||||||
jdb = Jdb.startAttachingJdb (this, jdbCmdArgs, JDB_STARTED);
|
|
||||||
// jdb.waitForPrompt(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run test in remote mode using listening connector.
|
|
||||||
*/
|
|
||||||
private void remoteLaunchAndListen
|
|
||||||
(String[] jdbCmdArgs, String classToExecute) throws IOException {
|
|
||||||
|
|
||||||
jdb = new Jdb(this);
|
|
||||||
display("Starting jdb listening to remote debuggee");
|
|
||||||
jdb.launch(jdbCmdArgs);
|
|
||||||
String address = jdb.waitForListeningJdb();
|
|
||||||
display("Listening address found: " + address);
|
|
||||||
|
|
||||||
debuggee = new RemoteLaunchedDebuggee(this);
|
|
||||||
String[] javaCmdArgs = makeCommandLineArgs(classToExecute);
|
|
||||||
try {
|
|
||||||
debuggee.launch(javaCmdArgs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new Failure("Caught exception while launching debuggee VM process:\n\t"
|
|
||||||
+ e);
|
|
||||||
};
|
|
||||||
|
|
||||||
jdb.waitForMessage(0, JDB_STARTED);
|
|
||||||
// jdb.waitForPrompt(0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // End of Launcher
|
} // End of Launcher
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -457,18 +457,6 @@ public class ArgumentHandler extends DebugeeArgumentHandler {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (! isLaunchedLocally() && ! isDefaultDebugeeSuspendMode()) {
|
|
||||||
throw new BadOption("inconsistent options: "
|
|
||||||
+ "-debugee.launch=" + getLaunchMode()
|
|
||||||
+ " and -debugee.suspend=" + getDebugeeSuspendMode());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! isLaunchedLocally() && isLaunchingConnector()) {
|
|
||||||
throw new BadOption("inconsistent options: "
|
|
||||||
+ "-debugee.launch=" + getLaunchMode()
|
|
||||||
+ " and -connector=" + getConnectorType());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLaunchingConnector() && ! isDefaultTransport()) {
|
if (isLaunchingConnector() && ! isDefaultTransport()) {
|
||||||
throw new BadOption("inconsistent options: "
|
throw new BadOption("inconsistent options: "
|
||||||
+ "-connector=" + getConnectorType()
|
+ "-connector=" + getConnectorType()
|
||||||
|
@ -127,8 +127,7 @@ public class Binder extends DebugeeBinder {
|
|||||||
* started with launching connector.
|
* started with launching connector.
|
||||||
*/
|
*/
|
||||||
public Debugee makeLocalDebugee(Process process) {
|
public Debugee makeLocalDebugee(Process process) {
|
||||||
LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(process, this);
|
return new Debugee(process, this);
|
||||||
return debugee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,51 +188,22 @@ public class Binder extends DebugeeBinder {
|
|||||||
|
|
||||||
prepareForPipeConnection(argumentHandler);
|
prepareForPipeConnection(argumentHandler);
|
||||||
|
|
||||||
if (argumentHandler.isLaunchedLocally()) {
|
if (argumentHandler.isDefaultConnector()) {
|
||||||
|
debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
|
||||||
if (argumentHandler.isDefaultConnector()) {
|
} else if (argumentHandler.isRawLaunchingConnector()) {
|
||||||
debugee = localDefaultLaunchDebugee(vmm, classToExecute, classPath);
|
debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
|
||||||
} else if (argumentHandler.isRawLaunchingConnector()) {
|
} else if (argumentHandler.isLaunchingConnector()) {
|
||||||
debugee = localRawLaunchDebugee(vmm, classToExecute, classPath);
|
debugee = localLaunchDebugee(vmm, classToExecute, classPath);
|
||||||
} else if (argumentHandler.isLaunchingConnector()) {
|
} else if (argumentHandler.isAttachingConnector()) {
|
||||||
debugee = localLaunchDebugee(vmm, classToExecute, classPath);
|
debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
||||||
} else if (argumentHandler.isAttachingConnector()) {
|
} else if (argumentHandler.isListeningConnector()) {
|
||||||
debugee = localLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
||||||
} else if (argumentHandler.isListeningConnector()) {
|
|
||||||
debugee = localLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
|
||||||
} else {
|
|
||||||
throw new TestBug("Unexpected connector type for local debugee launch mode"
|
|
||||||
+ argumentHandler.getConnectorType());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (argumentHandler.isLaunchedRemotely()) {
|
|
||||||
|
|
||||||
connectToBindServer(classToExecute);
|
|
||||||
|
|
||||||
if (argumentHandler.isAttachingConnector()) {
|
|
||||||
debugee = remoteLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
|
||||||
} else if (argumentHandler.isListeningConnector()) {
|
|
||||||
debugee = remoteLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
|
||||||
} else {
|
|
||||||
throw new TestBug("Unexpected connector type for remote debugee launch mode"
|
|
||||||
+ argumentHandler.getConnectorType());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (argumentHandler.isLaunchedManually()) {
|
|
||||||
|
|
||||||
if (argumentHandler.isAttachingConnector()) {
|
|
||||||
debugee = manualLaunchAndAttachDebugee(vmm, classToExecute, classPath);
|
|
||||||
} else if (argumentHandler.isListeningConnector()) {
|
|
||||||
debugee = manualLaunchAndListenDebugee(vmm, classToExecute, classPath);
|
|
||||||
} else {
|
|
||||||
throw new TestBug("Unexpected connector type for manual debugee launch mode"
|
|
||||||
+ argumentHandler.getConnectorType());
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new Failure("Unexpected debugee launching mode: " + argumentHandler.getLaunchMode());
|
throw new TestBug("Unexpected connector type for local debugee launch mode"
|
||||||
|
+ argumentHandler.getConnectorType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return debugee;
|
return debugee;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,194 +456,6 @@ public class Binder extends DebugeeBinder {
|
|||||||
|
|
||||||
// -------------------------------------------------- //
|
// -------------------------------------------------- //
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
|
|
||||||
* <code>AttachingConnector</code>.
|
|
||||||
*/
|
|
||||||
private Debugee remoteLaunchAndAttachDebugee (VirtualMachineManager vmm,
|
|
||||||
String classToExecute,
|
|
||||||
String classPath) {
|
|
||||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
|
||||||
AttachingConnector connector =
|
|
||||||
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
|
|
||||||
vmm.attachingConnectors());
|
|
||||||
|
|
||||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
|
|
||||||
|
|
||||||
String address = makeTransportAddress();
|
|
||||||
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
|
|
||||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
|
||||||
|
|
||||||
display("Starting remote java process:\n\t" + javaCmdLine);
|
|
||||||
Debugee debugee = startRemoteDebugee(cmdLineArgs);
|
|
||||||
|
|
||||||
display("Attaching to debugee");
|
|
||||||
VirtualMachine vm;
|
|
||||||
IOException ioe = null;
|
|
||||||
for (int i = 0; i < CONNECT_TRIES; i++) {
|
|
||||||
try {
|
|
||||||
vm = connector.attach(arguments);
|
|
||||||
display("Debugee attached");
|
|
||||||
debugee.setupVM(vm);
|
|
||||||
return debugee;
|
|
||||||
} catch (IOException e) {
|
|
||||||
display("Attempt #" + i + " to connect to debugee VM failed:\n\t" + e);
|
|
||||||
ioe = e;
|
|
||||||
if (debugee.terminated()) {
|
|
||||||
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
|
|
||||||
} catch (InterruptedException ie) {
|
|
||||||
ie.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
|
|
||||||
+ ie);
|
|
||||||
}
|
|
||||||
} catch (IllegalConnectorArgumentsException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
|
|
||||||
+ " tries:\n\t" + ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch debugee VM remotely via <code>BindServer</code> and connect to it using
|
|
||||||
* <code>ListeningConnector</code>.
|
|
||||||
*/
|
|
||||||
private Debugee remoteLaunchAndListenDebugee (VirtualMachineManager vmm,
|
|
||||||
String classToExecute,
|
|
||||||
String classPath) {
|
|
||||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
|
||||||
ListeningConnector connector =
|
|
||||||
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
|
|
||||||
vmm.listeningConnectors());
|
|
||||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
|
|
||||||
|
|
||||||
String address = null;
|
|
||||||
try {
|
|
||||||
display("Listening for connection from debugee");
|
|
||||||
address = connector.startListening(arguments);
|
|
||||||
} catch (IllegalConnectorArgumentsException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while starting listening debugee VM:\n\t" + e);
|
|
||||||
};
|
|
||||||
|
|
||||||
String[] cmdLineArgs = makeCommandLineArgs(classToExecute, address);
|
|
||||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
|
||||||
|
|
||||||
display("Starting remote java process:\n\t" + javaCmdLine);
|
|
||||||
Debugee debugee = startRemoteDebugee(cmdLineArgs);
|
|
||||||
|
|
||||||
display("Waiting for connection from debugee");
|
|
||||||
VirtualMachine vm;
|
|
||||||
IOException ioe = null;
|
|
||||||
for (int i = 0; i < CONNECT_TRIES; i++) {
|
|
||||||
try {
|
|
||||||
vm = connector.accept(arguments);
|
|
||||||
connector.stopListening(arguments);
|
|
||||||
display("Debugee attached");
|
|
||||||
debugee.setupVM(vm);
|
|
||||||
return debugee;
|
|
||||||
} catch (IOException e) {
|
|
||||||
display("Attempt #" + i + " to listen debugee VM failed:\n\t" + e);
|
|
||||||
ioe = e;
|
|
||||||
if (debugee.terminated()) {
|
|
||||||
throw new Failure("Unable to connect to debuggee VM: VM process is terminated");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.currentThread().sleep(CONNECT_TRY_DELAY);
|
|
||||||
} catch (InterruptedException ie) {
|
|
||||||
ie.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Thread interrupted while pausing connection attempts:\n\t"
|
|
||||||
+ ie);
|
|
||||||
}
|
|
||||||
} catch (IllegalConnectorArgumentsException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Failure("Unable to connect to debugee VM after " + CONNECT_TRIES
|
|
||||||
+ " tries:\n\t" + ioe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------- //
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompt to manually launch debugee VM and connect to it using
|
|
||||||
* <code>AttachingConnector</code>.
|
|
||||||
*/
|
|
||||||
private Debugee manualLaunchAndAttachDebugee (VirtualMachineManager vmm,
|
|
||||||
String classToExecute,
|
|
||||||
String classPath) {
|
|
||||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
|
||||||
AttachingConnector connector =
|
|
||||||
(AttachingConnector) findConnector(argumentHandler.getConnectorName(),
|
|
||||||
vmm.attachingConnectors());
|
|
||||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupAttachingConnector(connector, classToExecute, classPath);
|
|
||||||
|
|
||||||
String address = makeTransportAddress();
|
|
||||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
|
||||||
|
|
||||||
display("Starting manual java process:\n\t" + javaCmdLine);
|
|
||||||
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
|
|
||||||
|
|
||||||
VirtualMachine vm;
|
|
||||||
try {
|
|
||||||
display("Attaching to debugee");
|
|
||||||
vm = connector.attach(arguments);
|
|
||||||
} catch (IllegalConnectorArgumentsException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new TestBug("Wrong connector arguments used to attach to debuggee VM:\n\t" + e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while attaching to debugee VM:\n\t" + e);
|
|
||||||
};
|
|
||||||
display("Debugee attached");
|
|
||||||
|
|
||||||
debugee.setupVM(vm);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prompt to manually launch debugee VM and connect to it using
|
|
||||||
* <code>ListeningConnector</code>.
|
|
||||||
*/
|
|
||||||
private Debugee manualLaunchAndListenDebugee (VirtualMachineManager vmm,
|
|
||||||
String classToExecute,
|
|
||||||
String classPath) {
|
|
||||||
display("Finding connector: " + argumentHandler.getConnectorName() );
|
|
||||||
ListeningConnector connector =
|
|
||||||
(ListeningConnector) findConnector(argumentHandler.getConnectorName(),
|
|
||||||
vmm.listeningConnectors());
|
|
||||||
Map<java.lang.String,? extends com.sun.jdi.connect.Connector.Argument> arguments = setupListeningConnector(connector, classToExecute, classPath);
|
|
||||||
|
|
||||||
VirtualMachine vm;
|
|
||||||
try {
|
|
||||||
display("Listening for connection from debugee");
|
|
||||||
String address = connector.startListening(arguments);
|
|
||||||
String javaCmdLine = makeCommandLineString(classToExecute, address, "\"");
|
|
||||||
display("Starting manual java process:\n\t" + javaCmdLine);
|
|
||||||
ManualLaunchedDebugee debugee = startManualDebugee(javaCmdLine);
|
|
||||||
display("Waiting for connection from debugee");
|
|
||||||
vm = connector.accept(arguments);
|
|
||||||
display("Debugee attached");
|
|
||||||
connector.stopListening(arguments);
|
|
||||||
debugee.setupVM(vm);
|
|
||||||
return debugee;
|
|
||||||
} catch (IllegalConnectorArgumentsException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new TestBug("Wrong connector arguments used to listen debuggee VM:\n\t" + e);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while listening to debugee VM:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------- //
|
// -------------------------------------------------- //
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -920,33 +702,6 @@ public class Binder extends DebugeeBinder {
|
|||||||
return makeLocalDebugee(process);
|
return makeLocalDebugee(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch remote debuggee process with specified command line arguments
|
|
||||||
* and make initial <code>Debugee</code> mirror.
|
|
||||||
*/
|
|
||||||
protected RemoteLaunchedDebugee startRemoteDebugee(String[] cmdArgs) {
|
|
||||||
try {
|
|
||||||
launchRemoteProcess(cmdArgs);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while launching remote debuggee VM process:\n\t"
|
|
||||||
+ e);
|
|
||||||
}
|
|
||||||
|
|
||||||
RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch manual debuggee process with specified command line arguments
|
|
||||||
* and make initial <code>Debugee</code> mirror.
|
|
||||||
*/
|
|
||||||
protected ManualLaunchedDebugee startManualDebugee(String cmd) {
|
|
||||||
ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
|
|
||||||
debugee.launchDebugee(cmd);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) {
|
public static String readVMStartExceptionOutput(VMStartException e, PrintStream log) {
|
||||||
StringBuffer msg = new StringBuffer();
|
StringBuffer msg = new StringBuffer();
|
||||||
try (InputStream is = e.process().getInputStream()) {
|
try (InputStream is = e.process().getInputStream()) {
|
||||||
@ -995,287 +750,4 @@ public class Binder extends DebugeeBinder {
|
|||||||
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of locally launched debugee.
|
|
||||||
*/
|
|
||||||
final class LocalLaunchedDebugee extends Debugee {
|
|
||||||
|
|
||||||
/** Enwrap the locally started VM process. */
|
|
||||||
public LocalLaunchedDebugee (Process process, Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
this.process = process;
|
|
||||||
checkTermination = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
return process.exitValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
if (process == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
int value = process.exitValue();
|
|
||||||
return true;
|
|
||||||
} catch (IllegalThreadStateException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
log.display("Killing debugee VM process");
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () throws InterruptedException {
|
|
||||||
int code = process.waitFor();
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return process.getOutputStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return process.getInputStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return process.getErrorStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of remotely launched debugee.
|
|
||||||
*/
|
|
||||||
final class RemoteLaunchedDebugee extends Debugee {
|
|
||||||
|
|
||||||
/** Enwrap the remotely started VM process. */
|
|
||||||
public RemoteLaunchedDebugee (Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
return binder.getRemoteProcessStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
return binder.isRemoteProcessTerminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
binder.killRemoteProcess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () {
|
|
||||||
return binder.waitForRemoteProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of manually launched debugee.
|
|
||||||
*/
|
|
||||||
final class ManualLaunchedDebugee extends Debugee {
|
|
||||||
/** Enwrap the manually started VM process. */
|
|
||||||
public ManualLaunchedDebugee (Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
makeInputReader();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
private int exitCode = 0;
|
|
||||||
private boolean finished = false;
|
|
||||||
private static BufferedReader bin = null;
|
|
||||||
|
|
||||||
public void launchDebugee(String commandLine) {
|
|
||||||
makeInputReader();
|
|
||||||
|
|
||||||
putMessage("Launch target VM using such command line:\n"
|
|
||||||
+ commandLine);
|
|
||||||
String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
|
|
||||||
for ( ; ; ) {
|
|
||||||
if (answer.equals("yes"))
|
|
||||||
break;
|
|
||||||
if (answer.equals("no"))
|
|
||||||
throw new Failure ("Unable to manually launch debugee VM");
|
|
||||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void makeInputReader() {
|
|
||||||
if (bin == null) {
|
|
||||||
bin = new BufferedReader(new InputStreamReader(System.in));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void destroyInputReader() {
|
|
||||||
if (bin != null) {
|
|
||||||
try {
|
|
||||||
bin.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while closing input stream:\n\t" + e);
|
|
||||||
}
|
|
||||||
bin = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void putMessage(String msg) {
|
|
||||||
System.out.println("\n>>> " + msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String askQuestion(String question, String defaultAnswer) {
|
|
||||||
try {
|
|
||||||
System.out.print("\n>>> " + question);
|
|
||||||
System.out.print(" [" + defaultAnswer + "] ");
|
|
||||||
System.out.flush();
|
|
||||||
String answer = bin.readLine();
|
|
||||||
if (answer.equals(""))
|
|
||||||
return defaultAnswer;
|
|
||||||
return answer;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while reading answer:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
if (! finished) {
|
|
||||||
throw new Failure("Unable to get status of debugee VM: process still alive");
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
return finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
putMessage("Kill launched VM");
|
|
||||||
String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
|
|
||||||
for ( ; ; ) {
|
|
||||||
if (answer.equals("yes")) {
|
|
||||||
finished = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (answer.equals("no"))
|
|
||||||
throw new Failure ("Unable to manually kill debugee VM");
|
|
||||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () {
|
|
||||||
putMessage("Wait for launched VM to exit.");
|
|
||||||
String answer = askQuestion("What is VM exit code?", "95");
|
|
||||||
for ( ; ; ) {
|
|
||||||
try {
|
|
||||||
exitCode = Integer.parseInt(answer);
|
|
||||||
break;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
answer = askQuestion("Wrong answer. Please type integer value", "95");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finished = true;
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
destroyInputReader();
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -47,7 +47,7 @@ import java.util.*;
|
|||||||
* @see Binder
|
* @see Binder
|
||||||
* @see DebugeeProcess
|
* @see DebugeeProcess
|
||||||
*/
|
*/
|
||||||
abstract public class Debugee extends DebugeeProcess {
|
public class Debugee extends DebugeeProcess {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mirror of the debugee VM. This must be initialized by every
|
* Mirror of the debugee VM. This must be initialized by every
|
||||||
@ -68,6 +68,13 @@ abstract public class Debugee extends DebugeeProcess {
|
|||||||
this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
|
this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Debugee (Process process, Binder binder) {
|
||||||
|
super(binder);
|
||||||
|
this.process = process;
|
||||||
|
this.binder = binder;
|
||||||
|
this.argumentHandler = (ArgumentHandler)binder.getArgumentHandler();
|
||||||
|
}
|
||||||
|
|
||||||
/** Setup <code>Debugee</code> object with given VM mirror. */
|
/** Setup <code>Debugee</code> object with given VM mirror. */
|
||||||
public void setupVM(VirtualMachine vm) {
|
public void setupVM(VirtualMachine vm) {
|
||||||
if (this.vm != null) {
|
if (this.vm != null) {
|
||||||
|
@ -98,13 +98,8 @@ final public class Binder extends DebugeeBinder {
|
|||||||
|
|
||||||
prepareForPipeConnection(argumentHandler);
|
prepareForPipeConnection(argumentHandler);
|
||||||
|
|
||||||
if (argumentHandler.isLaunchedRemotely()) {
|
debugee = launchDebugee(classToExecute);
|
||||||
connectToBindServer(classToExecute);
|
debugee.redirectOutput(log);
|
||||||
debugee = launchDebugee(classToExecute);
|
|
||||||
} else {
|
|
||||||
debugee = launchDebugee(classToExecute);
|
|
||||||
debugee.redirectOutput(log);
|
|
||||||
}
|
|
||||||
|
|
||||||
Transport transport = debugee.connect();
|
Transport transport = debugee.connect();
|
||||||
|
|
||||||
@ -117,334 +112,16 @@ final public class Binder extends DebugeeBinder {
|
|||||||
public Debugee launchDebugee (String classToExecute) {
|
public Debugee launchDebugee (String classToExecute) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
Debugee debugee = new Debugee(this);
|
||||||
if (argumentHandler.isLaunchedLocally()) {
|
String address = debugee.prepareTransport(argumentHandler);
|
||||||
LocalLaunchedDebugee debugee = new LocalLaunchedDebugee(this);
|
if (address == null)
|
||||||
String address = debugee.prepareTransport(argumentHandler);
|
address = makeTransportAddress();
|
||||||
if (address == null)
|
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
||||||
address = makeTransportAddress();
|
debugee.launch(argsArray);
|
||||||
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
return debugee;
|
||||||
debugee.launch(argsArray);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentHandler.isLaunchedRemotely()) {
|
|
||||||
RemoteLaunchedDebugee debugee = new RemoteLaunchedDebugee(this);
|
|
||||||
String address = debugee.prepareTransport(argumentHandler);
|
|
||||||
if (address == null)
|
|
||||||
address = makeTransportAddress();
|
|
||||||
String[] argsArray = makeCommandLineArgs(classToExecute, address);
|
|
||||||
debugee.launch(argsArray);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argumentHandler.isLaunchedManually()) {
|
|
||||||
ManualLaunchedDebugee debugee = new ManualLaunchedDebugee(this);
|
|
||||||
String address = debugee.prepareTransport(argumentHandler);
|
|
||||||
if (address == null)
|
|
||||||
address = makeTransportAddress();
|
|
||||||
String cmdLine = makeCommandLineString(classToExecute, address, "\"");
|
|
||||||
debugee.launch(cmdLine);
|
|
||||||
return debugee;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new TestBug("Unexpected launching mode: "
|
|
||||||
+ argumentHandler.getLaunchMode());
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace(log.getOutStream());
|
e.printStackTrace(log.getOutStream());
|
||||||
throw new Failure("Caught exception while launching debugee:\n\t" + e);
|
throw new Failure("Caught exception while launching debugee:\n\t" + e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of locally launched debugee.
|
|
||||||
*/
|
|
||||||
final class LocalLaunchedDebugee extends Debugee {
|
|
||||||
|
|
||||||
/** Enwrap the existing <code>VM</code> mirror. */
|
|
||||||
public LocalLaunchedDebugee (Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
checkTermination = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
public void launch(String[] args) throws IOException {
|
|
||||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
|
||||||
display("Starting java process:\n" + cmdLine);
|
|
||||||
process = binder.launchProcess(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
return process.exitValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
if (process == null)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
int value = process.exitValue();
|
|
||||||
return true;
|
|
||||||
} catch (IllegalThreadStateException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
log.display("Killing debugee VM process");
|
|
||||||
process.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () throws InterruptedException {
|
|
||||||
return process.waitFor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return process.getOutputStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return process.getInputStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return process.getErrorStream();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of remotely launched debugee.
|
|
||||||
*/
|
|
||||||
final class RemoteLaunchedDebugee extends Debugee {
|
|
||||||
|
|
||||||
/** Enwrap the existing <code>VM</code> mirror. */
|
|
||||||
public RemoteLaunchedDebugee (Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
public void launch(String[] args) throws IOException {
|
|
||||||
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
|
||||||
display("Starting remote java process:\n" + cmdLine);
|
|
||||||
binder.launchRemoteProcess(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
return binder.getRemoteProcessStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
return binder.isRemoteProcessTerminated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
log.display("Killing debugee VM process");
|
|
||||||
binder.killRemoteProcess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () {
|
|
||||||
return binder.waitForRemoteProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mirror of manually launched debugee.
|
|
||||||
*/
|
|
||||||
final class ManualLaunchedDebugee extends Debugee {
|
|
||||||
|
|
||||||
private int exitCode = 0;
|
|
||||||
private boolean finished = false;
|
|
||||||
private static BufferedReader bin = new BufferedReader(new InputStreamReader(System.in));
|
|
||||||
|
|
||||||
/** Enwrap the existing <code>VM</code> mirror. */
|
|
||||||
public ManualLaunchedDebugee (Binder binder) {
|
|
||||||
super(binder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
public void launch(String commandLine) throws IOException {
|
|
||||||
putMessage("Launch target VM using such command line:\n"
|
|
||||||
+ commandLine);
|
|
||||||
String answer = askQuestion("Has the VM successfully started? (yes/no)", "yes");
|
|
||||||
for ( ; ; ) {
|
|
||||||
if (answer.equals("yes"))
|
|
||||||
break;
|
|
||||||
if (answer.equals("no"))
|
|
||||||
throw new Failure ("Unable to manually launch debugee VM");
|
|
||||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void putMessage(String msg) {
|
|
||||||
System.out.println("\n>>> " + msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String askQuestion(String question, String defaultAnswer) {
|
|
||||||
try {
|
|
||||||
System.out.print("\n>>> " + question);
|
|
||||||
System.out.print(" [" + defaultAnswer + "] ");
|
|
||||||
System.out.flush();
|
|
||||||
String answer = bin.readLine();
|
|
||||||
if (answer.equals(""))
|
|
||||||
return defaultAnswer;
|
|
||||||
return answer;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Caught exception while reading answer:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return exit status of the debugee VM. */
|
|
||||||
public int getStatus () {
|
|
||||||
if (! terminated()) {
|
|
||||||
throw new Failure("Unable to get status of debugee VM: process still alive");
|
|
||||||
}
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
|
||||||
public boolean terminated () {
|
|
||||||
if(! finished) {
|
|
||||||
String answer = askQuestion("Has the VM exited?", "no");
|
|
||||||
for ( ; ; ) {
|
|
||||||
if (answer.equals("no"))
|
|
||||||
return false;
|
|
||||||
if (answer.equals("yes")) {
|
|
||||||
finished = true;
|
|
||||||
waitForDebugee();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return finished;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
|
||||||
protected void killDebugee () {
|
|
||||||
super.killDebugee();
|
|
||||||
if (!terminated()) {
|
|
||||||
putMessage("Kill launched VM");
|
|
||||||
String answer = askQuestion("Has the VM successfully terminated? (yes/no)", "yes");
|
|
||||||
for ( ; ; ) {
|
|
||||||
if (answer.equals("yes")) {
|
|
||||||
finished = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (answer.equals("no"))
|
|
||||||
throw new Failure ("Unable to manually kill debugee VM");
|
|
||||||
answer = askQuestion("Wrong answer. Please type yes or no", "yes");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
|
||||||
protected int waitForDebugee () {
|
|
||||||
putMessage("Wait for launched VM to exit.");
|
|
||||||
String answer = askQuestion("What is VM exit code?", "95");
|
|
||||||
for ( ; ; ) {
|
|
||||||
try {
|
|
||||||
exitCode = Integer.parseInt(answer);
|
|
||||||
break;
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
answer = askQuestion("Wrong answer. Please type integer value", "95");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finished = true;
|
|
||||||
return exitCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
|
||||||
protected OutputStream getInPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
|
||||||
protected InputStream getOutPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
|
||||||
protected InputStream getErrPipe () {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStdout(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(OutputStream out) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void redirectStderr(Log log, String prefix) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
bin.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.display("WARNING: Caught IOException while closing InputStream");
|
|
||||||
}
|
|
||||||
bin = null;
|
|
||||||
super.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -46,7 +46,7 @@ import java.io.*;
|
|||||||
* @see Transport
|
* @see Transport
|
||||||
* @see DebugeeProcess
|
* @see DebugeeProcess
|
||||||
*/
|
*/
|
||||||
abstract public class Debugee extends DebugeeProcess {
|
public class Debugee extends DebugeeProcess {
|
||||||
|
|
||||||
/** Binder that creates this debugee. */
|
/** Binder that creates this debugee. */
|
||||||
protected Binder binder = null;
|
protected Binder binder = null;
|
||||||
@ -63,6 +63,12 @@ abstract public class Debugee extends DebugeeProcess {
|
|||||||
prefix = "Debugee> ";
|
prefix = "Debugee> ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void launch(String[] args) throws IOException {
|
||||||
|
String cmdLine = ArgumentHandler.joinArguments(args, "\"");
|
||||||
|
display("Starting java process:\n" + cmdLine);
|
||||||
|
process = binder.launchProcess(args);
|
||||||
|
}
|
||||||
|
|
||||||
/** Return <code>Binder</code> of the debugee object. */
|
/** Return <code>Binder</code> of the debugee object. */
|
||||||
public Binder getBinder() {
|
public Binder getBinder() {
|
||||||
return binder;
|
return binder;
|
||||||
|
@ -57,8 +57,6 @@ import java.net.ServerSocket;
|
|||||||
* (this works only with <code>-connector=listening</code> and <code>-transport=socket</code>)
|
* (this works only with <code>-connector=listening</code> and <code>-transport=socket</code>)
|
||||||
* <li> <code>-debugee.suspend=[yes|no|default]</code> -
|
* <li> <code>-debugee.suspend=[yes|no|default]</code> -
|
||||||
* should debugee start in suspend mode or not
|
* should debugee start in suspend mode or not
|
||||||
* <li> <code>-debugee.launch=[local|remote|manual]</code> -
|
|
||||||
* launch and bind to debugee VM locally, remotely (via BindSever) or manually
|
|
||||||
* <li> <code>-debugee.vmhome=</code><<i>path</i>> -
|
* <li> <code>-debugee.vmhome=</code><<i>path</i>> -
|
||||||
* path to JDK used for launching debugee VM
|
* path to JDK used for launching debugee VM
|
||||||
* <li> <code>-debugee.vmkind=</code><<i>name</i>> -
|
* <li> <code>-debugee.vmkind=</code><<i>name</i>> -
|
||||||
@ -275,11 +273,8 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
|||||||
* @see #isDefaultDebugeeSuspendMode()
|
* @see #isDefaultDebugeeSuspendMode()
|
||||||
*/
|
*/
|
||||||
public boolean willDebugeeSuspended() {
|
public boolean willDebugeeSuspended() {
|
||||||
if (isLaunchedLocally()) {
|
String mode = getDebugeeSuspendMode();
|
||||||
String mode = getDebugeeSuspendMode();
|
return mode.equals("no");
|
||||||
return mode.equals("no");
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean pipePortInited = false;
|
private boolean pipePortInited = false;
|
||||||
@ -337,54 +332,6 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
|||||||
setOption("-", "pipe.port", value);
|
setOption("-", "pipe.port", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return debugee VM launching mode, specified by
|
|
||||||
* <code>-launch.mode</code> command line option, or
|
|
||||||
* "<i>local</i>" string by default.
|
|
||||||
*
|
|
||||||
* Possible values for this option are:
|
|
||||||
* <ul>
|
|
||||||
* <li> "<code>local</code>"
|
|
||||||
* <li> "<code>remote</code>"
|
|
||||||
* <li> "<code>manual</code>"
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @see #isLaunchedLocally()
|
|
||||||
* @see #isLaunchedRemotely()
|
|
||||||
* @see #isLaunchedManually()
|
|
||||||
* @see #setRawArguments(String[])
|
|
||||||
*/
|
|
||||||
public String getLaunchMode() {
|
|
||||||
return options.getProperty("debugee.launch", "local");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return <i>true</i> if debugee should be launched locally.
|
|
||||||
*
|
|
||||||
* @see #getLaunchMode()
|
|
||||||
*/
|
|
||||||
public boolean isLaunchedLocally() {
|
|
||||||
return getLaunchMode().equals("local");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return <i>true</i> if debugee should be launched remotely via
|
|
||||||
* BindServer.
|
|
||||||
*
|
|
||||||
* @see #getLaunchMode()
|
|
||||||
*/
|
|
||||||
public boolean isLaunchedRemotely() {
|
|
||||||
return getLaunchMode().equals("remote");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return <i>true</i> if debugee should be launched manually by user.
|
|
||||||
*
|
|
||||||
* @see #getLaunchMode()
|
|
||||||
*/
|
|
||||||
public boolean isLaunchedManually() {
|
|
||||||
return getLaunchMode().equals("manual");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return additional options for launching debugee VM, specified by
|
* Return additional options for launching debugee VM, specified by
|
||||||
@ -710,9 +657,7 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// option with any nonempty string value
|
// option with any nonempty string value
|
||||||
if (option.equals("test.host")
|
if (option.equals("debugee.vmkind")
|
||||||
|| option.equals("debugee.host")
|
|
||||||
|| option.equals("debugee.vmkind")
|
|
||||||
|| option.equals("debugee.vmhome")
|
|| option.equals("debugee.vmhome")
|
||||||
|| option.equals("transport.shname")) {
|
|| option.equals("transport.shname")) {
|
||||||
if (value.length() <= 0) {
|
if (value.length() <= 0) {
|
||||||
@ -748,14 +693,10 @@ public class DebugeeArgumentHandler extends ArgumentParser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option.equals("debugee.launch")) {
|
if (option.equals("debugee.launch")
|
||||||
if ((!value.equals("local"))
|
|| option.equals("debugee.host")
|
||||||
&& (!value.equals("remote"))
|
|| option.equals("test.host")) {
|
||||||
&& (!value.equals("manual"))) {
|
throw new RuntimeException("option " + option + " is not supported.");
|
||||||
throw new BadOption(option + ": must be one of: "
|
|
||||||
+ "local, remote, manual " + value);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (option.equals("jvmdi.strict")) {
|
if (option.equals("jvmdi.strict")) {
|
||||||
|
@ -35,15 +35,6 @@ import java.util.*;
|
|||||||
* debuggee VM and to make connection to it using JDI connector or
|
* debuggee VM and to make connection to it using JDI connector or
|
||||||
* JDWP transport.
|
* JDWP transport.
|
||||||
* <p>
|
* <p>
|
||||||
* The present version of <code>Binder</code> allows
|
|
||||||
* to launch debuggee VM either on local machine (<i>local</i> launch mode),
|
|
||||||
* or on remote host using <code>BindServer</code> utility
|
|
||||||
* (<i>remote</i> launch mode). Also there is an ability to launch
|
|
||||||
* debuggee VM manually as a separate process on local or remote machine
|
|
||||||
* (<i>manual</i> launch mode), which is usefull for debugging.
|
|
||||||
* All these launching modes are specified by command line option
|
|
||||||
* <code>-debugee.launch</code> recognized by <code>DebugeeArgumentHandler</code>.
|
|
||||||
* <p>
|
|
||||||
* <code>Binder</code> also makes it possible to establish TCP/IP
|
* <code>Binder</code> also makes it possible to establish TCP/IP
|
||||||
* connection between debugger and debuggee throw <code>IOPipe</code>
|
* connection between debugger and debuggee throw <code>IOPipe</code>
|
||||||
* object. This connection allows debugger to communicate with debuggee
|
* object. This connection allows debugger to communicate with debuggee
|
||||||
@ -105,8 +96,6 @@ public class DebugeeBinder extends Log.Logger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------------------------------- //
|
// -------------------------------------------------- //
|
||||||
|
|
||||||
private BindServerListener bindServerListener = null;
|
|
||||||
private ServerSocket pipeServerSocket = null;
|
private ServerSocket pipeServerSocket = null;
|
||||||
|
|
||||||
// -------------------------------------------------- //
|
// -------------------------------------------------- //
|
||||||
@ -386,356 +375,12 @@ public class DebugeeBinder extends Log.Logger {
|
|||||||
return makeCommandLineArgs(classToExecute, makeTransportAddress());
|
return makeCommandLineArgs(classToExecute, makeTransportAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Make connection to remote BindServer and start BindServerListener thread.
|
|
||||||
*
|
|
||||||
* @throws IOException if I/O error occured while connecting
|
|
||||||
*/
|
|
||||||
public void connectToBindServer(String taskID) {
|
|
||||||
if (bindServerListener != null) {
|
|
||||||
throw new Failure("Connection to BindServer already exists");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
bindServerListener = new BindServerListener(this);
|
|
||||||
bindServerListener.setDaemon(true);
|
|
||||||
bindServerListener.connect(taskID);
|
|
||||||
bindServerListener.start();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(getOutStream());
|
|
||||||
throw new Failure("Caught exception while connecting to BindServer:\n\t" + e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Split string into list of substrings using specified separator.
|
|
||||||
*/
|
|
||||||
private static String[] splitString(String givenString, String separator) {
|
|
||||||
Vector<String> tmpList = new Vector<String>();
|
|
||||||
StringTokenizer tokenizer = new StringTokenizer(givenString, separator);
|
|
||||||
while(tokenizer.hasMoreTokens()) {
|
|
||||||
tmpList.add(tokenizer.nextToken());
|
|
||||||
}
|
|
||||||
String[] list = new String[tmpList.size()];
|
|
||||||
for (int i = 0; i < tmpList.size(); i++) {
|
|
||||||
list[i] = tmpList.elementAt(i);
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send command to remote <code>BindServer</code> and receive reply.
|
|
||||||
*
|
|
||||||
* @throws IOException if I/O error occured while launching process
|
|
||||||
*/
|
|
||||||
public synchronized Object sendRemoteCommand(Object command) {
|
|
||||||
try {
|
|
||||||
bindServerListener.sendCommand(command);
|
|
||||||
Object reply = bindServerListener.getReply();
|
|
||||||
return reply;
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace(log.getOutStream());
|
|
||||||
throw new Failure("Unexpected exception while sending command to BindServer:\n\t"
|
|
||||||
+ e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch remote process using request to <code>BindServer</code>.
|
|
||||||
*
|
|
||||||
* @throws IOException if I/O error occured
|
|
||||||
*/
|
|
||||||
public void launchRemoteProcess(String[] args) throws IOException {
|
|
||||||
String pathSeparator = System.getProperty("path.separator");
|
|
||||||
BindServer.LaunchDebugee command =
|
|
||||||
new BindServer.LaunchDebugee(args,
|
|
||||||
System.getProperty("file.separator"),
|
|
||||||
System.getProperty("user.dir"),
|
|
||||||
splitString(System.getProperty("java.library.path"), pathSeparator),
|
|
||||||
splitString(System.getProperty("java.class.path"), pathSeparator),
|
|
||||||
splitString(System.getProperty("java.library.path"), pathSeparator));
|
|
||||||
|
|
||||||
Object reply = sendRemoteCommand(command);
|
|
||||||
if (reply instanceof BindServer.OK) {
|
|
||||||
// do nothing
|
|
||||||
} else if (reply instanceof BindServer.RequestFailed) {
|
|
||||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
|
||||||
throw new Failure("BindServer error: " + castedReply.reason);
|
|
||||||
} else {
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return exit status of the remotely launched process
|
|
||||||
* using request to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public int getRemoteProcessStatus () {
|
|
||||||
Object reply = sendRemoteCommand(new BindServer.DebugeeExitCode());
|
|
||||||
if (reply instanceof BindServer.OK) {
|
|
||||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
|
||||||
return (int)castedReply.info;
|
|
||||||
} else if (reply instanceof BindServer.CaughtException) {
|
|
||||||
BindServer.CaughtException castedReply = (BindServer.CaughtException)reply;
|
|
||||||
throw new IllegalThreadStateException(castedReply.reason);
|
|
||||||
} else if (reply instanceof BindServer.RequestFailed) {
|
|
||||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
|
||||||
throw new Failure("BindServer error: " + castedReply.reason);
|
|
||||||
} else {
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether the remotely launched process has been terminated
|
|
||||||
* using request to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public boolean isRemoteProcessTerminated () {
|
|
||||||
try {
|
|
||||||
int value = getRemoteProcessStatus();
|
|
||||||
return true;
|
|
||||||
} catch (IllegalThreadStateException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------- //
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kill the remotely launched process
|
|
||||||
* using request to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public void killRemoteProcess () {
|
|
||||||
Object reply = sendRemoteCommand(new BindServer.KillDebugee());
|
|
||||||
if (reply instanceof BindServer.OK) {
|
|
||||||
return;
|
|
||||||
} else if (reply instanceof BindServer.RequestFailed) {
|
|
||||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
|
||||||
throw new Failure("BindServer error: " + castedReply.reason);
|
|
||||||
} else {
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait until the remotely launched process exits or crashes
|
|
||||||
* using request to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public int waitForRemoteProcess () {
|
|
||||||
|
|
||||||
Object reply = sendRemoteCommand(new BindServer.WaitForDebugee(0));
|
|
||||||
if (reply instanceof BindServer.OK) {
|
|
||||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
|
||||||
return (int)castedReply.info;
|
|
||||||
} else if (reply instanceof BindServer.RequestFailed) {
|
|
||||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
|
||||||
throw new Failure("BindServer error: " + castedReply.reason);
|
|
||||||
} else {
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close binder by closing all started threads.
|
* Close binder by closing all started threads.
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
if (bindServerListener != null) {
|
|
||||||
bindServerListener.close();
|
|
||||||
}
|
|
||||||
closePipeServerSocket();
|
closePipeServerSocket();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Separate thread for listening connection from <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
private class BindServerListener extends Thread {
|
|
||||||
private SocketConnection connection = null;
|
|
||||||
private Log.Logger logger = null;
|
|
||||||
|
|
||||||
/** List of received responses from <code>BindServer</code>. */
|
|
||||||
private LinkedList<BindServer.Response> replies = new LinkedList<BindServer.Response>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make thread.
|
|
||||||
*/
|
|
||||||
public BindServerListener(Log.Logger logger) {
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Establish connection to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public void connect(String taskID) throws IOException {
|
|
||||||
String host = argumentHandler.getDebugeeHost();
|
|
||||||
int port = argumentHandler.getBindPortNumber();
|
|
||||||
display("Connecting to BindServer: " + host + ":" + port);
|
|
||||||
connection = new SocketConnection(logger, "BindServer");
|
|
||||||
// connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT);
|
|
||||||
connection.attach(host, port);
|
|
||||||
handshake(taskID);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive OK(version) from BindServer and check received version number.
|
|
||||||
*/
|
|
||||||
private void handshake(String taskID) {
|
|
||||||
// receive OK(version)
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Waiting for initial OK(version) from BindServer");
|
|
||||||
Object reply = connection.readObject();
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Got initial OK(version) from BindServer: " + reply);
|
|
||||||
if (reply instanceof BindServer.RequestFailed) {
|
|
||||||
BindServer.RequestFailed castedReply = (BindServer.RequestFailed)reply;
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Reply is RequestFailed: throw Failure");
|
|
||||||
throw new Failure("BindServer error: " + castedReply.reason);
|
|
||||||
} else if (reply instanceof BindServer.OK) {
|
|
||||||
BindServer.OK castedReply = (BindServer.OK)reply;
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Reply is OK: check BindServer version");
|
|
||||||
if (castedReply.info != BindServer.VERSION) {
|
|
||||||
throw new Failure("Wrong version of BindServer: " + castedReply.info
|
|
||||||
+ " (expected: " + BindServer.VERSION + ")");
|
|
||||||
}
|
|
||||||
display("Connected to BindServer: version " + castedReply.info);
|
|
||||||
} else {
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Reply is unknown: throw Failure");
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send TaskID(id)
|
|
||||||
try {
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Sending TaskID(id) to BindServer");
|
|
||||||
sendCommand(new BindServer.TaskID(taskID));
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Sent TaskID(id) to BindServer");
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new Failure("Caught IOException while sending TaskID(id) to BindServer:\n\t"
|
|
||||||
+ e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if thread is connected to <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public boolean isConnected() {
|
|
||||||
return (connection != null && connection.isConnected());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a command to </code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public synchronized void sendCommand(Object command) throws IOException {
|
|
||||||
connection.writeObject(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive response from <code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public Object getReply() {
|
|
||||||
synchronized (replies) {
|
|
||||||
while (replies.isEmpty()) {
|
|
||||||
if (!isConnected()) {
|
|
||||||
throw new Failure("No reply from BindServer: connection lost");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
replies.wait(TRY_DELAY);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace(getOutStream());
|
|
||||||
throw new Failure("Thread interrupted while waiting for reply from BindServer:\n\t"
|
|
||||||
+ e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Object reply = replies.removeFirst();
|
|
||||||
if (reply == null) {
|
|
||||||
throw new Failure("No reply from BindServer: connection lost");
|
|
||||||
}
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add response object to the list of received responses.
|
|
||||||
*/
|
|
||||||
private void addReply(BindServer.Response reply) {
|
|
||||||
synchronized (replies) {
|
|
||||||
replies.add(reply);
|
|
||||||
replies.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read packets from <code>BindServer<code> connection and
|
|
||||||
* notify waiting thread if response or IOPipe message received.
|
|
||||||
* Received lines of redirected streams are put into log.
|
|
||||||
*/
|
|
||||||
public void run() {
|
|
||||||
trace(TRACE_LEVEL_THREADS, "BindServerListener thread started");
|
|
||||||
try {
|
|
||||||
for (;;) {
|
|
||||||
Object reply = connection.readObject();
|
|
||||||
if (reply == null) {
|
|
||||||
break;
|
|
||||||
} else if (reply instanceof BindServer.Disconnect) {
|
|
||||||
reply = null;
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Packet is Disconnect: close connection");
|
|
||||||
break;
|
|
||||||
} else if (reply instanceof BindServer.RedirectedStream) {
|
|
||||||
BindServer.RedirectedStream castedReply = (BindServer.RedirectedStream)reply;
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Packet is RedirectedStream: put message into log");
|
|
||||||
log.println(castedReply.line);
|
|
||||||
} else if (reply instanceof BindServer.Response) {
|
|
||||||
BindServer.Response castedReply = (BindServer.Response)reply;
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Packet is reply: notify all threads waiting for reply");
|
|
||||||
addReply(castedReply);
|
|
||||||
} else {
|
|
||||||
trace(TRACE_LEVEL_ACTIONS, "Packet is unknown: throw Failure");
|
|
||||||
throw new Failure("Wrong reply from BindServer: " + reply);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace(getOutStream());
|
|
||||||
complain("Caught exception while reading packets from BindServer:\n\t" + e);
|
|
||||||
} finally {
|
|
||||||
closeConnection();
|
|
||||||
addReply(null);
|
|
||||||
trace(TRACE_LEVEL_THREADS, "BindServerListener thread finished");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send Disconnect command to </code>BindServer</code>.
|
|
||||||
*/
|
|
||||||
public void disconnect() {
|
|
||||||
if (connection == null) return;
|
|
||||||
try {
|
|
||||||
sendCommand(new BindServer.Disconnect());
|
|
||||||
} catch (IOException e) {
|
|
||||||
display("Caught IOException while requesting disconnection with BindServer");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close socket connection.
|
|
||||||
*/
|
|
||||||
public void closeConnection() {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait for thread finished in the specified timeout or interrupt it.
|
|
||||||
*/
|
|
||||||
public void waitForThread(long millis) {
|
|
||||||
DebugeeBinder.waitForThread(this, millis, logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close this thread by waiting for it finishes or interrupt it
|
|
||||||
* and close socket connection.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
disconnect();
|
|
||||||
waitForThread(DebugeeBinder.THREAD_TIMEOUT);
|
|
||||||
closeConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // BindServerListener
|
|
||||||
|
|
||||||
} // DebugeeBinder
|
} // DebugeeBinder
|
||||||
|
@ -74,8 +74,8 @@ abstract public class DebugeeProcess {
|
|||||||
/** Argument handler from binder. */
|
/** Argument handler from binder. */
|
||||||
protected DebugeeArgumentHandler argumentHandler = null;
|
protected DebugeeArgumentHandler argumentHandler = null;
|
||||||
|
|
||||||
/** Need or not to check debuggee process termination at exit. */
|
/** Need or not to check debuggee process termination. */
|
||||||
protected boolean checkTermination = false;
|
private boolean checkTermination = true;
|
||||||
|
|
||||||
/** Debugee VM process or <i>null</i> if not available. */
|
/** Debugee VM process or <i>null</i> if not available. */
|
||||||
protected Process process = null;
|
protected Process process = null;
|
||||||
@ -164,26 +164,50 @@ abstract public class DebugeeProcess {
|
|||||||
// --------------------------------------------------- //
|
// --------------------------------------------------- //
|
||||||
|
|
||||||
/** Wait until the debugee VM shutdown or crash. */
|
/** Wait until the debugee VM shutdown or crash. */
|
||||||
abstract protected int waitForDebugee () throws InterruptedException;
|
protected int waitForDebugee() throws InterruptedException {
|
||||||
|
return process.waitFor();
|
||||||
|
}
|
||||||
|
|
||||||
/** Kill the debugee VM. */
|
/** Kill the debugee VM. */
|
||||||
abstract protected void killDebugee ();
|
protected void killDebugee() {
|
||||||
|
if (!terminated()) {
|
||||||
|
log.display("Killing debugee VM process");
|
||||||
|
process.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Check whether the debugee VM has been terminated. */
|
/** Check whether the debugee VM has been terminated. */
|
||||||
abstract public boolean terminated ();
|
public boolean terminated() {
|
||||||
|
if (process == null)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int value = process.exitValue();
|
||||||
|
return true;
|
||||||
|
} catch (IllegalThreadStateException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Return the debugee VM exit status. */
|
/** Return the debugee VM exit status. */
|
||||||
abstract public int getStatus ();
|
public int getStatus() {
|
||||||
|
return process.exitValue();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a pipe to write to the debugee's stdin stream. */
|
/** Get a pipe to write to the debugee's stdin stream. */
|
||||||
abstract protected OutputStream getInPipe ();
|
protected OutputStream getInPipe() {
|
||||||
|
return process.getOutputStream();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stdout stream. */
|
/** Get a pipe to read the debugee's stdout stream. */
|
||||||
abstract protected InputStream getOutPipe ();
|
protected InputStream getOutPipe() {
|
||||||
|
return process.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
/** Get a pipe to read the debugee's stderr stream. */
|
/** Get a pipe to read the debugee's stderr stream. */
|
||||||
abstract protected InputStream getErrPipe ();
|
protected InputStream getErrPipe() {
|
||||||
|
return process.getErrorStream();
|
||||||
|
}
|
||||||
// --------------------------------------------------- //
|
// --------------------------------------------------- //
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user