Skip to content
Code To Live By » Uncategorized » Tools of the Trade: How to Use a Debugger

Tools of the Trade: How to Use a Debugger

  • by

One of the greatest tools that I could start this series with is something that I use all the time as I’m trying to diagnose possible issues in code. A “debugger” allows you to stop your code at a particular point and see exactly what it is doing. For this post we’ll be specifically focusing on how to use a debugger with Java.

Let’s say we had some piece of code to gather ingredients for drink cocktails, then we used something like json-simple to print that as JSON. That might look something like this:

public static void main(String[] args) {
	JSONArray drinks = new JSONArray();
	
	JSONObject irishCoffee = getDrinkJSON("Irish Coffee", 
			Arrays.asList("Irish Whiskey", "Hot Coffee", "Cream", "Brown Sugar"));
	drinks.add(irishCoffee);
	
	JSONObject sazerac = getDrinkJSON("Sazerac", 
			Arrays.asList("Cognac", "Absinthe", "Sugar Cube", "Peychaud's Bitters"));
	drinks.add(sazerac);

	JSONObject whiteRussian = getDrinkJSON("White Russian", 
			Arrays.asList("Vodka", "Kahlua", "Heavy Cream"));
	drinks.add(sazerac);
	
	JSONObject json = new JSONObject();
	json.put("Drinks", drinks);
	
	System.out.println(json);
}	

private static JSONObject getDrinkJSON(String name, List<String> ingredientsList) {
	JSONObject drink = new JSONObject();
	drink.put("Name", name);
	JSONArray ingredients = new JSONArray();
	for (int i = 0; i < ingredientsList.size(); i++) {
		ingredients.add(ingredientsList.get(0));
	}
	drink.put("Ingredients", ingredients);
	return drink;
}

and our output might look something like this:

{
	"Drinks": [
		{
			"Ingredients": [
				"Irish Whiskey",
				"Hot Coffee",
				"Cream",
				"Brown Sugar"
			],
			"Name": "Irish Coffee"
		},
		{
			"Ingredients": [
				"Cognac",
				"Absinthe",
				"Sugar Cube",
				"Peychaud's Bitters"
			],
			"Name": "Sazerac"
		},
		{
			"Ingredients": [
				"Vodka",
				"Kahlua",
				"Heavy Cream"
			],
			"Name": "White Russian"
		}
	]
}

Or rather, it should if we didn’t have pesky bugs in our code! Instead we have this:

{
	"Drinks": [
		{
			"Ingredients": [
				"Irish Whiskey",
				"Irish Whiskey",
				"Irish Whiskey",
				"Irish Whiskey"
			],
			"Name": "Irish Coffee"
		},
		{
			"Ingredients": [
				"Cognac",
				"Cognac",
				"Cognac",
				"Cognac"
			],
			"Name": "Sazerac"
		},
		{
			"Ingredients": [
				"Cognac",
				"Cognac",
				"Cognac",
				"Cognac"
			],
			"Name": "Sazerac"
		}
	]
}

Now that we have familiarized ourselves with our problem space we can begin talking about the tool that can help us resolve this. I will using Eclipse for this post, but you can of course feel free to use whatever IDE is comfortable for you, with the caveat that the exact steps you will need to take may be a little different. If you are following along then you will also need to download json-simple and add it to your project’s build path.

First we are going to add our first breakpoint, we can right click on the left end of our Editor window and select the “Toggle Breakpoint” option. For this example we will do so on line 12:

Now that we have added that, we can “debug” our program similar to how we can run it. This is needed in order to pass the necessary options to Java so that our program will do things such as stopping at breakpoints.

After clicking on “Debug” you may see a screen like this which is asking you to “switch” perspective. This is fine, and will show us some more relevant tabs for debugging.

After selecting “Switch” we end up with something like this:

I added two red boxes to emphasize two big points of interest here. The smaller box on the left is”step commands” which allow us to control how are code behaves after hitting our breakpoint(s.) The second box shows the “Variables” window which can show our program state. Since this is the first line of code there isn’t much to see here yet. However, if we hit “Step Over” a couple of times until we are at line 18:

From the Variables tab we can see that our program has created our “irishCoffee” JSONObject. We can also see that our “drinks” JSONArray has one element added, and the contents of drinks[0] and irishCoffee JSONObject’s should match. Let’s now skip ahead to line 26.

We can see that the whiteRussian JSONObject was properly created, but the drinks[2] JSONObject doesn’t match; So we know the problem isn’t related to creating the whiteRussian JSONObject, but rather when we adding it to our drinks JSONArray. Sure enough if we look at the last line we have executed, line 24, we can see that we are accidentally adding the sazerac twice rather using our whiteRussian variable. Alas! A swift correction to line 24 and we now have:

{
	"Drinks": [
		{
			"Ingredients": [
				"Irish Whiskey",
				"Irish Whiskey",
				"Irish Whiskey",
				"Irish Whiskey"
			],
			"Name": "Irish Coffee"
		},
		{
			"Ingredients": [
				"Cognac",
				"Cognac",
				"Cognac",
				"Cognac"
			],
			"Name": "Sazerac"
		},
		{
			"Ingredients": [
				"Vodka",
				"Vodka",
				"Vodka"
			],
			"Name": "White Russian"
		}
	]
}

We now have the White Russian getting added properly, but our Ingredients array is still wrong. Let’s see if we can debug our getDrinkJSON function next. We can do this by removing our breakpoint at line 12, adding a new one at line 33, and then restarting our debug configuration.

Our program has stopped at our breakpoint the first time that our getDrinkJSON function would execute, which in our case is for Irish Coffee. We can see that our ingredientsList parameter that gets passed to this method is accurate, so we can be reasonably confident the problem is within the getDrinkJSON function.

We can skip ahead to line 37 and we should see this:

Since we are in a loop we will need to step through each iteration of the loop. We can see now that our loop variable (i) is set to 0. If we skip ahead to the next iteration:

Our first ingredient of “Irish Whiskey” seems to have been added properly. Let’s skip ahead to the next

Here we can see that even though our ingredientsList parameter is correct, ingredients is being populated with the wrong values. Sure enough, if we take a closer look at what is being executed within our loop, we can see that we aren’t actually referencing our loop variable to take contents from the ingredientsList parameter, we are merely adding the first element in the list on every loop iteration. Alas!

If we correct this and run our program again we should now be seeing the correct output. I hope that this has been a helpful exercise and has taught the basics of using a debugger (with Java), as well as maybe helped hone your critical eye for finding software bugs!

Leave a Reply

Your email address will not be published. Required fields are marked *