home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1997 October
/
Chip_1997-10_cd.bin
/
tema
/
sybase
/
powerj
/
java.z
/
TTY.java
< prev
next >
Wrap
Text File
|
1996-05-03
|
43KB
|
1,448 lines
/*
* @(#)TTY.java 1.68 96/04/21
*
* Copyright (c) 1995 Sun Microsystems, Inc. All Rights Reserved.
*
* Permission to use, copy, modify, and distribute this software
* and its documentation for NON-COMMERCIAL purposes and without
* fee is hereby granted provided that this copyright notice
* appears in all copies. Please refer to the file "copyright.html"
* for further important copyright and licensing information.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
* THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
*/
package sun.tools.ttydebug;
import sun.tools.debug.*;
import java.util.*;
import java.io.*;
import java.net.*;
public class TTY implements DebuggerCallback {
RemoteDebugger debugger;
RemoteThread currentThread;
RemoteThreadGroup currentThreadGroup;
PrintStream out = null;
PrintStream console = null;
private String lastArgs = null;
private RemoteThread indexToThread(int index) throws Exception {
setDefaultThreadGroup();
RemoteThread list[] = currentThreadGroup.listThreads(true);
if (index == 0 || index > list.length) {
return null;
}
return list[index-1];
}
private int parseThreadId(String idToken) throws Exception {
if (idToken.startsWith("t@")) {
idToken = idToken.substring(2);
}
int threadId;
try {
threadId = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
threadId = 0;
}
if (indexToThread(threadId) == null) {
out.println("\"" + idToken +
"\" is not a valid thread id.");
return 0;
}
return threadId;
}
private void printPrompt() throws Exception {
if (currentThread == null) {
out.print("> ");
} else {
out.print(currentThread.getName() + "[" +
(currentThread.getCurrentFrameIndex() + 1)
+ "] ");
}
out.flush();
}
public synchronized void printToConsole(String text) throws Exception {
console.print(text);
console.flush();
}
public void breakpointEvent(RemoteThread t) throws Exception {
out.print("\nBreakpoint hit: ");
RemoteStackFrame[] stack = t.dumpStack();
if (stack.length > 0) {
out.println(stack[0].toString());
currentThread = t;
} else {
out.println("Invalid thread specified in breakpoint.");
}
printPrompt();
}
public void exceptionEvent(RemoteThread t, String errorText)
throws Exception {
out.println("\n" + errorText);
t.setCurrentFrameIndex(0);
currentThread = t;
printPrompt();
}
public void threadDeathEvent(RemoteThread t) throws Exception {
out.println("\n" + t.getName() + " died.");
if (t == currentThread) {
currentThread = null;
}
printPrompt();
}
public void quitEvent() throws Exception {
String msg = null;
if (lastArgs != null) {
StringTokenizer t = new StringTokenizer(lastArgs);
if (t.hasMoreTokens()) {
msg = new String("\n" + t.nextToken() + " exited");
}
}
if (msg == null) {
msg = new String("\nThe application exited");
}
out.println(msg);
currentThread = null;
System.exit(0);
}
void classes() throws Exception {
RemoteClass list[] = debugger.listClasses();
out.println("** classes list **");
for (int i = 0 ; i < list.length ; i++) {
out.println(list[i].description());
}
}
void methods(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("No class specified.");
return;
}
String idClass = t.nextToken();
try {
RemoteClass cls = getClassFromToken(idClass);
RemoteField methods[] = cls.getMethods();
for (int i = 0; i < methods.length; i++) {
out.println(methods[i].getTypedName());
}
} catch (IllegalArgumentException e) {
out.println("\"" + idClass +
"\" is not a valid id or class name.");
}
}
int printThreadGroup(RemoteThreadGroup tg, int iThread) throws Exception {
out.println("Group " + tg.getName() + ":");
RemoteThread tlist[] = tg.listThreads(false);
int maxId = 0;
int maxName = 0;
for (int i = 0 ; i < tlist.length ; i++) {
int len = tlist[i].description().length();
if (len > maxId)
maxId = len;
String name = tlist[i].getName();
int iDot = name.lastIndexOf('.');
if (iDot >= 0 && name.length() > iDot) {
name = name.substring(iDot + 1);
}
if (name.length() > maxName)
maxName = name.length();
}
for (int i = 0 ; i < tlist.length ; i++) {
char buf[] = new char[80];
for (int j = 0; j < 79; j++) {
buf[j] = ' ';
}
buf[79] = '\0';
StringBuffer sbOut = new StringBuffer();
sbOut.append(buf);
sbOut.insert(((i + iThread + 1) < 10) ? 1 : 0, (i + iThread + 1));
sbOut.insert(2, ".");
int iBuf = 4;
sbOut.insert(iBuf, tlist[i].description());
iBuf += maxId + 1;
String name = tlist[i].getName();
int iDot = name.lastIndexOf('.');
if (iDot >= 0 && name.length() > iDot) {
name = name.substring(iDot + 1);
}
sbOut.insert(iBuf, name);
iBuf += maxName + 1;
sbOut.insert(iBuf, tlist[i].getStatus());
sbOut.setLength(79);
out.println(sbOut.toString());
}
RemoteThreadGroup tglist[] = debugger.listThreadGroups(tg);
for (int ig = 0; ig < tglist.length; ig++) {
if (tg != tglist[ig]) {
iThread += printThreadGroup(tglist[ig], iThread + tlist.length);
}
}
return tlist.length;
}
private void setDefaultThreadGroup() throws Exception {
if (currentThreadGroup == null) {
RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
currentThreadGroup = tglist[0]; // system threadgroup
}
}
void threads(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
setDefaultThreadGroup();
printThreadGroup(currentThreadGroup, 0);
return;
}
String name = t.nextToken();
RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
for (int i = 0; i < tglist.length; i++) {
if (name.equals(tglist[i].getName())) {
printThreadGroup(tglist[i], 0);
return;
}
}
out.println(name + " is not a valid threadgroup name.");
}
void threadGroups() throws Exception {
RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
for (int i = 0; i < tglist.length; i++) {
out.println(new Integer(i+1).toString() + ". " +
tglist[i].description() + " " +
tglist[i].getName());
}
}
void setThread(int threadId) throws Exception {
setDefaultThreadGroup();
RemoteThread thread = indexToThread(threadId);
if (thread == null) {
out.println("\"" + threadId +
"\" is not a valid thread id.");
return;
}
currentThread = thread;
}
void thread(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("Thread number not specified.");
return;
}
int threadId = parseThreadId(t.nextToken());
if (threadId == 0) {
return;
}
setThread(threadId);
}
void threadGroup(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("Threadgroup name not specified.");
return;
}
String name = t.nextToken();
RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
for (int i = 0; i < tglist.length; i++) {
if (name.equals(tglist[i].getName())) {
currentThreadGroup = tglist[i];
return;
}
}
out.println(name + " is not a valid threadgroup name.");
}
void run(StringTokenizer t) throws Exception {
String argv[] = new String[100];
int argc = 0;
if (!t.hasMoreTokens() && lastArgs != null) {
t = new StringTokenizer(lastArgs);
out.println("run " + lastArgs);
}
while (t.hasMoreTokens()) {
argv[argc++] = t.nextToken();
if (argc == 1) {
// Expand name, if necessary.
RemoteClass cls = debugger.findClass(argv[0]);
if (cls == null) {
out.println("Could not load the " + argv[0] + " class.");
return;
}
argv[0] = cls.getName();
}
}
if (argc > 0) {
RemoteThreadGroup newGroup = debugger.run(argc, argv);
if (newGroup != null) {
currentThreadGroup = newGroup;
setThread(1);
out.println("running ...");
} else {
out.println(argv[0] + " failed.");
}
} else {
out.println("No class name specified.");
}
}
void load(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("Class name not specified.");
return;
}
String idToken = t.nextToken();
RemoteClass cls = debugger.findClass(idToken);
if (cls == null) {
out.print(idToken + " not found");
out.println((idToken.indexOf('.') > 0) ?
" (try the full name)" : "");
} else {
out.println(cls.toString());
}
}
void suspend(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
setDefaultThreadGroup();
RemoteThread list[] = currentThreadGroup.listThreads(true);
for (int i = 0; i < list.length; i++) {
list[i].suspend();
}
out.println("All (non-system) threads suspended.");
} else {
while (t.hasMoreTokens()) {
String idToken = t.nextToken();
int threadId;
try {
threadId = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
threadId = 0;
}
RemoteThread thread = indexToThread(threadId);
if (thread == null) {
out.println("\"" + idToken +
"\" is not a valid thread id.");
continue;
}
thread.suspend();
}
}
}
void resume(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
setDefaultThreadGroup();
RemoteThread list[] = currentThreadGroup.listThreads(true);
for (int i = 0; i < list.length; i++) {
list[i].resume();
}
if (currentThread != null) {
currentThread.resetCurrentFrameIndex();
}
out.println("All threads resumed.");
} else {
while (t.hasMoreTokens()) {
String idToken = t.nextToken();
int threadId;
try {
threadId = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
threadId = 0;
}
RemoteThread thread = indexToThread(threadId);
if (thread == null) {
out.println("\"" + idToken +
"\" is not a valid thread id.");
continue;
}
thread.resume();
if (thread == currentThread) {
currentThread.resetCurrentFrameIndex();
}
}
}
}
void cont() throws Exception {
if (currentThread == null) {
out.println("Nothing suspended.");
return;
}
setDefaultThreadGroup();
RemoteThread list[] = currentThreadGroup.listThreads(true);
for (int i = 0; i < list.length; i++) {
list[i].cont();
}
currentThread.resetCurrentFrameIndex();
}
void step() throws Exception {
if (currentThread == null) {
out.println("Nothing suspended.");
return;
}
try {
currentThread.step(true);
} catch (IllegalAccessError e) {
out.println("Current thread is not at breakpoint.");
}
}
void next() throws Exception {
if (currentThread == null) {
out.println("Nothing suspended.");
return;
}
try {
currentThread.next();
} catch (IllegalAccessError e) {
out.println("Current thread is not at breakpoint.");
}
}
void kill(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("Usage: kill <threadgroup name> or <thread id>");
return;
}
while (t.hasMoreTokens()) {
String idToken = t.nextToken();
int threadId;
try {
threadId = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
threadId = 0;
}
RemoteThread thread = indexToThread(threadId);
if (thread != null) {
out.println("killing thread: " + thread.getName());
thread.stop();
return;
} else {
/* Check for threadgroup name, skipping "system". */
RemoteThreadGroup tglist[] = debugger.listThreadGroups(null);
tglist = debugger.listThreadGroups(tglist[0]);
for (int i = 0; i < tglist.length; i++) {
if (tglist[i].getName().equals(idToken)) {
out.println("killing threadgroup: " + idToken);
tglist[i].stop();
return;
}
}
out.println("\"" + idToken +
"\" is not a valid threadgroup or id.");
}
}
}
void catchException(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
String exceptionList[] = debugger.getExceptionCatchList();
for (int i = 0; i < exceptionList.length; i++) {
out.print(" " + exceptionList[i]);
if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
out.println();
}
}
} else {
String idClass = t.nextToken();
try {
RemoteClass cls = getClassFromToken(idClass);
cls.catchExceptions();
} catch (Exception e) {
out.println("Invalid exception class name: " + idClass);
}
}
}
void ignoreException(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
String exceptionList[] = debugger.getExceptionCatchList();
for (int i = 0; i < exceptionList.length; i++) {
out.print(" " + exceptionList[i]);
if ((i & 4) == 3 || (i == exceptionList.length - 1)) {
out.println();
}
}
} else {
String idClass = t.nextToken();
try {
RemoteClass cls = getClassFromToken(idClass);
cls.ignoreExceptions();
} catch (Exception e) {
out.println("Invalid exception class name: " + idClass);
}
}
}
void up(StringTokenizer t) throws Exception {
if (currentThread == null) {
out.println("Current thread not set.");
return;
}
int nLevels = 1;
if (t.hasMoreTokens()) {
String idToken = t.nextToken();
int n;
try {
n = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
n = 0;
}
if (n == 0) {
out.println("Usage: up [n frames]");
return;
}
nLevels = n;
}
try {
currentThread.up(nLevels);
} catch (IllegalAccessError e) {
out.println("Thread isn't suspended.");
} catch (ArrayIndexOutOfBoundsException e) {
out.println("End of stack.");
}
}
void down(StringTokenizer t) throws Exception {
if (currentThread == null) {
out.println("Current thread not set.");
return;
}
int nLevels = 1;
if (t.hasMoreTokens()) {
String idToken = t.nextToken();
int n;
try {
n = Integer.valueOf(idToken).intValue();
} catch (NumberFormatException e) {
n = 0;
}
if (n == 0) {
out.println("usage: down [n frames]");
return;
}
nLevels = n;
}
try {
currentThread.down(nLevels);
} catch (IllegalAccessError e) {
out.println("Thread isn't suspended.");
} catch (ArrayIndexOutOfBoundsException e) {
out.println("End of stack.");
}
}
void dumpStack(RemoteThread thread) throws Exception {
RemoteStackFrame[] stack = thread.dumpStack();
if (stack.length == 0) {
out.println("Thread is not running (no stack).");
} else {
int nFrames = stack.length;
for (int i = thread.getCurrentFrameIndex(); i < nFrames; i++) {
out.print(" [" + (i + 1) + "] ");
out.println(stack[i].toString());
}
}
}
void where(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
if (currentThread == null) {
out.println("No thread specified.");
return;
}
dumpStack(currentThread);
} else {
String token = t.nextToken();
if (token.toLowerCase().equals("all")) {
setDefaultThreadGroup();
RemoteThread list[] = currentThreadGroup.listThreads(true);
for (int i = 0; i < list.length; i++) {
out.println(list[i].getName() + ": ");
dumpStack(list[i]);
}
} else {
int threadId = parseThreadId(token);
if (threadId == 0) {
return;
}
dumpStack(indexToThread(threadId));
}
}
}
void trace(String cmd, StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println("(i)trace < \"on\" | \"off\" >");
return;
}
String v = t.nextToken();
boolean traceOn;
if (v.equals("on")) {
traceOn = true;
} else if (v.equals("off")) {
traceOn = false;
} else {
out.println("(i)trace < \"on\" | \"off\" >");
return;
}
if (cmd.equals("trace")) {
debugger.trace(traceOn);
} else {
debugger.itrace(traceOn);
}
}
void memory() throws Exception {
out.println("Free: " + debugger.freeMemory() + ", total: " +
debugger.totalMemory());
}
void gc() throws Exception {
RemoteObject[] save_list = new RemoteObject[2];
save_list[0] = currentThread;
save_list[1] = currentThreadGroup;
debugger.gc(save_list);
}
private RemoteClass getClassFromToken(String idToken) throws Exception {
RemoteObject obj;
if (idToken.startsWith("0x") ||
Character.isDigit(idToken.charAt(0))) {
/* It's an object id. */
int id;
try {
id = RemoteObject.fromHex(idToken);
} catch (NumberFormatException e) {
id = 0;
}
if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
throw new IllegalArgumentException();
} else if (!(obj instanceof RemoteClass)) {
throw new IllegalArgumentException();
}
} else {
/* It's a class */
obj = debugger.findClass(idToken);
if (obj == null) {
throw new IllegalArgumentException();
}
}
return (RemoteClass)obj;
}
void listBreakpoints() throws Exception {
String bkptList[] = debugger.listBreakpoints();
if (bkptList.length > 0) {
out.println("Current breakpoints set:");
for(int i = 0; i < bkptList.length; i++) {
out.println("\t" + bkptList[i]);
}
} else {
out.println("No breakpoints set.");
}
}
void stop(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
listBreakpoints();
return;
}
String idClass = null;
try {
String modifier = t.nextToken();
boolean stopAt;
if (modifier.equals("at")) {
stopAt = true;
} else if (modifier.equals("in")) {
stopAt = false;
} else {
out.println("Usage: stop at <class>:<line_number> or");
out.println(" stop in <class>.<method_name>");
return;
}
if (modifier.equals("at")) {
idClass = t.nextToken(": \t\n\r");
RemoteClass cls = getClassFromToken(idClass);
String idLine = t.nextToken();
int lineno = Integer.valueOf(idLine).intValue();
String err = cls.setBreakpointLine(lineno);
if (err.length() > 0) {
out.println(err);
} else {
out.println("Breakpoint set at " + cls.getName() +
":" + lineno);
}
} else {
idClass = t.nextToken(": \t\n\r");
RemoteClass cls = null;
String idMethod = null;
try {
cls = getClassFromToken(idClass);
} catch (IllegalArgumentException e) {
// Try stripping method from class.method token.
int idot = idClass.lastIndexOf(".");
if (idot == -1) {
out.println("\"" + idClass +
"\" is not a valid id or class name.");
return;
}
idMethod = idClass.substring(idot + 1);
idClass = idClass.substring(0, idot);
cls = getClassFromToken(idClass);
}
if (idMethod == null) {
idMethod = t.nextToken();
}
RemoteField method;
try {
method = cls.getMethod(idMethod);
} catch (NoSuchMethodException nsme) {
out.println("Class " + cls.getName() +
" doesn't have a method " + idMethod);
return;
}
String err = cls.setBreakpointMethod(method);
if (err.length() > 0) {
out.println(err);
} else {
out.println("Breakpoint set in " + cls.getName() +
"." + idMethod);
}
}
} catch (NoSuchElementException e) {
out.println("Usage: stop at <class>:<line_number> or");
out.println(" stop in <class>.<method_name>");
} catch (NumberFormatException e) {
out.println("Invalid line number.");
} catch (IllegalArgumentException e) {
out.println("\"" + idClass +
"\" is not a valid id or class name.");
}
}
void clear(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
listBreakpoints();
return;
}
String idClass = null;
String idMethod = null;
RemoteClass cls = null;
try {
idClass = t.nextToken(": \t\n\r");
try {
cls = getClassFromToken(idClass);
} catch (IllegalArgumentException e) {
// Try stripping method from class.method token.
int idot = idClass.lastIndexOf(".");
if (idot == -1) {
out.println("\"" + idClass +
"\" is not a valid id or class name.");
return;
}
idMethod = idClass.substring(idot + 1);
idClass = idClass.substring(0, idot);
cls = getClassFromToken(idClass);
RemoteField method;
try {
method = cls.getMethod(idMethod);
} catch (NoSuchMethodException nsme) {
out.println("\"" + idMethod +
"\" is not a valid method name of class " +
cls.getName());
return;
}
String err = cls.clearBreakpointMethod(method);
if (err.length() > 0) {
out.println(err);
} else {
out.println("Breakpoint cleared at " +
cls.getName() + "." + idMethod);
}
return;
}
String idLine = t.nextToken();
int lineno = Integer.valueOf(idLine).intValue();
String err = cls.clearBreakpointLine(lineno);
if (err.length() > 0) {
out.println(err);
} else {
out.println("Breakpoint cleared at " + cls.getName() +
": " + lineno);
}
} catch (NoSuchElementException e) {
out.println("Usage: clear <class>:<line_number>");
out.println(" or: clear <class>.<method>");
} catch (NumberFormatException e) {
out.println("Usage: clear <class>:<line_number>");
out.println(" or: clear <class>.<method>");
} catch (IllegalArgumentException e) {
out.println("\"" + idClass +
"\" is not a valid id or class name.");
}
}
void list(StringTokenizer t) throws Exception {
RemoteStackFrame frame = null;
if (currentThread == null) {
out.println("No thread specified.");
return;
}
try {
frame = currentThread.getCurrentFrame();
} catch (IllegalAccessError e) {
out.println("Current thread isn't suspended.");
return;
} catch (ArrayIndexOutOfBoundsException e) {
out.println("Thread is not running (no stack).");
return;
}
int lineno;
if (t.hasMoreTokens()) {
String id = t.nextToken();
// See if token is a line number.
try {
lineno = Integer.valueOf(id).intValue();
} catch (NumberFormatException nfe) {
// It isn't -- see if it's a method name.
try {
lineno = frame.getRemoteClass().getMethodLineNumber(id);
} catch (NoSuchMethodException iobe) {
out.println(id + " is not a valid line number or " +
"method name for class " +
frame.getRemoteClass().getName());
return;
} catch (NoSuchLineNumberException nse) {
out.println("Line number information not found in " +
frame.getRemoteClass().getName());
return;
}
}
} else {
lineno = frame.getLineNumber();
}
int startLine = (lineno > 4) ? lineno - 4 : 1;
int endLine = startLine + 9;
InputStream rawSourceFile = frame.getRemoteClass().getSourceFile();
if (rawSourceFile == null) {
out.println("Unable to find " +
frame.getRemoteClass().getSourceFileName());
return;
}
DataInputStream sourceFile = new DataInputStream(rawSourceFile);
String sourceLine = null;
/* Skip through file to desired window. */
for (int i = 1; i <= startLine; i++) {
sourceLine = sourceFile.readLine();
}
if (sourceLine == null) {
out.println(new Integer(lineno).toString() +
" is an invalid line number for the file " +
frame.getRemoteClass().getSourceFileName());
}
/* Print lines */
for (int i = startLine; i < endLine && sourceLine != null; i++) {
out.print(new Integer(i).toString() + "\t" +
((i == lineno) ? "=> " : " "));
out.println(sourceLine);
sourceLine = sourceFile.readLine();
}
}
/* Get or set the source file path list. */
void use(StringTokenizer t) throws Exception {
if (!t.hasMoreTokens()) {
out.println(debugger.getSourcePath());
} else {
debugger.setSourcePath(t.nextToken());
}
}
/* Print all local variables in current stack frame. */
void locals() throws Exception {
if (currentThread == null) {
out.println("No default thread specified: " +
"use the \"thread\" command first.");
return;
}
RemoteStackVariable rsv[] = currentThread.getStackVariables();
if (rsv == null || rsv.length == 0) {
out.println("No local variables: try compiling with -g");
return;
}
out.println("Method arguments:");
for (int i = 0; i < rsv.length; i++) {
if (rsv[i].methodArgument()) {
out.print(" " + rsv[i].getName());
if (rsv[i].inScope()) {
out.println(" = " + rsv[i].getValue().toString());
} else {
out.println(" is not in scope (WHAT???)");
}
}
}
out.println("Local variables:");
for (int i = 0; i < rsv.length; i++) {
if (!rsv[i].methodArgument()) {
out.print(" " + rsv[i].getName());
if (rsv[i].inScope()) {
out.println(" = " + rsv[i].getValue().toString());
} else {
out.println(" is not in scope.");
}
}
}
return;
}
/* Print a specified reference. Returns success in resolving reference. */
boolean print(StringTokenizer t, boolean dumpObject, boolean recursing) throws Exception {
if (!t.hasMoreTokens()) {
out.println("No objects specified.");
return false;
}
while (t.hasMoreTokens()) {
int id;
RemoteValue obj = null;
String delimiters = ".[(";
String expr = t.nextToken();
StringTokenizer pieces =
new StringTokenizer(expr, delimiters, true);
String idToken = pieces.nextToken(); // There will be at least one.
String varName = expr;
if (idToken.startsWith("t@")) {
/* It's a thread */
setDefaultThreadGroup();
RemoteThread tlist[] = currentThreadGroup.listThreads(true);
try {
id = Integer.valueOf(idToken.substring(2)).intValue();
} catch (NumberFormatException e) {
id = 0;
}
if (id <= 0 || id > tlist.length) {
out.println("\"" + idToken +
"\" is not a valid thread id.");
return false;
}
obj = tlist[id - 1];
} else if (idToken.startsWith("$s")) {
int slotnum;
try {
slotnum = Integer.valueOf(idToken.substring(2)).intValue();
} catch (NumberFormatException e) {
out.println("\"" + idToken +
"\" is not a valid slot.");
return false;
}
if (currentThread != null) {
RemoteStackVariable rsv[] = currentThread.getStackVariables();
if (rsv == null || slotnum >= rsv.length) {
out.println("\"" + idToken +
"\" is not a valid slot.");
return false;
}
obj = rsv[slotnum].getValue();
}
} else if (idToken.startsWith("0x") ||
Character.isDigit(idToken.charAt(0))) {
/* It's an object id. */
try {
id = RemoteObject.fromHex(idToken);
} catch (NumberFormatException e) {
id = 0;
}
if (id == 0 || (obj = debugger.get(new Integer(id))) == null) {
out.println("\"" + idToken +
"\" is not a valid id.");
return false;
}
} else {
/* See if it's a local stack variable */
if (currentThread != null) {
RemoteStackVariable rsv =
currentThread.getStackVariable(idToken);
if (rsv != null && !rsv.inScope()) {
out.println(idToken + " is not in scope.");
return false;
}
obj = (rsv == null) ? null : rsv.getValue();
}
if (obj == null) {
if (idToken.equals("this") == false) {
/* See if it's an instance variable */
String instanceStr = "this." + idToken;
if (print(new StringTokenizer(instanceStr),
dumpObject, true))
return true;
}
/* It's a class */
obj = debugger.findClass(idToken);
if (obj == null) {
if (!recursing) {
out.println("\"" + expr + "\" is not a " +
"valid id or class name.");
}
return false;
}
}
}
RemoteInt noValue = new RemoteInt(-1);
RemoteValue rv = noValue;
String lastField = "";
idToken = pieces.hasMoreTokens() ? pieces.nextToken() : null;
while (idToken != null) {
if (idToken.equals(".")) {
if (pieces.hasMoreTokens() == false) {
out.println("\"" + expr +
"\" is not a valid expression.");
return false;
}
idToken = pieces.nextToken();
if (rv != noValue) {
/* attempt made to get a field on a non-object */
out.println("\"" + lastField +
"\" is not an object.");
return false;
}
lastField = idToken;
rv = ((RemoteObject)obj).getFieldValue(idToken);
if (rv == null) {
out.println("\"" + idToken +
"\" is not a valid field of " +
obj.description());
return false;
}
if (rv.isObject()) {
obj = rv;
rv = noValue;
}
idToken =
pieces.hasMoreTokens() ? pieces.nextToken() : null;
} else if (idToken.equals("[")) {
if (pieces.hasMoreTokens() == false) {
out.println("\"" + expr +
"\" is not a valid expression.");
return false;
}
idToken = pieces.nextToken("]");
try {
int index = Integer.valueOf(idToken).intValue();
rv = ((RemoteArray)rv).getElement(index);
} catch (NumberFormatException e) {
out.println("\"" + idToken +
"\" is not a valid decimal number.");
return false;
} catch (ArrayIndexOutOfBoundsException e) {
out.println(idToken + " is out of bounds for " +
obj.description());
return false;
}
if (rv != null && rv.isObject()) {
obj = rv;
rv = noValue;
}
if (pieces.hasMoreTokens() == false ||
(idToken = pieces.nextToken()).equals("]") == false) {
out.println("\"" + expr +
"\" is not a valid expression.");
return false;
}
idToken = pieces.hasMoreTokens() ?
pieces.nextToken(delimiters) : null;
} else if (idToken.equals("(")) {
out.println("print <method> not supported yet.");
return false;
} else {
/* Should never get here. */
out.println("invalid expression");
return false;
}
}
out.print(varName + " = ");
if (rv != noValue) {
out.println((rv == null) ? "null" : rv.description());
} else if (dumpObject && obj instanceof RemoteObject) {
out.println(obj.description() + " {");
if (obj instanceof RemoteClass) {
RemoteClass cls = (RemoteClass)obj;
out.print(" superclass = ");
RemoteClass superClass = cls.getSuperclass();
out.println((superClass == null) ?
"null" : superClass.description());
out.print(" loader = ");
RemoteObject loader = cls.getClassLoader();
out.println((loader == null) ?
"null" : loader.description());
RemoteClass interfaces[] = cls.getInterfaces();
if (interfaces != null && interfaces.length > 0) {
out.println(" interfaces:");
for (int i = 0; i < interfaces.length; i++) {
out.println(" " + interfaces[i]);
}
}
}
RemoteField fields[] = ((RemoteObject)obj).getFields();
if (obj instanceof RemoteClass && fields.length > 0) {
out.println();
}
for (int i = 0; i < fields.length; i++) {
String name = fields[i].getTypedName();
String modifiers = fields[i].getModifiers();
out.print(" " + modifiers + name + " = ");
RemoteValue v = ((RemoteObject)obj).getFieldValue(i);
out.println((v == null) ? "null" : v.description());
}
out.println("}");
} else {
out.println(obj.toString());
}
}
return true;
}
void help
() {
out.println("** command list **");
out.println("threads [threadgroup] -- list threads");
out.println("thread <thread id> -- set default thread");
out.println("suspend [thread id(s)] -- suspend threads (default: all)");
out.println("resume [thread id(s)] -- resume threads (default: all)");
out.println("where [thread id] | all -- dump a thread's stack");
out.println("threadgroups -- list threadgroups");
out.println("threadgroup <name> -- set current threadgroup\n");
out.println("print <id> [id(s)] -- print object or field");
out.println("dump <id> [id(s)] -- print all object information\n");
out.println("locals -- print all local variables in current stack frame\n");
out.println("classes -- list currently known classes");
out.println("methods <class id> -- list a class's methods\n");
out.println("stop in <class id>.<method> -- set a breakpoint in a method");
out.println("stop at <class id>:<line> -- set a breakpoint at a line");
out.println("up [n frames] -- move up a thread's stack");
out.println("down [n frames] -- move down a thread's stack");
out.println("clear <class id>:<line> -- clear a breakpoint");
out.println("step -- execute current line");
out.println("cont -- continue execution from breakpoint\n");
out.println("catch <class id> -- break for the specified exception");
out.println("ignore <class id> -- ignore when the specified exception\n");
out.println("list [line number|method] -- print source code");
out.println("use [source file path] -- display or change the source path\n");
out.println("memory -- report memory usage");
out.println("gc -- free unused objects\n");
out.println("load classname -- load Java class to be debugged");
out.println("run <class> [args] -- start execution of a loaded Java class");
// out.println("kill <thread(group)> -- kill a thread or threadgroup\n");
out.println("!! -- repeat last command");
out.println("help (or ?) -- list commands");
out.println("exit (or quit) -- exit debugger");
}
void executeCommand(StringTokenizer t) {
String cmd = t.nextToken().toLowerCase();
try {
if (cmd.equals("print")) {
print(t, false, false);
} else if (cmd.equals("dump")) {
print(t, true, false);
} else if (cmd.equals("locals")) {
locals();
} else if (cmd.equals("classes")) {
classes();
} else if (cmd.equals("methods")) {
methods(t);
} else if (cmd.equals("threads")) {
threads(t);
} else if (cmd.equals("thread")) {
thread(t);
} else if (cmd.equals("suspend")) {
suspend(t);
} else if (cmd.equals("resume")) {
resume(t);
} else if (cmd.equals("threadgroups")) {
threadGroups();
} else if (cmd.equals("threadgroup")) {
threadGroup(t);
} else if (cmd.equals("catch")) {
catchException(t);
} else if (cmd.equals("ignore")) {
ignoreException(t);
} else if (cmd.equals("cont")) {
cont();
} else if (cmd.equals("step")) {
step();
} else if (cmd.equals("next")) {
next();
} else if (cmd.equals("kill")) {
kill(t);
} else if (cmd.equals("where")) {
where(t);
} else if (cmd.equals("up")) {
up(t);
} else if (cmd.equals("down")) {
down(t);
} else if (cmd.equals("load")) {
load(t);
} else if (cmd.equals("run")) {
run(t);
} else if (cmd.equals("memory")) {
memory();
} else if (cmd.equals("gc")) {
gc();
} else if (cmd.equals("trace") || cmd.equals("itrace")) {
trace(cmd, t);
} else if (cmd.equals("stop")) {
stop(t);
} else if (cmd.equals("clear")) {
clear(t);
} else if (cmd.equals("list")) {
list(t);
} else if (cmd.equals("use")) {
use(t);
} else if (cmd.equals("help") || cmd.equals("?")) {
help();
} else if (cmd.equals("quit") || cmd.equals("exit")) {
debugger.close();
System.exit(0);
} else {
out.println("huh? Try help...");
}
} catch (Exception e) {
out.println("Internal exception:");
out.flush();
e.printStackTrace();
}
}
void readCommandFile(File f) {
try {
if (f.canRead()) {
// Process initial commands.
DataInputStream inFile =
new DataInputStream(new FileInputStream(f));
String ln;
while ((ln = inFile.readLine()) != null) {
StringTokenizer t = new StringTokenizer(ln);
if (t.hasMoreTokens()) {
executeCommand(t);
}
}
}
} catch (IOException e) {}
}
public TTY(String host, String password, String javaArgs, String args,
PrintStream outStream, PrintStream consoleStream,
boolean verbose) throws Exception {
System.out.println("Initializing jdb...");
out = outStream;
console = consoleStream;
if (password == null) {
debugger = new RemoteDebugger(javaArgs, this, verbose);
} else {
debugger = new RemoteDebugger(host, password, this, verbose);
}
DataInputStream in = new DataInputStream(System.in);
String lastLine = null;
if (args != null && args.length() > 0) {
StringTokenizer t = new StringTokenizer(args);
load(t);
lastArgs = args;
}
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
// Try reading user's startup file.
File f = new File(System.getProperty("user.home") +
System.getProperty("file.separator") + "jdb.ini");
if (!f.canRead()) {
// Try opening $HOME/jdb.ini
f = new File(System.getProperty("user.home") +
System.getProperty("file.separator") + ".jdbrc");
}
readCommandFile(f);
// Try opening local jdb.ini
f = new File(System.getProperty("user.dir") +
System.getProperty("file.separator") + "startup.jdb");
readCommandFile(f);
// Process interactive commands.
while (true) {
printPrompt();
String ln = in.readLine();
if (ln == null) {
out.println("Input stream closed.");
return;
}
if (ln.startsWith("!!") && lastLine != null) {
ln = lastLine + ln.substring(2);
out.println(ln);
}
StringTokenizer t = new StringTokenizer(ln);
if (t.hasMoreTokens()) {
lastLine = ln;
executeCommand(t);
}
}
}
public static void main(String argv[]) {
// Get host attribute, if any.
String localhost;
try {
localhost = InetAddress.getLocalHost().getHostName();
} catch (Exception ex) {
localhost = null;
}
if (localhost == null) {
localhost = "localhost";
}
String host = null;
String password = null;
String classArgs = "";
String javaArgs = "";
boolean verbose = false;
for (int i = 0; i < argv.length; i++) {
String token = argv[i];
if (token.equals("-dbgtrace")) {
verbose = true;
} else if (token.equals("-cs") || token.equals("-checksource") ||
token.equals("-noasyncgc") || token.equals("-prof") ||
token.equals("-v") || token.equals("-verbose") ||
token.equals("-verify") || token.equals("-noverify") ||
token.equals("-verifyremote") ||
token.equals("-verbosegc") ||
token.startsWith("-ms") || token.startsWith("-mx") ||
token.startsWith("-ss") || token.startsWith("-oss") ||
token.startsWith("-D")) {
javaArgs += token + " ";
} else if (token.equals("-classpath")) {
if (i == (argv.length - 1)) {
System.out.println("No classpath specified.");
System.exit(1);
}
javaArgs += token + " " + argv[++i] + " ";
} else if (token.equals("-host")) {
if (i == (argv.length - 1)) {
System.out.println("No host specified.");
System.exit(1);
}
host = argv[++i];
} else if (token.equals("-password")) {
if (i == (argv.length - 1)) {
System.out.println("No password specified.");
System.exit(1);
}
password = argv[++i];
} else {
classArgs += token + " ";
}
}
if (host != null && password == null) {
System.out.println("A debug password must be specified for " +
"remote debugging.");
System.exit(1);
}
if (host == null) {
host = localhost;
}
try {
if (!host.equals(localhost) && password.length() == 0) {
System.out.println(
"No password supplied for accessing remote " +
"Java interpreter.");
System.out.println(
"The password is reported by the remote interpreter" +
"when it is started.");
System.exit(1);
}
new TTY(host, password, javaArgs, classArgs,
System.out, System.out, verbose);
} catch(SocketException se) {
System.out.println("Failed accessing debugging session on " +
host + ": invalid password.");
} catch(NumberFormatException ne) {
System.out.println("Failed accessing debugging session on " +
host + ": invalid password.");
} catch(Exception e) {
System.out.print("Internal exception: ");
System.out.flush();
e.printStackTrace();
}
}
}