The Basics of Debugging Your Code in IntelliJ - Java Programming

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone in today's video I want to talk about  debugging your Java code within the IntelliJ IDE   the first thing that most newer programmers think  of when they are debugging is oh let me just throw   print statements everywhere I'll figure out what  all my variables are and then I can debug my code   right well that can sometimes work but first  of all there are much more efficient ways to   do it and second of all sometimes adding print  statements in your code actually changes the   behavior of your code and then you're thinking  what's going on so that's where debugger comes   in let's go ahead and pull up IntelliJ and I'll  go through a few examples of how you can use   the debugger to debug some code all right so in  IntelliJ I've got a main class whose main method   is just doing some very basic arithmetic here  I've got two integers A and B I'm multiplying them   together and I'm comparing the product of those  two integers with another variable C and then I   am printing out whether it's bigger or smaller  now this program really shouldn't have very many   bugs in it if you look at it you would expect it  to print smaller because 2 times 5 is 10 Which is   less than 11 not greater and we think that we'd  always print smaller in this case let me run the   code just to double check that and as we expect  when we run the code we hit the smaller case here   we print smaller let's say that I move this to a  value of 10 though and then I rerun the code so   it still prints smaller even though actually the  values should be equal because 2 times 5 is 10.   now let's say the program weren't this  simple and I was trying to figure out why   I was getting a value of smaller rather than  equal or something else what you might think   you would do is you would add a print statement  in here you'd say debug and then you'd print out   a times B then you'd run the code and you would  check to see what the print statement said and   yeah that could work or what you could do is  you could run this code through a debugger and   you could see what the value of each variable is  and you can literally step through the program so   the first thing you do to do that is need to run  in debug mode and there's this little bug symbol   in the IDE you might think if you run this that  that's really debug mode but that's really not   debug mode that's just turning on additional  features in the IDE that you then you need   to customize to really debug your program many  many people click the little debug icon within   the IDE they don't see any different results  in their program and then they kind of throw   up their hands saying okay that didn't work now  what do I do well if you're frustrated you've   come to the right place let me talk through what  you do when you are debugging your code in debug   mode there's more to it than just hitting that  little bug icon the first thing we want to do   is we want to insert what's called a break point  a break point is where while you're running in   debug mode the IDE will stop execution of  your program at your break point and then   you can kind of poke around and see what the  state of your program is at that break point   so all you have to do to add a break point is in  IntelliJ you just click right here next to the   line number of where you want the break point  to start so basically before this line of code   is executed we're going to have the IDE stop  execution of the program so if I run with the   debug icon again we'll see what that does whoa  okay so what's going on here this is the debug   window you're used to normally seeing the console  output which is standard out in this case we have   a debug window which is saying what the state  of our program is so this little check mark says   that we did hit the break point right here and  this line is highlighted because we're currently   on that break point and it even says right here  main so we're at line three so we're right here   and it says that the only variable which is set  right now is this args array and that's because   the args array is right here it's an argument  that goes into the main method and because   we haven't executed this line of code yet the  debugger doesn't know about the a variable yet   so what you have to do is you want to do what's  called a step which means you want to execute   the next line of code and then see what happens  so there are these different arrows right here   what you want to do is you want to do a step over  and look at that we just ran step over and since   we weren't going further into What's called the  call stack we basically just went to the next line   of code so even though our break point was at line  three we are now still breaking at line four here   and we can see that our value of a is two so if I  skip one more time here now our value of B is 5.   so I can skip a few times and now I can see  that a is 2 B is 5. and a times b equals 10.   C equals 10 a times b equals 10. and it's already  telling me what's going to happen I'm going to hit   the else block and here we print out smaller so  look at that we were able to literally step by   step follow the logic through our program and we  were able to look at what it was doing based off   of the values of our variables that's pretty  neat huh so now that I know how the program   would execute in that situation I'm going to  go ahead and rerun the debugger by clicking on   the bug again and now we're back to where we  started we're back at line three so now that   I've stepped over I have a equal to 2 and the  code would interact the same way it last time   now let's say that I want to see how the code  would react if a were a different value you   might think you need to change the value of a  recompile rerun your code re-run the debugger nope   you don't have to do that you can set the values  of the variables while the debugger is running   so now I can literally click on this little arrow  set value and I'm going to set a value to 9.   now I could step through the code again I'll  go ahead and just do that here pretty quickly   so we can see at this time we're not even  going to hit the else Branch because our   value of a is 9 which means that our product  is 45 which is greater than 10. and now that   I know that I'm going to enter this if statement  I'm just going to go ahead and hit resume here   and we print out the value bigger so now let's say  I'm debugging this code and I want to specifically   look for when I'm hitting this else case but  really the value isn't smaller it's equal what   I can do is I can add a break point and I can  evaluate a times B relative to C I currently   have a break point still at line three and  now I'm going to add one at line eight and   then I'm going to right click on it and I'm going  to add a condition and I'm going to say a times B   equals c so now what will happen is this break  point will only get hit if the condition is true   and in the case of the code right now I would  expect it to be true so we've hit our first   break point I don't want to step over each line  so I'm going to hit resume and now we can see   that we've hit our second break point and our  value of c and a times B are exactly the same   and that's why we hit it if I were to rerun the  debugger and then I change the value of a to three then if I resume we can see that we just hit  bigger here and we don't hit this second break   point so that's pretty sweet you can make a break  point conditional based off of the state of your   program so that you don't hit it every single  time let's say that this first break Point's   annoying me and I don't want to use it anymore  but I want to generally keep it in place I can   right click on it and I can deselect the enabled  and what this means is I have a break point here I   could turn back on but it's not currently enabled  and we'll see that if I rerun the debugger that   I hit my conditional breakpoint because the two  values are the same but I skipped over the first   break point so next what I'm going to do is  instead of Primitives now I'm going to convert   this to using some objects and demonstrate  how you could use objects in a debugger alright so here's some more code where I've got  strings and I am adding things into a list and   then I'm printing the list so you may look at  this code and you may see the bug immediately   or maybe you don't let's go ahead and run it and  see what it's doing ah we have a bug looks like   we have a string index out of bounds exception and  it happens right here with substring So based on   the fact that we're throwing that exception here  you might pretty quickly draw the conclusion that   the strings within my list are not long enough I  need to be correct when you take a look at this   string for example but let's say it weren't  that straightforward and you didn't see the   contents of my list you could print out my list  ahead of time if you wanted to or you could add   in some break points let's go ahead and run this  with the debugger and see what it looks like all   right so now that we're in the for Loop this is  the first time that we're in the for Loop because   we don't have a conditional break point you can  see here that these are all the active variables   we can see that my list has a size of three where  a second list currently doesn't have any elements   in it because we haven't added anything  and the current value of my string is hello   and we could even see right here we just use this  little carrot we can see what the entire contents   of my list are I've got hello there yo and I can  just keep drilling down as to what the details of   all this information is this is really valuable  you can get down to pretty low level details   and the debugger pretty quickly with what your  variables are doing and what state they're in   so if I were running the debugger I could  immediately after adding this breakpoint if I   didn't have access to my list originally or let's  say it was a complex data structure I could look   through the contents in this debugger and I could  tell almost immediately why it would fail my check   and for me this sort of thing is really useful  way more useful than rerunning your code twice   five times ten times whatever it is adding in  the magic log statement that tells you where your   code's going wrong it's a lot faster and easier  to use a debugger in a situation like this so now   that we've talked about debugging Primitives and  objects let's talk about how you could debug when   you have multiple threads involved I'm going  to write a small program that hangs when you   run it and I'm going to show what the debugger  that you can tell with the state of your various   threads are when it enters that hung State all  right so I've got some code here that has two   object monitors that I'm going to be locking I've  got one thread here that I'm starting and another   thread that I'm starting the only difference  between these two threads is the order in   which they are trying to call synchronized so the  first thread is synchronizing on the first object   then it sleeps for a second and then it tries  to synchronize on the second object so basically   it's trying to acquire the monitor of object  and then acquire the monitor of object two   and then this thread is trying to acquire the  monitor of object two sleeping for a second and   then object one so think about that for a second  basically we have two threads that are each   starting by acquiring one monitor and then they  each try to acquire each other's monitors after   sleeping for a second so this is what's called  a deadlock because no thread can move forward   and they essentially get stuck there indefinitely  if I run this in regular run we can see here that   the code is just going to sit here indefinitely  we could wait here for 10 minutes we could wait   here for 10 hours doesn't make a difference these  threads are never going to exit and this is really   bad it's called a deadlock and this is sometimes  very difficult to debug in your code because where   do you start you could throw in logs kind of  in random places and guess where the deadlock   is happening or you could use the debugger and  you could find the answer much faster let's go   ahead and run this in debug mode and now what I  want to do is I want to go down to these little   icons down here and I want to get the thread dump  so if I click on that and I raise this up there's   a lot of information here so these are all of the  different threads that are currently running at   the time of when we requested that the debugger  gave us the thread dump there is a finalizer a   reference Handler signal dispatcher a lot of this  stuff is stuff that is normally running by the gel   virtual machine the jvm for you and you don't  need to worry about it but you'll notice there   are two right here that are very interesting each  saying waiting for monitor entry so each of these   two threads is seeking entry to a block of code  that is blocked by monitor so that looks promising   so if we click on the first one we can see  that we have a blocked thread because it's   waiting on monitor entry Waiting For Thread  755 oh 755 right here to release lock to FC   a Java Lang object here on line 13 of our code and  then likewise if we click on 755 we can see that   755 is also waiting for monitor entry because it's  waiting on a monitor that 751 has so interesting   so without needing to add any extra logging  or needing to do really much of anything we   were able to deduce that threads 755 and 751 are  deadlocked on each other and therefore they're   blocking our program pretty sweet huh and that  was a quick overview of using intellij's debugger   I hope I convinced you that that debugger is  really really useful and it's a lot better than   just adding print statements wherever you need to  add debug don't get me wrong I debug with print   statements quite a bit still sometimes it's just  not feasible to run a debugger in your environment   but when you do have a debugger available 100  you should use it where it makes sense because   it just makes your life so much easier you could  change the values of your variables you can change   the behavior of your program you can do thread  dumps like I was just demonstrating I mean the   options are pretty extensive if you learned  something new today please do give this video   a thumbs up drop a comment if you enjoyed  the content of today's video thank you for   watching I hope you have a good rest of your  day and I hope to see you next time take care
Info
Channel: Will Tollefson
Views: 3,309
Rating: undefined out of 5
Keywords:
Id: Wqt8O7arL2Y
Channel Id: undefined
Length: 15min 22sec (922 seconds)
Published: Fri Oct 06 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.