How to debug a program

First thing is first. Make sure you have done each of the following before spending time in the debugging phase.

  1. Do you have a complete strategy for solving the problem? Did you work out the possible complications and special cases your program might run into? Use paper and pencil for this phase and try running your program idea through several examples on paper.

  2. Plan out helper methods. Helper methods are always a good idea because they are
    1. reusable
    2. separately testable and debuggable
    3. make the overall program logic easier to follow

  3. Write logically detailed pseudocode that executes your strategy from step 1. Be detailed in exactly how things will work, but do it in English instead of code. The syntax details don't matter, but the logical details do. Once you have logically detailed pseudocode, writing your program will simply mean turning the pseudocode into comment lines and then writing the equivalent Java instructions below the comments. Each of your helper methods also needs its own pseudocode.
Now you are ready for the debugging phase - which will be much easier now that you have a detailed idea of how your program will work.

Debugging Suggestions

Determine whether you have a compiler error, runtime error, or logic error.
Compiler errors
Something is syntactically wrong with your program code. The Java compiler will tell you what the problem is. You need to understand what it's telling you. If you don't understand the message, look here:
http://www.skylit.com/javamethods/JM-Appendix-B.html
http://mindprod.com/jgloss/compileerrormessages.html

Runtime errors
Your program is syntactically correct, but it allowed something illegal to happen when it ran. Here's an example:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
   at Paw.claws(Paw.java:39)
   at Cat.scratch(Cat.java:209)
   at Animals.main(Animals.java:55)

You should read these errors from bottom to top. They say which line crashed and provide you with the chain reaction leading back to the cause. Reading from bottom to top, line 55 in the main() method of Animals.java crashed because line 209 in the scratch method Cat.java crashed. But that crashed because line 39 in the claws method of Paw.java crashed...which crashed because of an ArrayIndexOutOfBoundsException: -1 So, that's the problem. Line 39 in the Paw class tried accessing an array index of -1, which is illegal because arrays go from 0 to length-1. You need to debug your code and figure out why -1 is being calculated as the array index.

Here are explanations of common runtime error messages:
http://mindprod.com/jgloss/runerrormessages.html

Logic errors
Your program compiles and runs but it doesn't produce the output desired.
  1. Isolate the problem.
    Comment out everything. Then uncomment as few lines as necessary to make your program compile and run. Once that's working, uncomment a few more lines and make sure they work by recompiling and running your program. Make sure the variables and output up to that point are correct. You should add println() statements to verify the values of variables up to that point in your program.

  2. Test methods separately with known inputs.
    Well-written programs are broken into parts using separate methods and separate classes. Test each part separately. For example, if my program needs to find the fifth word in a sentence then I might have a separate method for it:

    String findNthWord(String s, int n) // finds the nth word in String s
       // code not shown
    }


    I can test to see whether this part of my program works properly on its own. In the main() method, I can run some tests:

    // This should produce an error message
    System.out.println( findNthWord("Hello there, how are you?", 0) );

    // This should print "Hello"
    System.out.println( findNthWord("Hello there, how are you?", 1) );

    // This should print "there,"
    System.out.println( findNthWord("Hello there, how are you?", 2) );

    // This should print "you?"
    System.out.println( findNthWord("Hello there, how are you?", 5) );

    // This should produce an error message
    System.out.println( findNthWord("Hello there, how are you?", 6) );


  3. Recognize that many of the logical errors students make in programs is failing to recognize special cases. In other words, you wrote code that is misbehaving in a way you didn't expect because you didn't think of handling special cases. When planning your program you must think through all the scenarios of what could be inputted into your methods/program. You need a plan that addresses all the reasonable possibilities. As with many things in life, you will often find out the special cases for the first time during the debugging process.

  4. Add lots of System.out.println() statements to your program to trace the value of variables during runtime. Find out why it's doing what it's doing.

  5. Use a debugger that allows you to "watch variables" and "step" through your program running it line by line. The free version of JCreator doesn't do this. BlueJ does and so do many other IDEs. You can also use standalone debuggers such as JSwat. Debuggers are very handy tools for stepping through code.