SIMS 255: Lab 6

Wednesday, October 2, 2002

Debugging with the Eclipse IDE
Iterators and Collections
Eclipse Tips

In today's lab we focus on debugging techniques using the Eclipse IDE. We'll mostly use pre-existing sample code to illustrate these debugging practices, and have an introduction to the Vector class, an implementation of the Collection interface. Vectors are often used in conjuction with the Enumeration class, which is used to iterate through Vectors and other Collection classes. Before we get started with the debugging, we'll start with a few general programming guidelines and Eclipse tips.

Consulting the Java API Documentation

Information on Java classes (such as String) and many, many others is available on Sun Microsystem's Java website: http://java.sun.com/.

On the menu bar at left, under Documentation, click on APIs.

Under Java 2 Platform, Standard Edition (J2SETM), click on J2SE 1.3.1 API Specification.

The lower left frame lists all of the classes and interfaces that are available. Navigate to the class you're looking for, and a description of it, its instance variables, and its methods will be displayed in the main frame.

Bookmarking this page is recommended, as it will often come in handy for reference about the Java classes that are available for use. In general, the Java site is a wealth of information about Java programming, containing tutorials, code snippets, and other helpful information.

Eclipse Perspectives

Eclipse has different "Perspectives" which are pre-saved views of combinations of Eclipse functionality. Different perspectives have different feature sets. The perspectives that will use most in this class are the "Java" and "Debug" perspectives. You can tell which perspective you're currently in by the first word in Eclipse's title bar. Usually you won't have to manually change your perspective, unless you notice that certain needed functionality is missing. For example, you may notice that the Run menu doesn't allow you to run any projects -- the Run menu contains only "External Tools". This occurs when you are in "Resource" perspective mode. To get into the more useful "Java" mode, choose Window > Open Perspective > Java. Now the Run menu should enable you to run and debug programs.

Debugging Techniques

We will use Eclipse to employ typical debugging practices and uncover common programming errors. There are two main methods of debugging, and depending on the problem, you may need to use one or both. The simplest method is to insert statements that print some output to standard output. You have probably already used this method while working on your Java homework. The method is to insert statements that print (a) where the print statement is in the code (so you can determine of certain portions of the code are being executed), and/or (b) the current state of variables at certain points in the code. The TestParams class from Lecture 6, slides 32-33 uses this method.

Let's do a simple example.

Debugging by printing to standard output

In doing this exercise, we will first demonstrate how to create a project using an existing code file. This code doesn't do anything very interesting, but it will enable us to try out some debugging techniques.

First, download this Java file, SimpleDebug.java to your desktop.

Launch the Eclipse IDE by choosing Start > Programs > Software Development > Eclipse 2.0 from the Windows Start menu.

Choose File > New > Project...

Select Java and Java Project, and click Next.

Type SimpleDebug in the Project name field, and click Finish.

In the Package Explorer window, highlight the SimpleDebug project.

Right-click on the SimpleDebug project and choose "Import…" from the context-sensitive pop-up menu.

Select File System and click Next.

In the Import dialog, to the right of the blank "Directory:" field, click the "Browse…" button, navigate to your desktop, and click OK.

In the window on the right, check "SimpleDebug.java" and leave everything else blank. Click Finish.

SimpleDebug.java has been added to your SimpleDebug project.

Double-click on the SimpleDebug.java file to open it.

You have now created a project using an existing *.java file. Now on to the debugging.

This code has a bug. If you can tell what it is by looking at it, don"t fix it yet. We"re going to run it in order to observe a very common programming error.

Choose Run > Run As > Java Application.

The code does not execute properly. There is no output, and the Java console at bottom indicates that an ArrayIndexOutOfBoundsException was thrown, and shows the line number (16 in this example) where the problem occurred.

One technique that"s used is to insert print statements before and after the line where the exception is thrown (or where the problem is suspected to be - not every problem that needs to be debugged throws an exception!). Insert 2 println statements around that line so that part of the code looks like this:

System.out.println("before the for loop");
for (int i = 0; i <= intArray.length; i++) {
System.out.println("in the for loop and i is " + i);

Run it again.

Now we can see that the println statement before the for loop was output (and that"s no surprise because we know it"s the for loop line that throws the exception). We also see that the println statement within the for loop also was output several times.

If we count the number of times that line was output, we see that it happened 11 times, which is one more than the length of the array. This means that we have been attempting to access the 11th element of the array, which doesn"t exist. It is a very common mistake to set up the conditional part of the for loop with the incorrect less-than-or-equals comparison operator rather than the correct less-than comparison operator.

Now modify the code to correct this mistake. Re-run it and it should execute properly.

A much more powerful method is stepping through the code. You can look at the values for each of the variables, and by watching them as you progress through the code, observe where they get filled with incorrect values.

Debugging by stepping through the code

We"ll use the fixed version of the code above to demonstrate this. In order to step through the code, you need to set breakpoints where you want to watch variables changing. We"re going to set a breakpoint where the variable intArray is accessed.

To do this, right-click to the left of this line in the SimpleDebug.java window, and choose "Add Breakpoint" from the context-sensitive pop-up menu.

intArray[i] = i;

A small circle indicating a breakpoint appears.

Now we will run the program in Debug mode.

Choose Run > Debug As > Java Application. The code will begin executing, then stop as soon as it hits the breakpoint.

The important windows to watch here are the SimpleDebug.java code window, and the Variables window at the upper right. The Variables window shows the current value of each of the variables that the method that we"re in knows about. For example, it shows that MAX_LENGTH is 10, i is 0, and sum is 0. We can also look at the contents of intArray. Click on the plus sign next to intArray to extend the contents.

Now let"s step through the code. Choose Run > Step Over (or press F6) a few times, and watch how the array gets filled up with the value of i each time through the loop.

Step Over continues to execute, line by line, within the current method, until the method finishes executing or the program terminates with errors.

Now let"s try another example, using the Vector and Enumeration classes. Quit the current debugging process by choosing Run > Terminate. (Note that if you want to debug the same application again, you need to either choose Run > Debug Last Launched, or be sure to click in the SimpleDebug.java window before choosing Run > Debug As > Java Application.)

Vectors

A Vector is similar to an array in that it holds a sequence of objects, but with some very important differences. First, it can dynamically expand - you don"t have to know in advance how many items you need to store. Also, a Vector can hold a mixture of object types. Each element in a Vector points to an Object, so as long as the items you"re using are subclasses of Object (and this will be true of any class you make or use, other than primitive types) they can be stored in a Vector. Finally, a Vector is part of Java"s Collections framework, and so it has methods that are used to access its elements. The square bracket notation that is used with Arrays is not used with Vectors.

Note that you"ll have to include this line at the top of any file that uses the Vector class.

import java.util.Vector;

Download VectorDemo.java.

Create a new project as above, and import VectorDemo.java into the new project.

This file was downloaded with sourcecode from Java 2: The Complete Reference, 4th ed., by Herbert Schildt. Note that some of the formatting is a bit off. You can reformat it quickly, giving it the proper indentation by selecting all and then choosing Source > Format.

This sample program uses many of the methods of the Vector class, including methods that add elements, get the first and last elements, and check the current capacity. The code also includes the Enumeration class, which is used to sequentially iterate through the elements of a Collection class.

As described above, set breakpoints in the code and use the debugger to step through and watch the variables change. Expand the Vector in the Variables window so you can watch as items are added.

Linking multiple files

When your program contains multiple classes, you can either put them all in one file, or split them up into separate files. When they are split into separate files, they are linked at run time. A couple of things to keep in mind:

One and only one of the classes must have a main() method.
All of the class files need to be imported into your project.

As an example, let"s use one of the solutions to the Schedule exercise from Lab 4. Download these files to your desktop, Schedule.java, Course.java, Professor.java. Create a new project called ScheduleLab6, and import the 3 files into it.

Open Schedule.java.

Run the program to ensure that everything links correctly.

Place a breakpoint on the first line of the main() method in Schedule.java:

Professor marti = new Professor("Marti Hearst", "Associate Professor", "212 South Hall");

Now choose Run > Debug As > Java Application to run the program in debug mode.

In the previous debugging examples, we used Step Over to step through the code. Now we will use Step Into to drill down into the method being called on this line (the Professor constructor).

Choose Run > Step Into (or press F5). (You might get a strange looking page that says "Class File Editor, Source not found." If that happens, choose Run > Step Return (or press F7) a couple of times to get back out to the main() method. Then try Step Into again.)

Observe that the program control snaps to the Professor constructor, and its file (Professor.java) is opened. Step Over a few times until the constructor finishes executing the creation of the "marti" Professor object, and you snap back up to the main() method in Schedule.java.

Step Into again, to go into the constructor for the "ray" Professor object.

Instead of using Step Over, use Step Return to immediately snap back up to the main() method.

Step Over lets us step through the code at the current level. If the current line of code contains a method call, using Step Into will take us down one level into that method, otherwise it will behave like Step Over. And Step Return will finish executing the current method and snap us up one level to the previous calling function.

Let's use these three Java files to illustrate another handy IDE feature. First terminate the current debugging session. Then change to the Java perspective by choosing Window > Open Perspective > Java. Also turn off any breakpoints by right-clicking on them and choosing Remove Breakpoint from the context-sensitive menu.

Navigating class, method and variable declarations

When your project contains many lengthy files, it can get difficult to determine where a certain method or class was declared. Here is a shortcut for finding the declaration of a class, method or variable.

Close any *.java files that are open, except for the Schedule.java file within the ScheduleLab6 project.

Select the word "Professor" anywhere in the file by double-clicking on it.

Right-click on the selected word and choose Open Declaration. The Professor file is opened, and the appropriate Professor constructor is highlighted.

Go back to Schedule.java, and do the same thing for method printCourseInfo(). The Course file is opened, and that method is highlighted. The same technique will work for variables too.

NOTE: Although you can employ this technique for the classes you use from the Java class libraries (e.g., String) in addition to the classes you or your project partners write, it is best to use the Java API documentation web site as described above. This contains a much richer set of information about the Java classes.

For more information on using Eclipse, see the Help files at Help > Welcome > Eclipse Platform and click on Workbench User Guide.


LZ -- last modified 10/8/02