Skip to content Skip to navigation

OpenStax-CNX

You are here: Home » Content » Debugging Java Programs Without a Debugger

Navigation

Recently Viewed

This feature requires Javascript to be enabled.
 

Debugging Java Programs Without a Debugger

Module by: Mordechai (Moti) Ben-Ari. E-mail the author

Summary: This module contains tips for debugging a Java program without a debugger, primarily by printing out data during the execution of the program.

Debugging is perhaps best done using a debugger such as those provided by integrated development environments. Nevertheless, many programmers debug programs by inserting print statements. This section describes some of the techniques that can be used in Java.

Printing number data and arrays

The methods System.out.print and System.out.println are predefined for primitive types as well as for strings:

int i = 1;
double d = 5.2;
System.out.print(i);
System.out.println(d);

Furthermore, automatic conversion to String type is performed by the concatenation operator +:

System.out.println("d = " + d + "and i = " + i);

The print statements can not print an entire array, so a method must be written:

public static void print(int[] a) {
  for (int i = 0; i < a.length; i++)
    System.out.print(a[i]);
  System.out.println();
}
 
public static void main(String[] args) {
  int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
  print(a);
}

Since the number of elements of an array can be large, it is better to write the method so that it inserts a newline after printing a fixed number of elements:

public static void print(int[] a) {
  for (int i = 0; i < a.length; i++) {
    System.out.print(a[i]);
    if (i % 8 == 7)  System.out.println();
  }
  System.out.println();
}

You can put this static method in a publicly accessible class and use it to print any integer array. Similar methods can be written for the other primitive types.

Converting objects to strings

Within the class Object, the root class for all other classes, a method toString is declared. The default implementation will not give useful information, so it is a good idea to override it in each class that you write:

class Node {
  int key;
  double value;
  public String toString() {
    return "The value at key " + key + " is " + value;
  }
}

Then, you can simply call the print statements for any object of this class and the conversion to String is done automatically:

Node node = new Node();
...
System.out.println(node);

The predefined class java.util.Arrays constains a lot of useful (static) methods for working with arrays, among them toString methods for arrays whose elements are of any primitive type:

int[] a = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
System.out.println(java.util.Arrays.toString(a));

or

import java.util.Arrays;
   ...
System.out.println(Arrays.toString(a));

You will receive a predefined representation of the array (the elements are separated by commas), so if you want an alternate representation (such as printing on multiple lines) you will have to write your own print method as we did in the previous section.

An array of objects of any reference type can be printed by defing a single method since any object can be converted to Object:

public static void print(Object[] a) {
  for (int i = 0; i < a.length; i++)
    System.out.print(a[i]);
  System.out.println();
}
 
Node[] nodes = new Node[];
   ...                         // Create elements of the array
print(nodes);

or by calling the predefined method deepToString:

Node[] nodes = new Node[];
   ...                         // Create elements of the array
System.out.println(java.util.Arrays.deepToString(node));

Forcing a stack trace

Suppose that you have isolated a bug to a certain method but you do not know which call of that method was responsible. You can force the interpreter to print a trace of the call stack by inserting the line:

new Exception().printStackTrace();

within the method. It creates a new object of type Exception and then invokes the method printStackTrace. Since the exception is not thrown, the execution of the program proceeds with no interruption. A program can always be terminated by calling System.exit(n) for an integer n.

Leave the debug statements in the program

Once you have found a bug, it is tempting to delete the print statements used for debugging, but it is better not to do so because you may need them in the future. You can comment out the statements that you don't need, but a better solution is to declare a global constant and then use it to turn the print statements on and off:

public class Global {
  public static boolean DEBUG = false;
  public static void print(int[] a) {...}
  public static void print(Object[] a) {...}
}
 
  if (Global.DEBUG) Global.print(nodes);

Content actions

Download module as:

Add module to:

My Favorites (?)

'My Favorites' is a special kind of lens which you can use to bookmark modules and collections. 'My Favorites' can only be seen by you, and collections saved in 'My Favorites' can remember the last module you were on. You need an account to use 'My Favorites'.

| A lens I own (?)

Definition of a lens

Lenses

A lens is a custom view of the content in the repository. You can think of it as a fancy kind of list that will let you see content through the eyes of organizations and people you trust.

What is in a lens?

Lens makers point to materials (modules and collections), creating a guide that includes their own comments and descriptive tags about the content.

Who can create a lens?

Any individual member, a community, or a respected organization.

What are tags? tag icon

Tags are descriptors added by lens makers to help label content, attaching a vocabulary that is meaningful in the context of the lens.

| External bookmarks