blob: d1da9cfbaaff4af6ac6b44c2fb722b58db9fe855 [file] [log] [blame]
/*
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
package sun.jvm.hotspot.tools;
import java.io.PrintStream;
import sun.jvm.hotspot.HotSpotAgent;
import sun.jvm.hotspot.debugger.DebuggerException;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.runtime.VM;
// generic command line or GUI tool.
// override run & code main as shown below.
public abstract class Tool implements Runnable {
private HotSpotAgent agent;
private JVMDebugger jvmDebugger;
private int debugeeType;
// debugeeType is one of constants below
protected static final int DEBUGEE_PID = 0;
protected static final int DEBUGEE_CORE = 1;
protected static final int DEBUGEE_REMOTE = 2;
public Tool() {
}
public Tool(JVMDebugger d) {
jvmDebugger = d;
}
public String getName() {
return getClass().getName();
}
protected boolean needsJavaPrefix() {
return true;
}
protected void setAgent(HotSpotAgent a) {
agent = a;
}
protected void setDebugeeType(int dt) {
debugeeType = dt;
}
protected HotSpotAgent getAgent() {
return agent;
}
protected int getDebugeeType() {
return debugeeType;
}
protected void printUsage() {
String name = null;
if (needsJavaPrefix()) {
name = "java " + getName();
} else {
name = getName();
}
System.out.println("Usage: " + name + " [option] <pid>");
System.out.println("\t\t(to connect to a live java process)");
System.out.println(" or " + name + " [option] <executable> <core>");
System.out.println("\t\t(to connect to a core file)");
System.out.println(" or " + name + " [option] [server_id@]<remote server IP or hostname>");
System.out.println("\t\t(to connect to a remote debug server)");
System.out.println();
System.out.println("where option must be one of:");
printFlagsUsage();
}
protected void printFlagsUsage() {
System.out.println(" -h | -help\tto print this help message");
}
protected void usage() {
printUsage();
}
/*
Derived class main should be of the following form:
public static void main(String[] args) {
<derived class> obj = new <derived class>;
obj.execute(args);
}
*/
protected void execute(String[] args) {
int returnStatus = 1;
try {
returnStatus = start(args);
} finally {
stop();
}
// Exit with 0 or 1
System.exit(returnStatus);
}
public void stop() {
if (agent != null) {
agent.detach();
}
}
private int start(String[] args) {
if ((args.length < 1) || (args.length > 2)) {
usage();
return 1;
}
// Attempt to handle -h or -help or some invalid flag
if (args[0].startsWith("-h")) {
usage();
return 0;
} else if (args[0].startsWith("-")) {
usage();
return 1;
}
PrintStream err = System.err;
PrintStream out = System.out;
int pid = 0;
String coreFileName = null;
String executableName = null;
String remoteServer = null;
switch (args.length) {
case 1:
try {
pid = Integer.parseInt(args[0]);
debugeeType = DEBUGEE_PID;
} catch (NumberFormatException e) {
// try remote server
remoteServer = args[0];
debugeeType = DEBUGEE_REMOTE;
}
break;
case 2:
executableName = args[0];
coreFileName = args[1];
debugeeType = DEBUGEE_CORE;
break;
default:
usage();
return 1;
}
agent = new HotSpotAgent();
try {
switch (debugeeType) {
case DEBUGEE_PID:
out.println("Attaching to process ID " + pid + ", please wait...");
agent.attach(pid);
break;
case DEBUGEE_CORE:
out.println("Attaching to core " + coreFileName +
" from executable " + executableName + ", please wait...");
agent.attach(executableName, coreFileName);
break;
case DEBUGEE_REMOTE:
out.println("Attaching to remote server " + remoteServer + ", please wait...");
agent.attach(remoteServer);
break;
}
}
catch (DebuggerException e) {
switch (debugeeType) {
case DEBUGEE_PID:
err.print("Error attaching to process: ");
break;
case DEBUGEE_CORE:
err.print("Error attaching to core file: ");
break;
case DEBUGEE_REMOTE:
err.print("Error attaching to remote server: ");
break;
}
if (e.getMessage() != null) {
err.println(e.getMessage());
e.printStackTrace();
}
err.println();
return 1;
}
out.println("Debugger attached successfully.");
startInternal();
return 0;
}
// When using an existing JVMDebugger.
public void start() {
if (jvmDebugger == null) {
throw new RuntimeException("Tool.start() called with no JVMDebugger set.");
}
agent = new HotSpotAgent();
agent.attach(jvmDebugger);
startInternal();
}
// Remains of the start mechanism, common to both start methods.
private void startInternal() {
PrintStream out = System.out;
VM vm = VM.getVM();
if (vm.isCore()) {
out.println("Core build detected.");
} else if (vm.isClientCompiler()) {
out.println("Client compiler detected.");
} else if (vm.isServerCompiler()) {
out.println("Server compiler detected.");
} else {
throw new RuntimeException("Fatal error: "
+ "should have been able to detect core/C1/C2 build");
}
String version = vm.getVMRelease();
if (version != null) {
out.print("JVM version is ");
out.println(version);
}
run();
}
}