CS302, UW-Madison
Begin by starting a new project in Eclipse. Name your project DebugLab. Next, download the following files to your src folder inside the DebugLab folder.
Refresh the project, so that Eclipse will recognize the files (right-click on your DebugLab and select "Refresh" or press F5).
Whether you're a beginning programmer or have been programming for years, it is a near certainty that you'll make mistakes while programming. These mistakes range from common oversights, such as forgetting a brace or a variable declaration, to subtle errors that appear during the program's execution that take a lot more effort to fix! We all make mistakes, but there are differences between those that are experienced programmers and those that aren't. One obvious difference is that experienced programmers make fewer syntax errors because they know the language better. Experienced programmers also minimize the number of potential errors they introduce into their program by coding and testing it in steps, which we call incremental programming (what we've encouraged you to do in your programs).
A key difference between experienced and inexperienced programmers is how they go about finding and fixing the mistakes that they invariably make. You've heard us refer to execution errors as bugs. Why "bug"? The term was coined after a poor moth met an untimely death in a relay of one of very early computers causing its program to crash. (See more about it.) The process of finding and fixing errors we've referred to as debugging. In this lab we'll learn about the debugging tool in Eclipse that is used by experienced programmers. We'll go through the following basics of Eclipse's debugger:
We'll start with the Debug perspective. A Perspective in Eclipse is an arrangement of windows and tabs that are used for a particular purpose. For programming code, we use the Java perspective, which is how Eclipse typically looks. For debugging code, we use the Debug perspective, which looks like the following:
This shows you the general layout for the debugger that initially appears when used on the sample program for this lab.
To use the debugger, you'll need to switch to the Debug perspective. To do this, look at the upper-right corner of the Eclipse window where you'll see an icon labeled "Java" that looks like: . Now look to just to the left of that icon is another unlabeled icon that looks like: . We use this icon to open perspectives. Click it and select Debug to open the Debug perspective. Now the Debug icon appears: in the same location as the others.
You can return back to the Java perspective in the same way by clicking on the icon that opens perspectives and selecting Java. You can also switch between these perspectives by clicking on the corrresponding icon. Try this now by switching back and forth between "Debug" and "Java".
Now that we've learned how to get into the debug perspective, we'll next
learn how to start (resume), stop (suspend), and end (terminate) a program's
execution. Begin in the Java perspective and open
SampleProgram.java
in the editor window, and select the editor
window. From the Run menu select Debug As and then select
Java application. You should see that sample program is printing output
to the Console window. Take a look at the source code and you'll see that this
program will run for a long time, which give us time to learn how to control
the program's execution.
Switch to the Debug perspective, and then find the window labeled Debug in the upper left of Eclipse.
In the Debug window at the top is a toolbar of icons that includes three that we'll use: . These icons are the Resume, Suspend and Terminate buttons respectively. Press the Suspend button (two vertical yellow bars), and notice its effect on the program. Now press the Resume button (a yellow bar and a green arrow NOT the green circle with a white arrow which is for normal execution). Try suspending and resuming a few times. Finally, press the Terminate button (red square) to end the program.
The previous buttons gave us general control over the program's execution, but they don't enable us to easily stop at a specific point in our program. To stop at a specific line in the code, we use breakpoints.
Take a look at the editor window in the Debug perspective (middle left), and notice the grayish vertical bar at the far left of that window. A breakpoint is set by double clicking in this bar at the line where you want to stop (break) the program's execution. Try this out by double clicking in this region at the same height as the first call to System.out.println(). An icon appears in this bar indicating that you've set a breakpoint at this line of code (circled in red below):
Run the program in debug mode again (Run → Debug As → Java Application), and you'll see that execution of the program automatically suspends at the breakpoint. In fact, execution is suspended just before executing the line of code, highlighted with a green background, associated with the breakpoint. Also note that the icon in the bar changes to show that you've suspended at that breakpoint (circled in red below):
Insert another breakpoint at the method call to innerLoop() method and another at the final call to System.out.println() in the main method. Now click Resume. Click Resume a few more times. Do you understand what is happening? Tell your Lab TA what you think is happening.
Find the Breakpoints window in the upper right of the Eclipse window, which looks like (you may have to click on the Breakpoints tab to get it to show):
Each of the breakpoints you have set should appear in this window. This window provides information about each breakpoint that we have set including the class name, line number, and method name. This can help us find where the breakpoint is in our code. The fastest way to find the code corresponding to the breakpoint is to double click the entries in the Breakpoints window. This brings that line of code into the editor window. Note that if you click on a line of code in the editor window, its line number is displayed at the very bottom of the Eclipse window before the colon (the value after the colon is the column where the cursor is located). You can also turn on line numbers by right-clicking in the bar on the right of the editor window where the break points are set and selecting "Show Line Numbers" (Or do Window → Preferences → +General → +Editors → Text Editors and then check the "Show line numbers" option).
You can disable breakpoints by unchecking them in the Breakpoints window or by by right-clicking on its listing in the Breakpoints window and the selecting Disable. Try disabling the second call to System.out.println, and then Resume execution of your program and notice the effect. Also note that the icon in the editor window shows the breakpoint as hollow to indicate that it is disabled.
Now enable that breakpoint again in the analogous way.
You can also remove breakpoints. Let's remove the first breakpoint. Right-click on it in the Breakpoints window and select remove. Note that you could also have selected one or more breakpoints to be removed and then click on the grey X in the toolbar of the Breakpoints window.
You can also control break points by right-clicking on them in the bar of the editor window and then choosing the desired action. Also note that double clicking on a breakpoint in left bar of the editor window also removes it. Show your Lab TA which breakpoints you have set.
Once we've stopped at a breakpoint, often you'll want finer control over the the execution of the subsequent lines of code. The debugger has buttons that provide us "Step Into" , "Step Over" and "Step Return" control that look like: . They are found in the tool bar at the top of the debug window to the right of the buttons we used to resume and suspend execution.
Start the sample program again. If it is still running, do you remember which button to use to terminate it? Make sure that you have at least one breakpoint set or else the step buttons cannot be used.
First find the Step Over button and click it a few times. The debugger
will step through the source code one line at a time. If the line of code calls
a method, it will step "over" the method by executing it entirely rather than
line by line. You'll see this happen with the System.out.println() and
innerLoop()
method calls. Step Over treats a method call as a single
line of code -- executing it in one step and then moving on -- just like any
other line of code.
Now find the Step Into button and click it a few times. This, too,
will cause the debugger to step through the code line by line, but now it will
step "into" any methods that are called. This allows you to execute each line of
code in a method's body to take a closer look at what the method is doing. (Note
that if you've downloaded the code for the Java API you can then step into and
view the code of classes and methods provided by Java, such as
System.out.println()
.) Normally, you'd just step over code provided
by Java since you can trust it works as specified. The code you've written is
the best place to look for bugs.
Once you feel you understand how Step Into works, then find the Step Return button. Each time you press it, execution will continue through the current method and stop just after the method returns. Depending on how many methods you have stepped into, you may need to press this button several times before you are returned to the main method of the sample program that you're executing.
What we've seen so far is that the debugger gives us control over a program's execution to help us figure out what is going wrong. There's one last piece of the puzzle to make the debugger truely useful for helping us find and fix errors. We've learned from tracing code, that we step through the statements of our program and record the changes that are made to variables as each statement is executed. By recording the changes to the variables, we can see if our program is working the way we expect. If a variable gets a value other than what is expected, then we have an important clue that points suspicion at that line of code or ones that were executed before it. A debugger must also provide us a way to see the contents of variables.
If you stopped the sample program at the end of the last exercise, start it again and make sure you have at least one breakpoint set.
Move the mouse over one of the variable names in the editor window. You will see a window pop up that shows the value currently stored in that variable. Note this window will only pop up with the variable's value only if its code has executed and it is in the method that is currently active.
There's also a way to watch more than one variable without using the mouse. Find the Variables window in the upper right of the Eclipse window, which looks like the following if you've stopped the program in the innerLoop method:
You may need to click on the Variables tab if the Breakpoints window is on top. The Variables window shows you a list of the currently defined variables, along with the value stored in each. The Variables window can be used to view primitives, arrays (useful for program 2), and objects; far more than what is shown in the simple program above.
Click Resume a few more times and watch the values change in the Variables window.
You can also change a variable's value for testing. To do this, click on one of the variables in the Variables window. The value of that variable now appears in the editor region at the bottom of the Variables window. Change the value, and then save the change with by typing Ctrl+S. Notice that the value displayed for the variable (and the value stored in the variable's memory) has been updated.
You can also monitor how the values of an expression changes over time.
Recall that expressions are operands and operators that are combined to form
calculations or conditions. First, we need to open the Expressions
window by clicking in the menu Window → Show View and select Expressions. Now
highlight and copy (ctrl-C) in the source code displayed in the editor window
the expression j < 10000
in the for loop of the innerLoop
method. Once you've copied the expression, then right click on the "Expressions window"
and click on "Add Watch Expression". Paste (ctrl-V) the copied expression into
the text area of the pop-up window that appears and click Ok. Here's what the
Expressions window looks like:
Now you'll be able to see the value of this expression as it changes during the execution of your program. If the expression has not been executed or it is out of scope, the expression's Value might be listed as an error, which you can ignore. Step through your program until your expression widow matches what is shown above.
Tell your Lab TA when you've finished the tutorial.Spend no more than 15 minutes on this task.
Now let's put to use the Eclipse debugging facilities you've just learned.
We'll start with a simple buggy program, StringBugs.java
, that you
could probably fix by just carefully looking at the code, but the purpose of
this task is to practice using Eclipse's debugger. Just glance at the code to
notice that it has one method to count the number of occurrences of a character
in a string and another to reverse a string. Run the program to see how it
behaves and come up with a set of test cases to test the code.
Tell your Lab TA your test cases you'll use.
Now use the debugger to step through the code (set one or more break points to do this). Correct the code as you discover the bugs while stepping through your program. Each method requires 2 or more small changes to fix the bugs. While working on the reverseString method use the debugger to view the swap array contents by clicking on the plus symbol next to the array's name in the "Variables" window. Tell your Lab TA the bugs you've fixed before moving on to the next task.
In lab 3 you debugged the Guess.java program by adding statements to printout information to help you determine what was wrong with the code. For this task, debug the Guess2.java program using Eclipse's debugger instead of print statements as you did in lab 3. We've put new errors in the program to make it a bit harder. Write down what features of Eclipse's debugger you use to find the errors. When you've fixed the bugs, tell your Lab TA those features of Eclipse's debugger that you found most useful for finding and fixing the bugs.
In the time that remains, debug the program, BuggyQuilt.java
,
that implements the quilt program from
lab 6. Use
the debugger as the primary tool for doing this debugging and use the view
variables feature to view the contents of the 2-D arrays. Click on the plus
next to the array variable's name in the "Variables" window.
Tell your lab TA which
bugs you were able to find and fix before the lab ends..