Name:
PID: (page 1)
Debuggers would be more accurately called program or process inspectors.
They don't actually remove any bugs. You (the programmer) have to do that. They tell us what's going in the running program so we can relate symptoms to our code. They also let us see some information that's often hidden away, like private fields or memory layout information.
interface StrChecker { boolean checkString(String s); }
class ListEx {
private static List<String> result = new ArrayList<>();
// Returns a new list that has only the elements of the
// input where the given StringChecker returns true
static List<String> filter(List<String> list, StrChecker sc) {
if(list.size() == 0) { return list; }
result.clear();
for(String s: list) {
if(sc.checkString(s)) {
result.add(s);
}
}
return result;
}
}
$ java -cp .:lib/* org.junit.runner.JUnitCore TestListExamples
JUnit version 4.13.2
.E.
Time: 0.011
There was 1 failure:
1) testFilter2(TestListExamples)
java.lang.AssertionError: expected:<[a]> but was:<[a, a]>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:120)
at org.junit.Assert.assertEquals(Assert.java:146)
at TestListExamples.testFilter2(TestListExamples.java:39)
FAILURES!!!
Tests run: 2, Failures: 1
Which assert/test is failing?
What's your best guess as to why? What's weird about the code in ListEx?
How many Lists do you think are created during that test? What's their contents and which variables or fields refer to them?
Name:
PID: (page 2)
$ javac -g -cp .:lib/* *.java -g is a special option that adds information for the debugger to the class files
jdb (Java Debugger) runs much like the java command, but when it starts up it gives a special prompt that lets us control evaluation
$ jdb -classpath .:lib/* org.junit.runner.JUnitCore TestListExamples (detail: -classpath not -cp)
Text on line after > are what I typed, the rest is the response. It's a special kind of “debugging shell”
stop at is a command that means "when you get to line 35 in TestListExamples, stop and let me run inspection commands”
> stop at TestListExamples:39
Deferring breakpoint TestListExamples:39.
It will be set after the class is loaded.
the program doesn't actually start running until we use the command “run”
> run
run org.junit.runner.JUnitCore TestListExamples
Set uncaught java.lang.Throwable
Set deferred uncaught java.lang.Throwable
>
VM Started: JUnit version 4.13.2
Set deferred breakpoint TestListExamples:39
.
Breakpoint hit: "thread=main", TestListExamples.testFilter2(), line=39 bci=104
39 assertEquals(expect1, result1);
here, the program is STOPPED, right before running line 39 (the line with the failing assert). Now we can inspect current values of variables, fields, and so on. The prompt looks a little different, too.
main[1] print s1
s1 = "[a, b, c]"
main[1] print s2 you fill in the blanks here – what's the current value?
main[1] print result1
main[1] locals
Method arguments:
Local variables:
s1 = instance of java.util.Arrays$ArrayList(id=717)
s2 = instance of java.util.Arrays$ArrayList(id=720)
expect1 = instance of java.util.Arrays$ArrayList(id=722)
expect2 = instance of java.util.Arrays$ArrayList(id=723)
result1 = instance of java.util.ArrayList(id=724)
result2 = instance of java.util.ArrayList(id=724)
main[1] print ListExamples.result (view a private field!)
ListExamples.result = "[a, a]"
(partial) output of help for jdb
run [class [args]] -- start execution of application's main class
where [<thread id> | all] -- dump a thread's stack
print <expr> -- print value of expression
dump <expr> -- print all object information
eval <expr> -- evaluate expression (same as print)
set <lvalue> = <expr> -- assign new value to field/variable/array element
locals -- print all local variables in current stack frame
stop at <class id>:<line> -- set a breakpoint at a line
catch [uncaught|caught|all] <class id>|<class pattern>
-- break when specified exception occurs
step -- execute current line
next -- step one line (step OVER calls)
cont -- continue execution from breakpoint
list [line number|method] -- print source code
javac -g ... compile options ...
Compile a java program with debugging information
java -classpath ... ClassName args ...
Run the java debugger, and use commands to the left to control and inspect
What's interesting about this locals output? How does that relate to what we noticed was weird on the front?