Using a Java debugger
Today you will be debugging a simple threaded program using Eclipse.
Note As of Oxygen, the Eclipse debugger is a pretty terrible tool. We will use it to get a feel for debugging, but this is not what a powerful and efficient debugger feels like.
In your course repo you will find a project called java-padd
.
This is a simple parallel add program.
It spawns several threads that sum a range, then it gathers the results into a final sum.
This code should always successfully run to completion.
Observe the bug
- Run the program a few times to observe the results.
The initial program attempts to sum the numbers 0 - 1599.
According to the closed form solution of a summation:$$
S = \frac{n(n+1)}{2}$$
The correct value should be:
$$ 1279200 = \frac{1599(1600)}{2}$$What is the closest value you get to the correct answer?
Understand the tools
-
Before debugging this program, we need to make some change to how Eclipse does debugging. Open the Eclipse preferences and go to Java > Debug. Change the option Default suspend policy for new breakpoints: to Suspend VM
-
Whenever using a tool, you should be able to use it efficiently and effectively. Review the keyboard shortcuts for these commands in Eclipse, then note the shortcut in the space provided.
- Run the program in the debugger
- Set and clear a breakpoint
- Step over the next line of code
- Step into the next line of code
- Continue/Resume running the program
- Restart the debugger
-
Observe your tool's instruments. This is how you will gather infomation about the running program. In the default view the panes have these tools:
Pane | Function |
---|---|
Top-left | Shows the running call context (thread and call stack) |
Top-right | Shows the local variable values for the selected context |
Middle-left | Shows source code and next line to execute |
Middle-right | Shows an outline of the current code context |
Bottom | Shows the console (and other stuff) |
Gather information
-
Set the following breakpoints:
- At the loop that starts the worker threads and start the debugger.
- At the
run()
method. - At the
finalSum
accumulation. Using the Breakpoints tab in the upper-right, disable all breakpoints except the thread start loop one.
-
Step over the code until the main thread finishes. If you 'lose' your next line indicator, it has probably switched to a ParallelAdd thread. You can just Continue the debugger; we will debug these threads later. Do you notice any issues?
-
Now, let's purposely debug the ParallelAdd threads. Disable the thread start loop breakpoint and enable the
run()
one. Note that when debugging threads, Eclipse will not follow debug execution to other threads, so when one thread suspends, you can no longer step through code. You might need to switch to another thread using the context window. -
Debug the program. What is the interesting result?
-
How many threads are in the context pane?
-
When the thread breakpoint is hit, there is no obvious way to get to the end of the function without going through the loop many, many times. Let's reduce the problem size and see if the bug still happens.
Reduce scope
-
Change the
DATASIZE
to 2. The sum should now be 120. -
Run the program without debugging several times and observe the results. Is there still an issue?
Debugging a smaller problem
-
Hopefully the bug is still present, just in smaller form. Enable the
finalSum
breakpoint and debug the program. There should now be several ParallelAdd threads and the main thread (and maybe a bit more). Switch to each of the ParallelAdd threads and step through to completion. Now step through the main thread. -
At this point, you should be able to deduce the problem. If not, repeat the above step but don't run complete of the ParallelAdd threads before completing the main thread. What is the problem with the code?
-
Describe a possible solution.
Rubric | | | | |-----------------------|-------------------|----------------| |Answer status |0 : Incorrect |1 : Correct |