How to Debug Java with IntelliJ: Breakpoints, Evaluate Expression, Watches, and Variable View
This post has a look at how to effectively debug code in the IntelliJ IDE (hey, not everyone uses Eclipse!). Read on to find out more.
Join the DZone community and get the full member experience.
Join For Freei have deliberately created a failing test. obviously deliberately since i would never ever create such simple issues in code. i’m far too experienced for that. :)
even though these issues were created deliberately i still need to know how to debug code. in this blog post i’ll describe how i debug java using intellij.
you can also watch this post on youtube .
i have some code which fills a dynamic array with “*” to simulate a set of ‘pixels’ — which can be whatever. but it doesn’t work.
@test
public void createsquare2darray(){
int squarewidth = 16;
string[][]square = new string [squarewidth][];
for(int row=0; row<square.length; row++){
square[row] = new string[squarewidth];
for(int i=0; i< (squarewidth+1); i++){
square[row][i] = "*";
}
}
print2dstringarrayiterators(square);
system.out.println("");
}
it throws an error on the line:
square[row][i] = "*";
something about…
java.lang.arrayindexoutofboundsexception: 16
at com.javafortesters.chap009arraysiteration.exercises.
triangleexercisesdebugtest.
createsquare2darray(triangleexercisesdebugtest.java:40)
it will be fairly obvious to most people what is going on, but if i put a breakpoint on the line that is failing then i can debug the @test method and step through the code to see what is going on.
oh look, a breakpoint.
then run in debug mode.
when the test is running in debug and has stopped at a breakpoint, i can:
- see all the current variables
- expand them when they are an object instance of some sort
- resume execution (stop at next breakpoint)
- step over the line to advance execution bit by bit
- step into the code to advance execution, but into the method implementation
i can also highlight code and “evaluate expression”.
this lets me execute code on the fly and experiment with different code constructs. e.g. i can evaluate
square[row][i]
note that this is not the full line, just ‘code’. i can run that and experiment with it. for example:
-
square[row][i]
returnsnull
because we haven’t set the value yet -
square[row][15]
also returnsnull
because we haven’t set the value yet -
square[row][16]
reportsjava.lang.indexoutofboundsexception: invalid array range: 16 to 16
that
indexoutofboundsexception
seems suspiciously close to the error i saw when i ran the test. i could add a ‘watch’ for
i
even though it is obvious in the variables list by clicking the green
+
symbol in the ‘watch’ section.
so if i step through until
i==16
then i can also see in the variables list the exception will be thrown - even though the line hasn’t executed yet.
and we know the problem is that i copied the code from a previous ‘triangle exercise’
string[][]triangle = new string [16][];
for(int row=0; row<triangle.length; row++){
triangle[row] = new string[row+1];
for(int i=0; i< (row+1); i++){
triangle[row][i] = "*";
}
}
and accidentally left a
+1
in the loop condition. i fix that.
for(int row=0; row<square.length; row++){
square[row] = new string[squarewidth];
for(int i=0; i< squarewidth; i++){
square[row][i] = "*";
}
}
and then i have a problem in my next method. instead of printing out a 16x16 square of
*
it prints out:
****************
and here is the horror in all its glory:
public void print2dstringarrayiterators(string [][]multi){
iterable<string[]> outerlist = arrays.aslist(multi);
iterator<string[]> outer = outerlist.iterator();
while(outer.hasnext()){
string[] innermulti = outer.next();
iterable<string> innerlist = arrays.aslist(innermulti);
iterator<string> inner = innerlist.iterator();
while(inner.hasnext()){
string pixel = inner.next();
system.out.print(pixel);
}
system.out.println("");
break;
}
}
i decided to “get fancy” and use iterators and lists instead of just
for
loops with arrays. but i didn’t get fancy enough. i should have wrapped my
print2dstringarrayiterators
with
@test
methods and made sure it worked before i used it.
- me: “but it prints out, i couldn’t unit test it”
-
other me: "you could have written a method that returned the output, and we could have used
@test
to assert on its functionality - me: …
- other me: yeah, exactly.
but i didn’t do that. so i have to debug it instead.
if i breakpoint the line where the method is called:
print2dstringarrayiterators(square);
then i can “step into” the method and debug from there. and as i step through the method, the problem is obvious - the
break;
that i added by mistake. ok. so these were pretty poor examples, but, they are also very similar to code examples that i’ve received emails from, and probably wrote myself back in the day (monday, or yesterday, or something).
basics
- yes we prefer to tdd our code
- if we don’t tdd we better learn how to debug
- use breakpoints
- step through code
- use the ‘variables view’
- setup up ‘watches’ if you have a lot of variables
- use ‘evaluate expression’ to experiment in the running code
- use resume to run to next breakpoint
- use step into to move to the next level of code in a method
try it and see.
Published at DZone with permission of Alan Richardson, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments