USING THE ECLIPSE DEBUGGER

updated: 8/6/18

This tutorial assumes that you have previously completed the Getting Started with Eclipse tutorial. Since much of what you’re going to do for this tutorial is identical to what you’ve done for that tutorial, I will refrain from providing all the details this time. If you don’t remember the details of how to do something, look it up in the previous tutorial.

This tutorial uses x: to refer to the drive that you’re saving your work to. In the lab, x: should be replaced by the USB drive (assuming that you’re using a USB flash drive storage device). At home, x: should be replaced by the USB drive or the hard drive, whichever you prefer.

Whenever you are asked to perform an action (left column below) that you’ve already done before, I will refrain from providing the supplemental information (right column below). If you don’t remember the details of how to do something, look for it earlier in the tutorial. I expect you to have to look up a lot of previously covered material. This is my attempt to force you to memorize how to do things.

Actions Supplemental Information
Load Eclipse.
Create a project named tutorial2. In creating a tutorial2 project, Eclipse will 1) create a tutorial2 folder and put it in your workspace folder, and 2) create a .project file and put it in your tutorial2 folder.
Within your tutorial2 project, create a source code file named MouseDriver.java and enter this text: public class MouseDriver

{

public static void main(String[] args)

{

String temp = “stan”;

Mouse mickey = new Mouse(temp + “dard”, 100, 10);

Mouse fivel = new Mouse(“standard”, 100, 10);

mickey.printStatus();

mickey.simulateGrowth(4);

mickey.printStatus();

fivel.simulateGrowth(4);

if (mickey.equals(fivel))

{

System.out.println(“They’re equal”);

}

} // end main

} // end class MouseDriver

Save the source file.
Within your tutorial2 project, create a source code file named Mouse.java and enter this text: public class Mouse

{

private String variety; // standard, hairless, etc.

private int weight; // the mouse’s weight in grams

private int growthRate; // % that mouse grows each day

private int days; // # of simulated days so far

public Mouse(String v, int w, int gR)

{

variety = v; weight = w; growthRate = gR;

} // end Mouse constructor

public void simulateGrowth(int d)

{

days += d;

while ((d > 0) || (weight > 0))

{

weight += growthRate/100 * weight;

d–;

}

} // end simulateGrowth

public void printStatus()

{

System.out.println(“After ” + days + ” days, ” +

” weight = ” + weight + “.”);

} // end printStatus

public boolean equals(Mouse otherMouse)

{

boolean varietyCheck, weightCheck;

varietyCheck = (variety == otherMouse.variety);

weightCheck = (weight == otherMouse.weight);

return varietyCheck && weightCheck;

} // end equals

} // end class Mouse

Save the source file.
Build (i.e., compile) the tutorial2 project.
If necessary, fix compilation errors.
Run the project. This should appear in the output pane:

After 0 days, weight = 100.

Study the main method to figure out if the output is correct. Note that the main method contains two calls to the printStatus method. You may safely assume that the first call to printStatus was responsible for printing the above status message.

But why doesn’t main’s second call to printStatus generate a second status message? The second status message is missing because, in executing the program, the Java Virtual Machine (JVM) never reaches the second call to printStatus.

Terminate the program. Note the red button at the top of your output window. The red button’s redness indicates that the program is still running. So why is the program still running? Hmmm … We’ll figure that out eventually. For now, terminate the program by clicking the red button. (Makes sense, right? Red for stop.)

As the program terminates, the red button should become non-red.

Switch to the debug perspective. Click the Window menu.

Select Perspective / Open Perspective.

Select Debug from the pop-up sub-menu.

That should cause the window’s appearance to change to the debug “perspective.”

You should see Debug and Java buttons in the top-right corner of your window. For practice purposes, click the Java button. That should cause your window to revert back to its normal mode, the Java perspective. Click the Debug button to return to the debug perspective.

Display the MouseDriver.java file. In your debug perspective, you should see tabs for your project’s source code files in the middle left pane. More specifically, you should see Mouse.java and MouseDriver.java tabs. Click the MouseDriver.java tab. Your window should look approximately like this:

Understand the debug perspective. Note the five panes in the debug perspective. The top left pane is called the Debug pane. The Debug pane shows the status of the currently running program or the status of the just-completed program. An exit value of 0 means the program ended normally. An exit value of 1 means the program ended abnormally.

The top right pane shows two tabbed panes. The Variables pane shows the current state of program variables while the program is running. The Breakpoints pane shows the status of breakpoints within the program. A breakpoint is a marker. When the debugger reaches a breakpoint marker, it stops executing the program and waits for the user’s next instruction.

The middle right pane is the Outline pane. It shows the instance variables and methods for the source code file that’s currently chosen in the middle left pane.

The bottom pane shows two tabbed panes – Console and Tasks. The Console pane shows the console-based output generated by the program and the input entered by the user.

Set a breakpoint. In debug mode, you’ll need to specify one or more lines in your program as breakpoints so that when you run your program, the debugger will stop at the breakpoints. If you don’t set a breakpoint, then when you run your program, the debugger will run the same as it ran in non-debug mode.

Click your mouse on the first executable line in your MouseDriver.java source code (click on the String temp = “stan”; line).

Click the Run menu.

Note the Toggle Breakpoint option. At the right of the Toggle Breakpoint option, you should see Ctrl+Shift+B. That’s a hotkey shortcut. Ctrl+Shift+B means that to set a breakpoint, you can hold down the Ctrl and Shift keys and then tap the b key (b for break). This time, don’t use the hotkey shortcut; instead click on the Run menu’s Toggle Breakpoint option.

After setting the breakpoint, you should see a bullet in the gray area at the left of the breakpoint line. For practice purposes, press Ctrl+Shift+B and notice how the bullet disappears. Press Ctrl+Shift+B again and notice how the bullet reappears.

Initiate a debug session Click the Run menu.

Select Debug As.

Select Java Application from the pop-up sub-menu.

That should cause the debugger to run to the first breakpoint line. The first executable line (String temp = “stan”;) should be highlighted.

Examine the Step Over option. Click the Run menu.

Note the Step Over option. If your Step Over option (and other debug options) are grayed out, that means they are deactivated and unusable. If that’s the case, then you might have external software that’s hindering your debug session. On my home computer, my McAfee software prompted me with “Do you want to allow javaw.exe to access the Internet?” When I clicked “Allow,” my Eclipse debug options became active.

Understand different techniques for stepping over a line of code. At left of the Run menu’s Step Over option, you should see an icon with an underscore and an arrow jumping over it. At the right of the Step Over option, you should see the hotkey shortcut, F6. Those labels indicate alternative shortcut ways to select the Step Over option. To use that shortcut, you can click on the same-looking button above the Debug pane. To use F6, you can simply press the F6 key. Of course, as a third alternative, you can click on the Run menu’s Step Over option. Back out of the Run menu by pressing the Esc key.
Step over two lines of code. Now initiate two step-over actions by 1) clicking the icon with the arrow jumping over the underscore and then 2) pressing F6.
Step into the code. Notice that the step-over action causes the debugger to jump to the line that’s positioned immediately below the current line in the program. Sometimes you won’t want to jump there. Instead you’ll want to jump inside of the method or constructor that the current line is calling.

The debugger should now be highlighting the line that instantiates the second Mouse object. With the first instantiation line, you performed a step-over command. This time, we want you to perform a step-into command so that you can see what happens when the Mouse object is created.

Click the Run menu.

Click Step Into (as always, feel free to use the alternative shortcut methods as specified by the labels on the Step Into option).

The step-into action causes the debugger to jump into the module (constructor or method) that the current line is on. In this case, the module is a constructor. Notice how the constructor assigns the three passed in argument values to the three instance variables.

Step until printStatus is highlighted. Perform the step-over action several times and that should take you through and then out of the Mouse constructor. Perform the step-over action until the printStatus line is highlighted.
Step into the printStatus method. Perform the step-into action to jump into the printStatus method. Perform the step-into action again while the System.out.println line is highlighted.
Practice stepping into and out of an api method. Normally, you won’t want to step into an API method (System.out.println is an API method) because there’s no need to debug API methods. However, sometimes you’ll step into a method accidentally. To step out of a method, click the Run menu and then select the Step Return option. Perform the step-return action so that the System.out.println line is once again highlighted. Perform the stepover action several times until the mickey.simulateGrowth(4) line is highlighted.
Step into the simulateGrowth method.
View the values for the simulateGrowth method’s variables. While inside the simulateGrowth method, view the Variables pane (click the Variables pane’s tab if necessary). In the Variables pane, you should see the d parameter and the this reference.

The d parameter should display the value 4.

Click the this reference’s expansion icon (a triangle) to display the calling object’s instance variables.

The weight variable should display a value of 100 and the growthRate variable should display a value of 10.

Step through the simulateGrowth method. Perform a number of step-over actions and observe how the d variable decrements correctly and observe how the weight variable does not behave correctly (it does not change its value at all).

Why does weight’s value not change?

Inspect expression values. Highlight the growthRate/100 * weight expression and then right click. Select Inspect from the pop-up menu.

Note that the Inspect feature allows you to evaluate an entire expression (whereas the Variables pane only displays values for individual variables).

Note that the expression’s value is 0.

Why?

Close the Inspect window by clicking anywhere outside of the inspection box.

Highlight the growthRate/100 expression and inspect its value.

Note that the expression’s value is 0.

Why?

Integer division!

Find the declaration for the growthRate instance variable.

Note that it’s declared as an int.

10 / 100 does indeed evaluate to 0.

What’s the solution?

Fix the bug. Terminate the program by clicking the red button in the Debug pane or the red button in the Console pane.

Edit the growthRate declaration so that it’s declared as a double instead of an int.

Run the project in normal mode. Although you’re using the debug perspective, it’s possible to run your program in normal mode, with debugging turned off.

To run a program, you need to select the source code pane for the class that contains main, so click the MouseDriver.java tab.

Click the Run menu.

Select Run As.

Select Java Application from the pop-up sub-menu.

The program, unfortunately, produces the same results as before – one line of output from the printStatus method and no program termination. Don’t get mad and assume that your fix from before didn’t help. Instead, realize that you have additional bugs to fix. Please remember that patience is a virtue in the programming profession!

Terminate the program.
Set a breakpoint in the simulateGrowth method. This time, instead of stepping all the way through the program until we get to simulateGrowth’s loop, let’s take a shortcut by setting a breakpoint within the loop and then running the program up to that breakpoint.

Before adding the new breakpoint, let’s remove the old breakpoint.

Select the Breakpoints pane. Look for the Remove All Breakpoints button (the button with the two X’s on it) and click it.

In the Mouse pane, scroll to the while loop in the simulateGrowth method.

Add a breakpoint to the weight += … line.

Initiate a debug session. If you want to use the Run menu to initiate your debug session, you first have to select the MouseDriver.java pane.

As a shortcut alternative to using the Run menu, feel free to use the debug button at the top of the window. It’s the button with the bug picture on it. In clicking the button, it runs the program that was previously run. Since you previously ran the MouseDriver program, the debug button should work fine.

Hover your mouse over the debug button.

That should cause the microhelp text “Debug MouseDriver” to pop up.

Click the button in order to run your MouseDriver program in debug mode.

The debugger should execute your program up to the breakpoint line. The debugger’s current line (as indicated by an arrow at the left of the line) should now be on the weight += … line.

Run to the next breakpoint. Click the Run menu.

Select Resume.

The debugger should run through the loop one time and stop at the weight += line once again. Select the Variables pane and note that the d and weight values are updated appropriately.

Run to the next breakpoint four more times in succession. Note that the d value decrements past zero and becomes a negative number. The loop was supposed to terminate when d reached zero. What’s the bug?
Fix the bug. Terminate the program.

Change the while loop’s condition so that it uses && instead of ||.

Run project in normal mode. This time, the program should terminate successfully and both printStatus method calls should generate reasonable output.

Since the main method initializes both Mouse objects with the same values, we’d expect the “They’re equal” message to be printed.

Why is it not printed? Apparently the equals method returned a false instead of a true. But why?

Initiate a debug session. The debugger should execute the program up to the simulateGrowth breakpoint line.
Remove the breakpoint in simulateGrowth. Find the breakpoint line in simulateGrowth. Click on the breakpoint line and then press Ctrl+Shift+B.

The reason that we had you remove the breakpoint in simulateGrowth is because we’re no longer interested in tracing through the simulateGrowth method. Instead, we’re interested in tracing through the equals method.

Set a breakpoint in the equals method. Note that breakpoints can only be set on executable lines of code.

Method headings are not considered to be executable lines of code.

This line is the first executable line of code in the equals method:

varietyCheck = (variety == otherMouse.variety);

Set a breakpoint on that line.

Initiate a debug session. The debugger should execute the program up to the equals breakpoint line.
View the values for the equals method’s variables. While inside the equals method, view the Variables pane (click the Variables pane’s tab if necessary). In the Variables pane, you should see the this reference and the otherMouse reference. Since they’re both reference variables, they should have expansion icons at their left. Click the expansion icons to reveal the values of their instance variables.

Inside a method, a calling object’s instance variables are often written without a “reference variable dot” prefix. Thus, the variables that appear to the left of the “==” operators (variety, weight, and growthRate) are the calling object’s instance variables.

The Variables pane shows that the calling object’s variety, weight, and growthRate instance variable values are the same as the otherMouse’s variety, weight, and growthRate instance variable values. So why didn’t the equals method return a true when we previously ran the program?

For this bug, the Variables pane is actually not all that helpful. It looks like the instance variable values are all the same, but are they really … ?

Step over the varietyCheck assignment statement.
Inspect the varietyCheck variable. In the Inspect window, varietyCheck’s value is false. Why?

Remember that variety is a String and a String is a reference variable and a reference variable holds an address. The address stored in mickey’s variety instance variable is different from the address stored in fivel’s variety instance variable. Thus, the ==operator yields a value of false.

What’s the solution?

Fix the bug. Terminate the program.

Change the variety’s test for equality so that it uses .equals instead of ==.

Run the project in normal mode. This time, the program should generate reasonable output for the two printStatus method calls and it should print “They’re equal”.
Exit from Eclipse.