If ajdb ever existed and was part of the product, it must have been 20+ years ago. There are still some references to it in old release notes and unused Ant and text files, but that is OK for now. Signed-off-by: Alexander Kriegisch <Alexander@Kriegisch.name>antora
* xref:adk15notebook:varargs.adoc[] | * xref:adk15notebook:varargs.adoc[] | ||||
* xref:devguide:aj.adoc[] | * xref:devguide:aj.adoc[] | ||||
* xref:devguide:ajc.adoc[] | * xref:devguide:ajc.adoc[] | ||||
* xref:devguide:ajdb.adoc[] | |||||
* xref:devguide:ajdoc.adoc[] | * xref:devguide:ajdoc.adoc[] | ||||
* xref:devguide:antsupport.adoc[] | * xref:devguide:antsupport.adoc[] | ||||
* xref:devguide:compatibility.adoc[] | * xref:devguide:compatibility.adoc[] |
ajdb | |||||
debugger for .class files produced by ajc (early-access) | |||||
ajdb | |||||
-classpath | |||||
path | |||||
-D | |||||
name | |||||
= | |||||
value | |||||
-help | |||||
-gui | |||||
-read | |||||
file | |||||
-sourcepath | |||||
dir | |||||
-v | |||||
-verbose | |||||
:class | |||||
:gc | |||||
:jni | |||||
workingdir | |||||
dir | |||||
-X | |||||
option | |||||
class | |||||
arguments | |||||
= Description | |||||
The command `ajdb` is used to debug AspectJ and Java programs. In | |||||
addition to its command line interface, `adjb` also has a standalone, | |||||
Swing-based GUI interface. | |||||
Note: As of the 1.0.3 release, AspectJ supports JSR-45, which provides | |||||
source-level debugging from many source files per class and non-Java | |||||
source files. JSR-45 is implemented in the J2SE 1.4 debugger support, so | |||||
you may be able to use your existing debugger to step through AspectJ | |||||
source code if both the source and target VM's are running under Java | |||||
1.4 or later. However, existing debuggers will display synthetic methods | |||||
in the stack frame. | |||||
-classpath | |||||
path | |||||
Specify where to find user class files. | |||||
-D | |||||
name | |||||
= | |||||
value | |||||
Define the property | |||||
name | |||||
to have the value | |||||
value | |||||
. | |||||
-help | |||||
Print out | |||||
ajdb | |||||
's usage summary. | |||||
-read | |||||
file | |||||
Read this file for initializatoin commands. | |||||
-sourcepath | |||||
path | |||||
Search this directory for source files. | |||||
-gui | |||||
-v | -verbose [:class | :gc | :jni] | |||||
Print out class loading, garbage collection or dynamic library loading | |||||
information. Defaults to class loading. | |||||
-workingdir | |||||
directory | |||||
Set | |||||
ajdb | |||||
's working directory. | |||||
-X | |||||
option | |||||
Pass a non-standard option to the VM | |||||
== Capabilities | |||||
The AspectJ debugger implements all of ``jdb``'s commands. In addition, | |||||
the command `workingdir` allow you to set the AspectJ working directory, | |||||
and the breakpoint command, `stop on`, has been extended to allow the | |||||
setting of breakpoint on a source file line. | |||||
== Examples | |||||
Suppose you want to debug the file spacewar/Ship.java found in the | |||||
examples directory. At the command line start up the debugger: ` | |||||
ajdb | |||||
` | |||||
The debugger will first look for initialization files in your home or | |||||
current directory called either `ajdb.ini` or `.ajdbrc` and execute the | |||||
commands contained in them. A useful command to have in this file is the | |||||
`source-path` command which tells the debugger where to find source | |||||
files. | |||||
For this example, we need to set the source path by: ` | |||||
use C:\src | |||||
` | |||||
To view the file to debug, type `list | |||||
spacewar/Ship.java` which generates the following output: | |||||
[source, java] | |||||
.... | |||||
/*209*/ void fire() { | |||||
/*210*/ // firing a shot takes energy | |||||
/*211*/ if (!expendEnergy(BULLET_ENERGY)) | |||||
/*212*/ return; | |||||
/*213*/ | |||||
/*214*/ //create a bullet object so it doesn't hit the ship that's firing it | |||||
/*215*/ double xV = getXVel() + BULLET_SPEED * (Math.cos(orientation)); | |||||
/*216*/ double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||||
/*217*/ | |||||
/*218*/ // create the actual bullet | |||||
/*219*/ new Bullet( | |||||
/*220*/ getGame(), | |||||
/*221*/ (getXPos() + ((getSize()/2 + 2) * (Math.cos(orientation))) + xV), | |||||
/*222*/ (getYPos() + ((getSize()/2 + 2) * (Math.sin(orientation))) + yV), | |||||
/*223*/ xV, | |||||
/*224*/ yV); | |||||
/*225*/ } | |||||
.... | |||||
This is different from `jdb` because it allows one to view files before | |||||
the debugger has started. The `list` command has the following syntax: | |||||
list | |||||
list the source containing the location at which we are currently | |||||
stopped (can only be used with a running VM) | |||||
list | |||||
source | |||||
list the entire file source | |||||
list | |||||
source line | |||||
list source line line of file source | |||||
list | |||||
source start-line end-line | |||||
list the lines from | |||||
start-line | |||||
to | |||||
end-line | |||||
of file | |||||
source | |||||
To set a breakpoint in the method `Ship.fire`, we would could type | |||||
`stop in spacewar.Ship.fire`. | |||||
The following message appears notifying the user that the breakpoint has | |||||
been noted but will not be set until the class has been loaded by the | |||||
VM: | |||||
[source, text] | |||||
.... | |||||
Deferring breakpoint spacewar.Ship.fire() | |||||
It will be set after the class is loaded. | |||||
.... | |||||
To start Spacewar we type `run spacewar.Game`. | |||||
When the breakpoint is set, the following message appears: | |||||
[source, text] | |||||
.... | |||||
Set deferred breakpoint spacewar.Ship.fire() | |||||
.... | |||||
We are notified that we've hit the breakpoint: | |||||
[source, text] | |||||
.... | |||||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=174, bci=0 209 void fire() { | |||||
.... | |||||
The prompt changes to present the thread that has broken, and we can | |||||
view the current stack with the `where` command, as follows: | |||||
[source, text] | |||||
.... | |||||
Thread-2[1] where | |||||
[1] fire (spacewar\Ship.java:209) | |||||
[2] run (spacewar\Robot.java:100) | |||||
[3] run [class java.lang.Thread] | |||||
.... | |||||
Next, to stop on line 216 we type `stop on spacewar/Ship.java:216` | |||||
The following message tells us the breakpoint was set: | |||||
[source, text] | |||||
.... | |||||
Set breakpoint Ship.java:216 | |||||
.... | |||||
To continue execution, we type `cont` and the breakpoint at line 216 is | |||||
hit | |||||
[source, text] | |||||
.... | |||||
Breakpoint hit: thread="Thread-2", spacewar.Ship.fire(), line=216, bci=28 | |||||
216 double yV = getYVel() + BULLET_SPEED * (Math.sin(orientation)); | |||||
.... | |||||
To view the visible local variables, we type `locals` and ajdb responds | |||||
with: | |||||
[source, text] | |||||
.... | |||||
Local variables | |||||
xV = 12.242462584304468 | |||||
.... | |||||
To change the value of the local variable i to 15, we type | |||||
`set xV = 16.1` | |||||
[source, text] | |||||
.... | |||||
Changed 'xV' from '12.242462584304468' to '16.1' | |||||
.... | |||||
To see our changes we can print the value of `i` by the following: | |||||
[source, text] | |||||
.... | |||||
print xV | |||||
Value for printing 'xV' = 12.242462584304468 | |||||
.... | |||||
We can now type exit or quit to leave the debugger, and we receive the | |||||
following message: | |||||
[source, text] | |||||
.... | |||||
The application has exited. | |||||
.... | |||||
== The AspectJ debugger API | |||||
The AspectJ debugger is implemented completely in Java and can be called | |||||
as a Java class. The only interface that should be considered public is | |||||
the method `org.aspectj.tools.debugger.Main.main(String[] | |||||
args)` where `args` are the standard `ajc` command line arguments. | |||||
This means that an alternative way to run the compiler is | |||||
[source, text] | |||||
.... | |||||
java org.aspectj.tools.debugger.Main options class arguments | |||||
.... | |||||
You must additionally include `tools.jar` from your Java developer's kit | |||||
in your classpath. |
//package debugger; | |||||
public class AJDBThreads { | |||||
public static void main(String[] args) { | |||||
new ThreadForker().go(); | |||||
} | |||||
public static String currentThread = "none"; | |||||
} | |||||
class ThreadForker { | |||||
public void go() { | |||||
fork(1000); | |||||
fork(500); | |||||
fork(200); | |||||
fork(100); | |||||
} | |||||
void fork(long sleep) { | |||||
new NamedThread(sleep).start(); | |||||
} | |||||
} | |||||
class NamedThread implements Runnable { | |||||
private long sleep; | |||||
private String name; | |||||
private Thread thread; | |||||
private int num = 0; | |||||
public NamedThread(long sleep) { | |||||
this.sleep = sleep; | |||||
} | |||||
public void start() { | |||||
if (thread == null) { | |||||
thread = new Thread(this); | |||||
name = thread.getName(); | |||||
thread.start(); | |||||
} | |||||
} | |||||
public void run() { | |||||
while (true) { | |||||
AJDBThreads.currentThread = name; | |||||
System.out.println("\n********** " + AJDBThreads.currentThread + ":" + (num++) + "\n"); | |||||
try { | |||||
Thread.sleep(sleep); | |||||
} catch (Exception e) { | |||||
} | |||||
} | |||||
} | |||||
} |
//package debugger; | |||||
import com.sun.jdi.*; | |||||
import com.sun.jdi.event.*; | |||||
import com.sun.jdi.request.*; | |||||
import java.io.*; | |||||
import java.util.*; | |||||
import org.aspectj.tools.debugger.*; | |||||
public class ArgumentTester extends Tester { | |||||
public static void main(String[] args) { | |||||
new Main(new ArgumentTester(false), args); | |||||
} | |||||
public ArgumentTester(boolean b) { | |||||
super(b); | |||||
} | |||||
public String getClassName() { | |||||
return "Arguments"; | |||||
} | |||||
public boolean test() { | |||||
db(); | |||||
try { | |||||
setRunArgs("0 1 2"); | |||||
stopon(19); | |||||
stop(3); | |||||
startTest(); | |||||
setRunArgs("0 1 2 3 4 5 6"); | |||||
stopon(19); | |||||
stop(7); | |||||
startTest(); | |||||
quit(); | |||||
return true; | |||||
} catch (DebuggerException de) { | |||||
de.printStackTrace(); | |||||
} | |||||
return false; | |||||
} | |||||
protected void stop(final int max) { | |||||
d.addStopListener(new StopAdapter() { | |||||
int times = -1; | |||||
public void breakpointEvent(BreakpointEvent e) { | |||||
try { | |||||
String value = print("s") + ""; | |||||
String str = "\"" + times + "\""; | |||||
if ((times++) != -1) { | |||||
check(value.equals(str), value + "!=" + str); | |||||
} | |||||
if (times < max) { | |||||
cont(); | |||||
} else { | |||||
clear(19); | |||||
d.removeStopListener(this); | |||||
} | |||||
} catch (DebuggerException de) { | |||||
de(de); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
} |
//package debugger; | |||||
public class Arguments { | |||||
String[] args; | |||||
public static void main(String[] args) { | |||||
new Arguments(args).go(); | |||||
} | |||||
Arguments(String[] args) { | |||||
this.args = args; | |||||
} | |||||
void go () { | |||||
int i = -1; | |||||
String s = ""; | |||||
while ((++i) < args.length) { | |||||
s = args[i]; | |||||
System.out.println("[" + i + "] " + s); | |||||
} | |||||
} | |||||
} |
//package debugger; | |||||
import com.sun.jdi.*; | |||||
import com.sun.jdi.event.*; | |||||
import com.sun.jdi.request.*; | |||||
import java.io.*; | |||||
import java.util.*; | |||||
import org.aspectj.tools.debugger.*; | |||||
/** | |||||
* BreakpointTester.java | |||||
* | |||||
* | |||||
* Created: Wed Sep 06 15:53:29 2000 | |||||
* | |||||
* @author <a href="mailto:palm@parc.xerox.com"Jeffrey Palm</a> | |||||
*/ | |||||
public class BreakpointTester extends Tester { | |||||
public static void main(String[] args) { | |||||
new Main(new BreakpointTester(false), args); | |||||
} | |||||
public BreakpointTester(boolean d) { | |||||
super(d); | |||||
} | |||||
public String getClassName() { | |||||
return "TestClass"; | |||||
} | |||||
public boolean test() { | |||||
db(); | |||||
Vector locals = new Vector(); | |||||
Vector names = new Vector(); | |||||
names.add(""); | |||||
names.add("system"); | |||||
names.add("main"); | |||||
IntVector sizes = new IntVector(); | |||||
sizes.add(4); | |||||
sizes.add(3); | |||||
sizes.add(1); | |||||
Vector cases = new Vector(); | |||||
try { | |||||
stopin("main"); | |||||
stopin("a"); | |||||
stopin("b"); | |||||
//stopat("TestClassAspect", 41); | |||||
stopin("c"); | |||||
stopat("TestClassAspect", 54); | |||||
int i = 0; | |||||
locals = new Vector(); | |||||
locals.add("args"); | |||||
cases.add(new Case(PCKG + "TestClass.main", 5, 1, locals, names, sizes, (i++))); | |||||
locals = new Vector(); | |||||
cases.add(new Case(PCKG + "TestClass.a", -2, 3, locals, names, sizes, (i++))); | |||||
locals = new Vector(); | |||||
cases.add(new Case(PCKG + "TestClass.b", -2, 5, locals, names, sizes, (i++))); | |||||
// locals = new Vector(); | |||||
// locals.add("thisJoinPoint"); | |||||
// cases.add(new Case(PCKG + "TestClassAspect:41", 41, 6, locals, names, sizes, (i++))); | |||||
locals = new Vector(); | |||||
cases.add(new Case(PCKG + "TestClass.c", -2, 7, locals, names, sizes, (i++))); | |||||
locals = new Vector(); | |||||
locals.add("thisJoinPoint"); | |||||
cases.add(new Case(PCKG + "TestClassAspect:54", 54, 8, locals, names, sizes, (i++))); | |||||
stop(cases); | |||||
startTest(); | |||||
return true; | |||||
} catch (DebuggerException de) { de.printStackTrace(out); | |||||
} | |||||
return false; | |||||
} | |||||
} |
//package debugger; | |||||
/** | |||||
* Main.java | |||||
* | |||||
* | |||||
* Created: Wed Sep 06 15:54:41 2000 | |||||
* | |||||
* @author <a href="mailto:palm@parc.xerox.com"Jeffrey Palm</a> | |||||
*/ | |||||
public class Main { | |||||
public Main(Tester tester, String[] args) { | |||||
String classPath = getArg(args, "-classpath"); | |||||
String root = getArg(args, "-root"); | |||||
String verbose = getSwitch(args, "-verbose"); | |||||
String dbg = getSwitch(args, "-debug"); | |||||
boolean debug = !dbg.equals(""); | |||||
Tester.setClassPath(classPath); | |||||
Tester.setRoot(root); | |||||
if (verbose.equals("true")) { | |||||
Tester.setVerbose(true); | |||||
} | |||||
if (dbg.equals("true")) { | |||||
Tester.setDebug(true); | |||||
} | |||||
if (!root.equals("")) { | |||||
Tester.setRoot(root); | |||||
} | |||||
tester.go(args); | |||||
// new BreakpointTester(debug).go(args); | |||||
// new ThreadTester(debug).go(args); | |||||
// new ArgumentTester(debug).go(args); | |||||
} | |||||
static void fail(Object o) { | |||||
System.err.println("ERROR: " + o); | |||||
System.exit(1); | |||||
} | |||||
public static String getSwitch(String[] args, String arg) { | |||||
return getArg(args, arg, false); | |||||
} | |||||
public static String getArg(String[] args, String arg) { | |||||
return getArg(args, arg, true); | |||||
} | |||||
public static String getArg(String[] args, String arg, boolean needArg) { | |||||
String s = ""; | |||||
for (int i = 0; i < args.length; i++) { | |||||
if (args[i].equals(arg)) { | |||||
try { | |||||
s = args[i+1]; | |||||
break; | |||||
} catch (Exception e) { | |||||
if (needArg) { | |||||
e.printStackTrace(); | |||||
fail("Need to set a value for switch " + arg); | |||||
} | |||||
} | |||||
if (needArg) { | |||||
return s; | |||||
} else { | |||||
return "true"; | |||||
} | |||||
} | |||||
} | |||||
return ""; | |||||
} | |||||
} |
SHELL = bash | |||||
### Fill these in ####################### | |||||
aspectj = C:/aspectj | |||||
root = C:/aspectj/tests | |||||
your_classpath = C:/aspectj/tests/lib#C:/classes | |||||
tools_jar = C:/apps/jdk1.3/lib/tools.jar | |||||
aspectj_lib = C:/aspectj/lib | |||||
########################################## | |||||
aspectj_src = $(aspectj)/src | |||||
jar_path = C:/apps/aspectj0.7/lib | |||||
aspectj_jars = $(jar_path)/aspectjrt.jar;$(jar_path)/aspectjtools.jar | |||||
path = debugger | |||||
tests = $(aspectj)/tests | |||||
d = $(tests)/lib | |||||
lib = $(d)/$(path) | |||||
srcpath = $(tests) | |||||
classpath = "$(d);$(your_classpath);$(aspectj_lib);$(tools_jar)" | |||||
javac_opts = -d $(d) $(g) -sourcepath $(srcpath) -classpath $(classpath) | |||||
javac_compile = javac $(javac_opts) | |||||
java_ex = Main | |||||
java_main = debugger.$(java_ex) | |||||
java_main_class = $(java_ex).class | |||||
java_opts = -classpath $(classpath) | |||||
java_args = | |||||
g = -g | |||||
ajc_compile = ajc $(g) -d $(your_classpath) -workingdir $(root)/ajworkingdir | |||||
javac_names = \ | |||||
Main\ | |||||
Tester\ | |||||
BreakpointTester\ | |||||
ThreadTester | |||||
javac_srcs = $(foreach name, $(javac_names), $(name).java) | |||||
javac_classes = $(foreach name, $(javac_names), $(d)/$(path)/$(name).class) | |||||
ajc_names = \ | |||||
TestClass\ | |||||
AJDBThreads | |||||
ajc_srcs = $(foreach name, $(ajc_names), $(name).java) | |||||
ajc_classes = $(foreach name, $(ajc_names), $(d)/$(path)/$(name).class) | |||||
test_args = -classpath "$(your_classpath);$(aspectj_jars)" -root $(root) | |||||
.SUFFIXES: .java .class | |||||
all: classes aspects | |||||
classes: | |||||
$(javac_compile) $(javac_srcs) | |||||
aspects: | |||||
$(ajc_compile) $(ajc_srcs) | |||||
run: | |||||
java $(java_opts) $(java_main) $(java_args) | |||||
clean: | |||||
rm -Rf *~* $(lib)/*.class | |||||
srcclean: | |||||
rm -Rf *~* *.ajsym #* | |||||
db: | |||||
make -C ../../debugger | |||||
test: | |||||
java $(java_opts) $(java_main) $(test_args) | |||||
.java.class: | |||||
$(javac_compile) $? |
//package debugger; | |||||
public class TestClass { | |||||
public static void main(String[] args) { | |||||
new TestClass().go(); | |||||
} | |||||
void go() { | |||||
String s = "s"; | |||||
String ss = "ss"; | |||||
String sss = "sss"; | |||||
a(); | |||||
} | |||||
void a() { | |||||
int i3 = 3; | |||||
b(); | |||||
} | |||||
void b() { | |||||
int i1 = 1; | |||||
int i2 = 2; | |||||
c(); | |||||
} | |||||
void c() { | |||||
String c = "c"; | |||||
System.out.println(c); | |||||
} | |||||
} | |||||
aspect TestClassAspect of eachobject(instanceof(TestClass)) { | |||||
pointcut a(): receptions(* a(..)) && instanceof(TestClass); | |||||
pointcut b(): receptions(* b(..)) && instanceof(TestClass); | |||||
pointcut c(): receptions(* c(..)) && instanceof(TestClass); | |||||
before(): a() { | |||||
System.out.println("before a"); | |||||
} | |||||
before(): b() { | |||||
System.out.println("before b"); | |||||
} | |||||
before(): c() { | |||||
System.out.println("before c"); | |||||
} | |||||
after(): a() { | |||||
long l = 123; | |||||
System.out.println("after a"); | |||||
} | |||||
after(): b() { | |||||
System.out.println("after b"); | |||||
} | |||||
after(): c() { | |||||
System.out.println("after c"); | |||||
} | |||||
} |
//package debugger; | |||||
import com.sun.jdi.*; | |||||
import com.sun.jdi.event.*; | |||||
import com.sun.jdi.request.*; | |||||
import java.io.*; | |||||
import java.util.*; | |||||
import org.aspectj.tools.debugger.*; | |||||
/** | |||||
* Tester.java | |||||
* | |||||
* | |||||
* Created: Wed Sep 06 15:53:29 2000 | |||||
* | |||||
* @author <a href="mailto:palm@parc.xerox.com"Jeffrey Palm</a> | |||||
*/ | |||||
public abstract class Tester extends DebuggerAdapter implements DebuggerListener { | |||||
public abstract boolean test(); | |||||
public abstract String getClassName(); | |||||
public static String ROOT = "."; //"C:/aspectj/tests/debugger"; | |||||
public final static String PCKG = ""; //"debugger."; | |||||
public final static String PATH = ""; //"debugger/"; | |||||
public String FILE = getClassName() + ".java"; | |||||
public String CLASS = PCKG + getClassName(); | |||||
public static String classPath = ".."; | |||||
public int time = 0; | |||||
public static boolean verboseSuccess = false; //true; | |||||
protected AJDebugger d; | |||||
protected PrintStream out = System.out; | |||||
protected PrintStream err = System.err; | |||||
protected boolean mutex; | |||||
protected boolean good = true; | |||||
protected Vector failures = new Vector(); | |||||
protected static boolean debug = false; //true; | |||||
public static void setDebug(boolean _debug) { | |||||
debug = _debug; | |||||
} | |||||
protected final static String errFile = "err.txt"; | |||||
public Tester(boolean debug) { | |||||
this.debug = debug; | |||||
this.classPath = classPath; | |||||
if (debug()) { | |||||
outln("Testing..." + getClassName()); | |||||
} | |||||
setErr(); | |||||
} | |||||
public Tester() { | |||||
this(false); | |||||
} | |||||
public void go(String[] args){ | |||||
good &= test(); | |||||
sd(); | |||||
if (!good) { | |||||
outln("The test failed with the following:\n" + d.iter(failures)); | |||||
} | |||||
} | |||||
public boolean debug() { | |||||
return debug | false; | |||||
} | |||||
public static void setClassPath(String _classPath) { | |||||
classPath = _classPath; | |||||
} | |||||
public static void setRoot(String root) { | |||||
ROOT = root; | |||||
} | |||||
public static void setVerbose(boolean _verboseSuccess) { | |||||
verboseSuccess = _verboseSuccess; | |||||
} | |||||
/****************************** Tests ******************************/ | |||||
protected HashMap breaks = new HashMap(); | |||||
static class IntVector extends Vector { | |||||
public void add(int i) { | |||||
super.add(new Integer(i)); | |||||
} | |||||
} | |||||
protected void quit() throws DebuggerException { | |||||
db("Quitting tester..." + getClassName()); | |||||
d.quitCommand(); | |||||
//d.exit(false); | |||||
d = null; | |||||
db("Quit."); | |||||
} | |||||
protected Value print(Object obj) throws DebuggerException { | |||||
return d.printCommand(obj); | |||||
} | |||||
protected void stopin(String method) throws DebuggerException { | |||||
stopin(getClassName(), method); | |||||
} | |||||
protected void stopin(String className, String method) throws DebuggerException { | |||||
d.stopInCommand(PCKG + className, method); | |||||
} | |||||
protected void stopat(int line) throws DebuggerException { | |||||
stopat(CLASS, line); | |||||
} | |||||
protected void stopat(String className, int line) throws DebuggerException { | |||||
d.stopAtCommand(PCKG + className, line); | |||||
} | |||||
protected void stopon(int line) throws DebuggerException { | |||||
d.stopOnCommand(PATH + FILE, line); | |||||
} | |||||
protected void clear(int line) throws DebuggerException { | |||||
d.clearOnCommand(PATH + FILE, line); | |||||
} | |||||
protected void clear(String className, int line) throws DebuggerException { | |||||
d.clearAtCommand(PCKG + className, line); | |||||
} | |||||
protected void clear(String method) throws DebuggerException { | |||||
clear(CLASS, method); | |||||
} | |||||
protected void clear(String className, String method) throws DebuggerException { | |||||
d.clearInCommand(PCKG + className, method); | |||||
} | |||||
protected void step() throws DebuggerException { | |||||
d.stepCommand(); | |||||
} | |||||
protected void stepi() throws DebuggerException { | |||||
d.stepiCommand(); | |||||
} | |||||
protected void stepup() throws DebuggerException { | |||||
d.stepUpCommand(); | |||||
} | |||||
protected void next() throws DebuggerException { | |||||
d.nextCommand(); | |||||
} | |||||
protected void de(Throwable de) { | |||||
de.printStackTrace(); | |||||
good = false; | |||||
} | |||||
static class Case { | |||||
String msg; | |||||
int line; | |||||
int frames; | |||||
List locals; | |||||
List names; | |||||
List sizes; | |||||
int time; | |||||
public Case(String msg, int line, int frames, List locals, List names, List sizes, int time) { | |||||
this.msg = msg; | |||||
this.line = line; | |||||
this.frames = frames; | |||||
this.locals = locals; | |||||
this.names = names; | |||||
this.sizes = sizes; | |||||
this.time = time; | |||||
} | |||||
public String toString() { | |||||
return | |||||
"msg=" + msg + | |||||
" line=" + line + | |||||
" frames=" + frames + | |||||
" locals=" + locals + | |||||
" names=" + names + | |||||
" sizes=" + sizes + | |||||
" time=" + time; | |||||
} | |||||
} | |||||
protected void stop(final Vector cases) { | |||||
d.addStopListener(new StopAdapter() { | |||||
public void breakpointEvent(BreakpointEvent e) { | |||||
try { | |||||
if (cases.size() > time) { | |||||
Case caze = (Case) cases.get(time); | |||||
//System.out.println(caze); | |||||
//System.out.println(d.format(e)); | |||||
String msg = caze.msg; | |||||
int line = caze.line; | |||||
int frames = caze.frames; | |||||
List locals = caze.locals; | |||||
List names = caze.names; | |||||
List sizes = caze.sizes; | |||||
int caseTime = caze.time; | |||||
check(time == caseTime, "Out of sync " + time + ":" + caseTime); | |||||
int lineNumber = d.lineNumber(e.location()); | |||||
String methodName = d.methodName(e); | |||||
if (lineNumber > 0) { | |||||
check(lineNumber == line, "Lines don't match " + | |||||
lineNumber + ":" + line); | |||||
} else { | |||||
check(msg.endsWith(methodName), | |||||
"Method '" + msg + "' does not match '" + methodName + "'."); | |||||
} | |||||
msg(msg + ": " + d.format(e)); | |||||
threads(names, sizes); | |||||
where("", frames); | |||||
locals(locals); | |||||
cont(); | |||||
} | |||||
} catch (/*Debugger*/Exception de) { | |||||
de.printStackTrace(out); | |||||
good = false; | |||||
} | |||||
time++; | |||||
}}); | |||||
} | |||||
protected boolean locals(List locals) throws DebuggerException { | |||||
List vars = d.localsCommand(); | |||||
boolean allGood = true; | |||||
for (int i = 0; i < locals.size(); i++) { | |||||
boolean there = false; | |||||
if (vars != null) { | |||||
for (int j = 0; j < vars.size(); j++) { | |||||
LocalVariable lv = (LocalVariable) vars.get(j); | |||||
if (lv.name().equals(locals.get(i))) { | |||||
there = true; | |||||
} | |||||
} | |||||
} | |||||
allGood &= check(there, "The local variable '" + locals.get(i) + | |||||
"' was not found in\n" + d.locals(vars)); | |||||
} | |||||
return allGood; | |||||
} | |||||
protected void threads(List names, List sizes) throws DebuggerException { | |||||
for (int i = 0; i < names.size(); i++) { | |||||
List threads = d.threadsCommand(names.get(i) + ""); | |||||
check(threads.size() == ((Integer) sizes.get(i)).intValue(), | |||||
"need " + sizes.get(i) + " thread(s) in '" + names.get(i) + "':\n" + d.threads(threads)); | |||||
} | |||||
} | |||||
protected void where(String name, int frames) throws DebuggerException { | |||||
try { | |||||
List stack = d.whereCommand(name); | |||||
check(stack.size() == frames, | |||||
"need " + frames + " frame(s) in '" + name + "':\n" + d.frames(stack)); | |||||
} catch (WhereRequest.BadThreadStateException e) { | |||||
//TODO | |||||
} | |||||
} | |||||
/****************************** DebuggerListener ******************************/ | |||||
public void requestSetEvent(RequestEvent re) { | |||||
msg("Set " + re.getRequest()); | |||||
} | |||||
public void requestClearEvent(RequestEvent re) { | |||||
msg("Cleared " + re.getRequest()); | |||||
} | |||||
public void requestDeferredEvent(RequestEvent re) { | |||||
} | |||||
public void requestFailedEvent(RequestEvent re) { | |||||
msg("Unable to set " + re.getRequest() + " : " + re.getErrorMessage()); | |||||
} | |||||
/****************************** Misc. ******************************/ | |||||
protected void setErr() { | |||||
try { | |||||
err = new PrintStream(new BufferedOutputStream(new FileOutputStream(errFile)), true) { | |||||
public void write(int b) { | |||||
super.write(b); | |||||
} | |||||
}; | |||||
} catch (IOException ioe) { | |||||
} | |||||
System.setErr(err); | |||||
} | |||||
protected void setOut() { | |||||
PrintStream redirect = new PrintStream(new OutputStream() { | |||||
public void write(int b) {} | |||||
}); | |||||
System.setOut(redirect); | |||||
} | |||||
protected void down() { | |||||
mutex = true; | |||||
} | |||||
protected void up() { | |||||
mutex = false; | |||||
} | |||||
protected void stall() { | |||||
stall(getMaxStallTime()); | |||||
} | |||||
protected long getMaxStallTime() { | |||||
return (long) 20000; | |||||
} | |||||
protected void stall(long time) { | |||||
long start = System.currentTimeMillis(); | |||||
while (mutex) { | |||||
if ((System.currentTimeMillis() - start) > time) { | |||||
errln("Stalled for too long"); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
protected void cont() { | |||||
try { | |||||
d.contCommand(); | |||||
} catch (DebuggerException de) { | |||||
} | |||||
} | |||||
protected void sd() { | |||||
if (d != null) { | |||||
d.shutDown(); | |||||
} | |||||
d = null; | |||||
} | |||||
protected void db(Object o) { | |||||
if (debug()) { | |||||
System.out.println(o); | |||||
} | |||||
} | |||||
protected void db() { | |||||
sd(); | |||||
d = new AJDebugger(this, false); | |||||
d.addDebuggerListener(this); | |||||
ex("use " + ROOT); | |||||
} | |||||
protected void stop() { | |||||
stop(5000); | |||||
} | |||||
protected void stop(long time) { | |||||
long start = System.currentTimeMillis(); | |||||
while (!d.isAtBreakpoint()) { | |||||
if ((System.currentTimeMillis() - start) > time) { | |||||
errln("Stopped for too long"); | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
protected Object ex(String command) { | |||||
return d.execute(command); | |||||
} | |||||
public void outln(Object o) { | |||||
if ((o+"").startsWith("Initializing ajdb...")) { | |||||
return; | |||||
} | |||||
out(o); | |||||
out("\n"); | |||||
} | |||||
protected void out(Object o) { | |||||
out.print(o); | |||||
out.flush(); | |||||
} | |||||
protected void err(Object o) { | |||||
err.print(o); | |||||
err.flush(); | |||||
} | |||||
protected void errln(Object o) { | |||||
err(o); | |||||
err("\n"); | |||||
} | |||||
protected boolean check(boolean b, String msg) { | |||||
if (!b) { | |||||
outln("<<FAIL>> " + msg); | |||||
good = false; | |||||
failures.add(msg); | |||||
} else if (verboseSuccess) { | |||||
outln("<<SUCESS>> " + msg); | |||||
} | |||||
return b; | |||||
} | |||||
protected boolean check(Object o, String msg) { | |||||
return check(o != null, msg); | |||||
} | |||||
protected void msg(Object o) { | |||||
if (debug()) { | |||||
outln(o); | |||||
} else { | |||||
err.println(o); | |||||
} | |||||
} | |||||
private String runArgs = ""; | |||||
public String getRunArgs() { | |||||
return runArgs; | |||||
} | |||||
public void setRunArgs(String runArgs) { | |||||
this.runArgs = runArgs; | |||||
} | |||||
private final String _getArgs() { | |||||
String args = getRunArgs(); | |||||
if (args != null && !args.equals("") && !args.startsWith(" ")) { | |||||
args = " " + args; | |||||
} | |||||
return args; | |||||
} | |||||
protected void startTest() { | |||||
String cmd = "run " + classPath() + " " + CLASS + _getArgs(); | |||||
startTest(cmd); | |||||
} | |||||
protected static String classPath() { | |||||
if (classPath == null || classPath.equals("")) { | |||||
return ""; | |||||
} | |||||
return "-classpath \"" + classPath + "\""; | |||||
} | |||||
protected void startTest(String cmd) { | |||||
d.addVMListener(new VMAdapter() { | |||||
public void vmDisconnectEvent(VMDisconnectEvent e) { | |||||
msg("Done"); | |||||
up(); | |||||
}}); | |||||
ex(cmd); | |||||
down(); | |||||
stall(); | |||||
} | |||||
} |
//package debugger; | |||||
import com.sun.jdi.*; | |||||
import com.sun.jdi.event.*; | |||||
import com.sun.jdi.request.*; | |||||
import java.io.*; | |||||
import java.util.*; | |||||
import org.aspectj.tools.debugger.*; | |||||
/** | |||||
* ThreadTester.java | |||||
* | |||||
* | |||||
* Created: Wed Sep 27 13:56:44 2000 | |||||
* | |||||
* @author <a href="mailto:palm@parc.xerox.com"Jeffrey Palm</a> | |||||
*/ | |||||
public class ThreadTester extends Tester { | |||||
public static void main(String[] args) { | |||||
new Main(new ThreadTester(false), args); | |||||
} | |||||
public ThreadTester(boolean d) { | |||||
super(d); | |||||
} | |||||
public String getClassName() { | |||||
return "AJDBThreads"; | |||||
} | |||||
public boolean test() { | |||||
db(); | |||||
try { | |||||
stopon(43); | |||||
stop1(); | |||||
startTest(); | |||||
quit(); | |||||
return true; | |||||
} catch (DebuggerException de) { | |||||
de.printStackTrace(); | |||||
} | |||||
return false; | |||||
} | |||||
protected void stop1() { | |||||
d.addStopListener(new StopAdapter() { | |||||
int times = 0; | |||||
int stopTimes = 0; | |||||
int max = 5; | |||||
int stopMax = 3; | |||||
String thread = ""; | |||||
Pair[] pairs = new Pair[max]; | |||||
class Pair { | |||||
String thread; | |||||
int time; | |||||
Pair(String thread, int time) { | |||||
this.thread = thread; | |||||
this.time = time; | |||||
} | |||||
} | |||||
public void breakpointEvent(BreakpointEvent e) { | |||||
try { | |||||
String threadName = d.getDefaultThread().name(); | |||||
msg("stop times=" + times + " thread=" + threadName); | |||||
if ((++times) < max) { | |||||
thread = threadName; | |||||
Pair pair = new Pair(thread, times); | |||||
pairs[times] = pair; | |||||
step(); | |||||
} else { | |||||
quit(); | |||||
} | |||||
} catch (DebuggerException de) { | |||||
de(de); | |||||
} | |||||
} | |||||
public void stepEvent(StepEvent se) { | |||||
try { | |||||
ThreadReference threadRef = d.getDefaultThread(); | |||||
check(pairs[times].thread.equals(thread), "Should step in *one* thread"); | |||||
msg("\ttimes=" + times + ":" + stopTimes + " thread=" + threadRef.name()); | |||||
if ((++stopTimes) < stopMax) { | |||||
step(); | |||||
} else { | |||||
stopTimes = 0; | |||||
cont(); | |||||
} | |||||
} catch (DebuggerException de) { | |||||
de(de); | |||||
} | |||||
} | |||||
}); | |||||
} | |||||
protected long getMaxStallTime() { | |||||
return (long) 3 * super.getMaxStallTime(); | |||||
} | |||||
} |
public class AJDBClass { | |||||
public int publicInt = 0; | |||||
protected int protectedInt = 1; | |||||
private int privateInt = 2; | |||||
/*package*/ int packageInt = 3; | |||||
public AJDBClass() {} | |||||
/*package*/ AJDBClass(int i) {} | |||||
protected AJDBClass(byte b) {} | |||||
private AJDBClass(String s) {} | |||||
{ | |||||
publicInt = 13; | |||||
} | |||||
public static void main(String[] args) { | |||||
System.out.println("Starting..."); | |||||
new AJDBClass().go(); | |||||
System.out.println("Done."); | |||||
} | |||||
void go() { | |||||
int j = 1; | |||||
String string = "string"; | |||||
byte b = (byte)9; | |||||
long l = 123123123; | |||||
double d = 123.123; | |||||
short s = (short)4; | |||||
char c = 'c'; | |||||
Object o = null; | |||||
Integer integer = new Integer(13); | |||||
a(); | |||||
b(); | |||||
c(); | |||||
d(); | |||||
} | |||||
public void a() { | |||||
System.out.println("a"); | |||||
} | |||||
protected void b() { | |||||
System.out.println("b"); | |||||
} | |||||
private void c() { | |||||
System.out.println("c"); | |||||
} | |||||
void d() { | |||||
System.out.println("d"); | |||||
} | |||||
} | |||||
aspect Aspect { | |||||
pointcut ours(): instanceof(AJDBClass); | |||||
pointcut allReceptions(): receptions(void *(..)) && ours(); | |||||
pointcut allExecutions(): executions(void *(..)) && within(AJDBClass); | |||||
pointcut allCalls(): calls(void AJDBClass.*(..)); | |||||
pointcut allCallsTo(): callsto(receptions(void *(..)) && instanceof(AJDBClass)); | |||||
static before(): allReceptions() { | |||||
System.out.println("before receptions: " + thisJoinPoint); | |||||
} | |||||
static after(): allReceptions() { | |||||
System.out.println("after receptions: " + thisJoinPoint); | |||||
} | |||||
static around() returns void: allReceptions() { | |||||
System.out.println("around before receptions: " + thisJoinPoint); | |||||
proceed(); | |||||
System.out.println("around after receptions: " + thisJoinPoint); | |||||
} | |||||
static before(): allExecutions() { | |||||
System.out.println("before executions: " + thisJoinPoint); | |||||
} | |||||
static after(): allExecutions() { | |||||
System.out.println("after executions: " + thisJoinPoint); | |||||
} | |||||
static around() returns void: allExecutions() { | |||||
System.out.println("around before executions: " + thisJoinPoint); | |||||
proceed(); | |||||
System.out.println("around after executions: " + thisJoinPoint); | |||||
} | |||||
static before(): allCalls() { | |||||
System.out.println("before calls: " + thisJoinPoint); | |||||
} | |||||
static after(): allCalls() { | |||||
System.out.println("after calls: " + thisJoinPoint); | |||||
} | |||||
static around() returns void: allCalls() { | |||||
System.out.println("around before calls: " + thisJoinPoint); | |||||
proceed(); | |||||
System.out.println("around after calls: " + thisJoinPoint); | |||||
} | |||||
static before(): allCallsTo() { | |||||
System.out.println("before callsTo: " + thisJoinPoint); | |||||
} | |||||
static after(): allCallsTo() { | |||||
System.out.println("after callsTo: " + thisJoinPoint); | |||||
} | |||||
static around() returns void: allCallsTo() { | |||||
System.out.println("around before callsTo: " + thisJoinPoint); | |||||
proceed(); | |||||
System.out.println("around after callsTo: " + thisJoinPoint); | |||||
} | |||||
} |
import org.aspectj.tools.ajdb.Main; | |||||
import org.aspectj.debugger.tty.CommandLineDebugger; | |||||
import org.aspectj.debugger.base.*; | |||||
import com.sun.jdi.*; | |||||
import com.sun.jdi.event.*; | |||||
import java.io.*; | |||||
import java.util.*; | |||||
import org.aspectj.testing.Tester; | |||||
public class AJDBTest implements StopListener, VMListener { | |||||
String classpath; | |||||
{ | |||||
classpath = "\"" + Tester.outputDir(); | |||||
String javaClasspath = System.getProperty("java.class.path"); | |||||
if (javaClasspath != null) { | |||||
classpath += ";" + javaClasspath; | |||||
} | |||||
classpath += "\""; | |||||
} | |||||
protected String[] stringCommands() { | |||||
return new String[] { | |||||
"workingdir " + Tester.workingDir(), | |||||
"use " + "./new", | |||||
"stop on AJDBClass.java:24", | |||||
"run -classpath " + classpath + " AJDBClass", | |||||
}; | |||||
} | |||||
protected String getSourceName() { | |||||
return "AJDBClass.java"; | |||||
} | |||||
// Methods for VMListener | |||||
protected void death(VMDeathEvent e) { | |||||
System.out.println("*** Death: " + e); | |||||
} | |||||
protected void disconnect(VMDisconnectEvent e) { | |||||
System.out.println("*** Disconnect: " + e); | |||||
} | |||||
protected void start(VMStartEvent e) { | |||||
System.out.println("*** Start: " + e); | |||||
} | |||||
// Methods for StopListener | |||||
protected void access(AccessWatchpointEvent e) { | |||||
} | |||||
protected void breakpoint(BreakpointEvent e) { | |||||
checkLines((List) ex("where"), "next"); | |||||
} | |||||
protected void exception(ExceptionEvent e) { | |||||
} | |||||
protected void modification(ModificationWatchpointEvent e) { | |||||
} | |||||
protected void step(StepEvent e) { | |||||
List lines = (List) ex("where"); | |||||
checkLines(lines); | |||||
try { | |||||
StackFrame frame = (StackFrame) lines.get(0); | |||||
Location loc = frame.location(); | |||||
if (loc.sourceName().equals("Thread.java") && | |||||
loc.method().name().equals("exit")) { | |||||
isRunning = false; | |||||
} | |||||
} catch (Throwable t) {} | |||||
ex("next"); | |||||
} | |||||
public void checkLines(Collection lines, Object then) { | |||||
checkLines(lines); | |||||
if (then != null) ex(then); | |||||
} | |||||
public void checkLines(Collection lines) { | |||||
Iterator iter = lines.iterator(); | |||||
while (iter.hasNext()) { | |||||
StackFrame frame = (StackFrame) iter.next(); | |||||
String source = "no.source"; | |||||
try { | |||||
source = debugger.sourceName(frame.location()); | |||||
} catch (Throwable t) {} | |||||
int line = debugger.lineNumber(frame.location()); | |||||
if (source.equals(getSourceName())) { | |||||
Tester.check(line>0, "non-mapping line for " + frame); | |||||
} | |||||
} | |||||
} | |||||
// VMListener | |||||
public void vmDeathEvent(VMDeathEvent e) { | |||||
death(e); | |||||
} | |||||
public void vmDisconnectEvent(VMDisconnectEvent e) { | |||||
disconnect(e); | |||||
} | |||||
public void vmStartEvent(VMStartEvent e) { | |||||
start(e); | |||||
} | |||||
// StopListener | |||||
public final void accessWatchpointEvent(AccessWatchpointEvent e) { | |||||
access(e); | |||||
} | |||||
public final void breakpointEvent(BreakpointEvent e) { | |||||
breakpoint(e); | |||||
} | |||||
public final void exceptionEvent(ExceptionEvent e) { | |||||
exception(e); | |||||
} | |||||
public final void modificationWatchpointEvent(ModificationWatchpointEvent e) { | |||||
modification(e); | |||||
} | |||||
public final void stepEvent(StepEvent e) { | |||||
step(e); | |||||
} | |||||
AJDebugger debugger; | |||||
CommandLineDebugger ajdb; | |||||
public void realMain(String[] args) { | |||||
String fileName = null; | |||||
String[] newArgs = args; | |||||
if (args.length > 0) { | |||||
fileName = args[0]; | |||||
newArgs = new String[args.length-1]; | |||||
System.arraycopy(args, 1, newArgs, 0, newArgs.length); | |||||
} | |||||
realMain(fileName, newArgs); | |||||
} | |||||
private void realMain(String fileName, String[] args) { | |||||
debugger = (ajdb = new Main().debug(args)).getDebugger(); | |||||
debugger.addStopListener(this); | |||||
debugger.addVMListener(this); | |||||
ex(fileName == null ? commands() : commands(fileName)); | |||||
while (isRunning) { | |||||
//System.out.println(">>>>>>>> " + debugger.isRunning()); | |||||
} | |||||
} | |||||
private boolean isRunning = true; | |||||
public final Collection commands() { | |||||
Collection list = new Vector(); | |||||
String[] commands = stringCommands(); | |||||
for (int i = 0; i < commands.length; i++) { | |||||
list.add(commands[i]); | |||||
} | |||||
return list; | |||||
} | |||||
Object ex(Object command) { | |||||
return ajdb.executeCommand(command+""); | |||||
} | |||||
void ex(Collection list) { | |||||
Iterator iter = list.iterator(); | |||||
while (iter.hasNext()) { | |||||
ex(iter.next()); | |||||
} | |||||
} | |||||
final static String COMMENT = "#"; | |||||
final static String FILENAME = "script.txt"; | |||||
Collection commands(String fileName) { | |||||
Collection list = new Vector(); | |||||
try { | |||||
BufferedReader in = new BufferedReader(new FileReader(fileName)); | |||||
String line; | |||||
while ((line = in.readLine()) != null) { | |||||
line = line.trim(); | |||||
if (line.startsWith(COMMENT)) { | |||||
continue; | |||||
} | |||||
list.add(line); | |||||
} | |||||
in.close(); | |||||
} catch (IOException ioe) { | |||||
ioe.printStackTrace(); | |||||
System.exit(-1); | |||||
} | |||||
return list; | |||||
} | |||||
public static void main(String[] args) { | |||||
new AJDBTest().realMain(args); | |||||
} | |||||
} |