IntelliJ IDEA. Debugger Advanced

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everyone and a lot of people here today much more than it was on the previous talk and that's okay because uh last time it was really essential parts of the debugger and today we are going to have much more fun with the debugger so hopefully you will have as much fun as me doing this presentation okay so uh i don't have slides for today the whole presentation will be in the form of a demo so let's begin and the first thing i would like to tell you about is a breakpoints dialect so on a previous session we showed i've shown you the breakpoints conditions and the very basic settings uh for the breakpoints and the central place where you observe your breakpoints is the breakpoints dialog and you can open it either with the shortcut if you remember that or with the button from the main menu or the debugger tool window so here you have all your breakpoints with all the settings all the breakpoint types are there as well and you can group them how you want it by class or by uh the file and the breakpoint is contained in uh or by the package so in my case the package is default so it's not really useful and this grouping is usually used to enable or disable breakpoints at once because otherwise it's really complicated to enable or disable the breakpoints you need and if you group them it's really easy to disable or delete them all at once um also if you don't want to delete your breakpoints but you don't need them right now you can create a group of breakpoints with your custom name so for example we can set a breakpoint for a specific problem in a bug and we can create a group for that named for example bug one two three and these breakpoints can appear in in a dedicated bug group or a breakpoint group so you can add as many breakpoints there as you need and you can disable them for now and forget about them and when you need them again you can get back to them and also if you don't need the groups but you have your favorite breakpoints like i have here you can set a description for that and it will be displayed right here so that you can come back to the breakpoints you like later um i usually don't delete breakpoints i just disable them because uh i'm lazy and if someday later i i come back i usually don't remember what i did there but break points even disabled with some conditions or or log expressions remind me about what i did there so other than that in this dialogue there are a lot of settings for the breakpoints and we'll go through them right now so here is the first example and this is a simple cache program well it's it's not a cache actually but it gets one instance of a cached object so like a usual pattern if the instance is now we create a new instance and if it's not we just return it and in a loop we call just get instance uh 10 times so you can see that if we run this there will be 10 10 times the same object so when you debug such code you may be interested for example in in adding some logging so here we have a parameter for the get instance method and it is not logged anywhere well actually it is not used anywhere but maybe you are interested in logging this for some reason so you can uncheck the suspend um button and this creates a breakpoint which does not do anything so it is there but it does not suspend the program so why can we really use that for so if it is a breakpoint but it doesn't do anything well actually you can do many things other than suspending a program and one of those things is logging as i said so you can enable the evaluate and log field and put any expression there and so on the breakpoint event expression will be evaluated and the result of this expression will be locked to the console so in our case we can [Music] put i here we can run the program in the debug mode and see that now you we have the parameter here so it's not obvious what these numbers mean so we can slightly modify this to more human readable form restart it and there you go now you know something about your program and what else can you do here actually if you are not interested in the particular expression you may be interested in the fact that this breakpoint was actually hit so you can set the breakpoint hit message alone and run it and in the log there will be 10 10 lines with the link to to the particular line in the code where the breakpoint was really hit so we didn't set it once again to suspend anything but the fact that is it was hit and sometimes give you a good understanding of what's happening so for example we can move it to the next line and see that it really happened only once because well it is how the program is is done so other than that we can add the stack trace here and it will uh dump uh stack trace uh of of of the program when it called the particular method and also from here we can quickly create such breakpoints using the selection in the editor so you select what you want to unlock and you do the shift click on the gutter not the regular click for the breakpoint and it will automatically create a non-suspending breakpoint with the expression you have just selected in the editor this is kind of a short short path to create such expressions such such breakpoints also in the breakpoints field this field actually is not a simple log field as i said before the expression is evaluated and the result is locked to the console so here you can while you evaluate this expression you can change something so for example we can set instance to now and what it will do then every time a program reach this point it will reset the instance value to null so effectively we will disable the caching so you can see that now uh well null is the result of that evaluation but also the values of every cache object is now different so we by using this logging breakpoint we changed the behavior of the program so why do we need that um well it depends on what you want to get but usually i use it to debug the insights of the object initialization so sometimes you get to such code and you are really interested in how the instance is initialized and it is already initialized so there is no way to debug the new cache constructor anymore so you can either change the value of the instance right here by hand so it is also possible and we discussed it previously so right now it's now but for example now it's not null and we can go here and set new value to now and now we can debug the cache constructor but if you want to do that like every time you can do that using the log breakpoint as i have shown you before what else the non-suspending breakpoints could be used for uh consider this example so we have some work um well it does something well it it really doesn't do anything but um we pretend that it does and it does it in a loop and it does it in actually two loops so first loop is a warm-up and the second one is a real work so if you set a breakpoint in the work code and debug it for sure we will stop first in the warm-up so in the stack you can see that it is called from the warm-up method which we are most probably are not interested in so how do we skip that to the warm-up to the real work so we can either resume it like 10 times until we hit the real work code or we can unset this breakpoint here set a breakpoint here resume so until we finish the warm-up and now set the breakpoint here to the work code and now finally we are inside the work code so uh you can do that but actually there's an easy way to do that this breakpoint could be non-suspending and we are done with that so it is really doing nothing but it acts as a marker so in these settings for the second breakpoint we can select uh disable until hitting the following break point and select the first breakpoint so now what we have and this breakpoint changed the icon because it is disabled until the first breakpoint is hit and when it is hit this breakpoint is enabled and you can also specify what to do on the first hit of this breakpoint after that so we can leave it enabled here for now and we rerun the debug session and we immediately stop in the real work because this is how we set up our breakpoints so you can see that this no these non-suspending breakpoints are really useful sometimes uh what else can we do with the breakpoint suspend modes so as you have seen the we can disable the suspend mode at all so the breakpoint doesn't do anything or we can select to suspend all or thread what what does it mean well suspend all means to spend all like all the threads in the application will be suspended when these certain position in the code is reached in any thread and this is fine this is the default this is usually what most people really want but in some cases like in the case we will describe and discuss here requires some more control so with the suspend thread mode and i will switch the breakpoint here we can control uh we can stop threads separately so this breakpoint will be hit in two threads i will show you that in a moment and we will be able to control threads separately so what this code example is about so we have a list and it's not a simple list it's a synchronized list um we have a method which effectively do what it's what it is named after so ad if absent it checks if the list contains a number and if it's not then it adds the number to the list and it we call this adefabscent method from two different threads from the main thread and from another thread which is started right here and then we wait and then we print the contents of the list um when i did this example actually this is the example from the tutorial for the debugger so when we did this uh this was like number one um concurrency issue on the stack trace so um not the stack trace the stack overflow so the problem here is that the list is synchronized so most developers really think that if the list is synchronized there will be no synchronization problems and in this particular case it's true there are no synchronization problems but the program may behave uh in a way which you don't expect so i i wrapped it in a test so we can run this test and it really check if the resulting collection size is one and you can run it many many times and it will work correctly but then and i think you know that in the test run configuration you can change the repeat mode to the until failure and we do that and we run it again and we wait so the test will work correctly for many many times and now the number is 1300 something and then it will fail and there will be two elements in the list and such bugs are really really really hard to find first and then it's not that easy to fix so it's easy to fix but in this particular case of course in in real life it's not that easy to fix so what's the problem here i think you all got it now so the collection is synchronized so all the methods like contains and add are internally synchronized and you can call them from any threads there will be no problems but the whole like method so adf absent is not synchronized so this contains an ad can be called from different threads in different order so uh in the debugger let's put a breakpoint here suspending a thread and start it so we stopped in one thread here and also you can see the notification here so this breakpoint is reached in another thread and you can switch right from here if you want so uh you can see that now we stopped in two frets main and thread zero and they both are standing inside the adfabsent method right before the first check for contains so what we do here is that we do one step over in one thread so one thread now have checked the contains and of course the result is false because the list does not contain anything then we switch to another thread and do the same thing so we do the check so now both threads did the check and both checks uh returned false because the list does not contain anything yet and now we continue working actually so we can add the number to the list in one thread and you can see that the collection now contains one number and we can switch to the first fret or the second fret and we can add it here as well so now you can see that the collection contains two elements so we can simply resume everything and see that it failed immediately so the problem here is well it's a standard like race condition so in the debugger using this suspend threat breakpoints controlling each thread separately you can easily reproduce this situation in in your program and like prove that the problem is there so there is no need to wait for for many many test runs to to be just able to see that the problem is somewhere inside so how do we fix this and the most easy way is to just add this synchronization here and we do it like this and we run it again you can see there's no notification now here that the another thread is hit the breakpoint because it it's not so what it does right now we can dump threads from here what it does right now it's actually blocked because it wanted to enter this uh synchronized block and now it simply waits for the first thread to complete this so we can like go through this thread and then resume and now another thread entered this section and there will be no problems anymore so we can the breakpoint and see that it will never fail well we cannot guarantee that of course but we can wait for some time okay what else so in the breakpoints dialect there are a lot of settings here so these are filters and these filters allows you to specify not the exact place where you want to stay to stand but the more [Music] but as you're more tuning for conditions when you want to stop so consider this example we have a simple class human and it has an age and a name and a man is a human woman is a human and we have free person initialized here with their names and we call the age increment just in a loop for all of them so we set a breakpoint here and we debug this program [Music] and we can check that that some some person has the age increased so what if we don't care about other people here so we care only about paul for example so we can resume session now and we can see that we have mary here and we have max here and we have oh paul again but we are only interested in paul so the easiest solution for this using the information from the previous session is to set the condition here why not and we do it like this so everyone remembers and now if we resume we will only see modifications to the poll object and it's easy to do it like this if you have the easy condition for that so uh in this situation we had the name and it was unique through all the objects but it's not it's not the case always so for this particular case we have another solution so we can disable the condition and switch to the full view and enable the instance filters instance filters is the check for exact object id so in the debugger you can see it here so here is the unique id of the object in the debugger so it's not the identity hash code as in the vm itself it's the unique number in the debugger so if you want for example to for this breakpoint to stop only uh when in this object you can remember this number and you can enter it here in the instance filters and you will stop only in the poll object so well actually it's it's quite strange to remember something i i cannot remember it actually so there's an easy way for that actually we just deleted from here if you already stopped on a breakpoint you can call intentions menu from here alt enter and you can remove a breakpoint disable breakpoint from here you can edit breakpoint and also you can do much more with the breakpoints for example what we did before like stop only in the current object there is a special intention for this here and if we do that it will automatically do what we did before with with the hands it is much easier to do that from where there and you will be able uh to make it uh like without mistakes otherwise you will have to remember the number which is awkward and what if for example you are not interested in this one particular object but you are interested in a class of objects so for example we are interested in man objects any man this is where class filters is useful so once again you can set a class filter from here using the include exclude patterns you can search for the class this is really really ugly there's an easier solution for this and once again it's intentions so you can say that you are only interested in the man objects or you are interested in any other kind of objects so for example we say we don't stop in the class math and it will automatically add a filter for this here and actually there is a small minus in front meaning that it's an exclude filter so if we continue stepping we'll see but now we only stop in in a woman objects this is how you use the class filters there's another filter which is strange but sometimes useful and this is a pass count so let's first restart it and uh what if we want to skip like uh 10 times the breakpoint is hit and stop only on the next like 11th uh time we can use the pass count filter for this and you say you don't want to stop on the first 10 occurrences and you want to stop only on on the next one so you can see the age of three so there's three person there we skip like 10 iterations and we can go further and the next 10 iterations are skipped and we can go further and the program is finished so sometimes this is useful when you have this warm up which we discussed before but you don't want to set up um independent breakpoints for example but you know for sure that the warm up is not long enough and you just want to skip for example like first 10 times the first thousand times and then after that all the occurrences are good like equally good so you can skip whatever is in the beginning and stop only after that then you can use the pass count filter okay so let's go on the breakpoint types filters are good and the line breakpoints are good as well and in most cases line breakpoints are enough but not always consider this example so you have the base interface for your objects and it is called base interface um you get the instance of the object somewhere so literally somewhere get object and the object has several methods which you are interested in so you want to stop in those methods and if you want to stop in the full method for example you may go and set a line breakpoint in every class which overrides this method or implements this method you can do the same for buu but the error here may be super large like i don't know a hundred classes implements this method and you don't know for sure which one exactly uh object you will get from here and also you may not even know where the method is called so here of course you can set a breakpoint here but what but what about foo well basically idea tells us that it is not used so we'll check that in a moment so how do you do that there's an easy way for this and this is method breakpoints so you set a breakpoint on a method in the interface or the class and it will stop in every method overriding this or implementing this method so let's do it twice for four and boom methods and start the program okay so we immediately stop in the full method and as you remember the full method is unused at least idea told us so so what's happened let's check the call stack so first of all it is implemented in class three and this is already a good information for us and here you can see the icon here uh the breakpoint is not there so we set a breakpoint in the interface and the icon here appeared only to indicate that this is actually a breakpoint event so that you don't think that it's a step or something like that from here you can easily disable the breakpoint or delete it or modify it but the icon will disappear on on any step or any resume i mean disappear from from this class so what's happened why the method foo is called at all so let's check the call stack and also i think i forgot the last time to tell you about this nice button and it hides the frames from from libraries so here are a lot of frames from java which we are probably not interested in so i just click on that and hide them so here is the reason why the method fo is called it is called through reflection and of course idea is smart but not that smart to detect that the method is really used so using this method breakpoints it's really easy to find not only the place where the method is implemented not only the instance which is used to call this method but also using the stack trace it's easy to find out how the method is called if for example it looks like it isn't used so of course we have the same for boo and we stopped again because in settings of the method breakpoint you have two options to stop on method entry only or only exit or both so default is both so we'll you will stop on entry and exit and we resume and we stop and boo and we can see once again so it is called from here so it's it's obvious but we didn't need to set lane breakpoints in every kind of uh every class extending the base interface and it's really funny some sometimes to set such method breakpoints in some really widely used classes like runable so you can by not you can set a breakpoint in runable run interface method and then run the debug and see how and where runable run interface method is uh implemented and used by many different things inside the jdk inside your application inside everywhere so in idea i sometimes i don't know the exact class of the action for example so i have a button on the screen and i click there and i want to stop inside the handler for this section and i don't know the name for the action so i go to the an action class and put a method breakpoint on the action performed this is the very very base method for all actions in in the idea code and it takes just maybe 10 seconds because there are really huge number of implementers of that interface or the class i don't remember and after that i immediately stop in the exact action which calls the action performed method really easy to to find the exact places you want to be in the code so what's next let's get back to this next breakpoint type uh okay no so let's get back to the method breakpoint type there's more to this you can actually stop uh on a wildcard cart method breakpoint so from the breakpoints dialog you can click this plus sign and add the java method breakpoints and this method breakpoints is slightly different than the breakpoint we had seen before because here you can type a wildcards so for example you are interested in a main method inside your project's code maybe you don't know where it is so you start something and you want to know where the main method is so you immediately stop in in the first main method called anywhere in the program uh also you can do the same for example for a particular class so java lung string and we are interested in i don't know which which method um length so we don't know about string so we haven't yet even opened the the source code we may not even have that source code but we can set a breakpoint and we immediately stop there and you we can see where it is called from it's really interesting why it is called from here that's ah so i i hit this button so now it's not obvious but actually there is a lot of class loading here happening so this is this call from string length is is from inside the class loader okay so but more fun you think so you can set a breakpoint for any method in your packages and after that you will stop like on every method call or the constructor more of that if you are really really interested in in having like everything in your life stop everywhere you can do this well why not it's a debugger you can so you will stop like in every method in vacation every constructor every everything why not some people like to to trace every method call and you can you can once again you can do things like this so you set it to stop in every method and you may tell it not to suspend but instead like evaluate and lock something or the stack trace for example who knows sometimes it's useful okay so let's stop this and get back to the classes okay so the next breakpoint type is a field breakpoint so consider this example so we have a class and a field in this class and the field is modified in many many many many different places and after something is done with the object of this class we end up here so the question is oops it's um i think we have not deleted this breakpoint and it's really nice but we don't need that so the question is how do we get here why the field is the field value is eight in this case so we can set line break points in all places where the field is modified and there is actually an easy way for that i will show it to you i don't remember the shortcuts but there is a select all occurrences and it will add a correct to every occurrence and then you can click command f8 to set a breakpoint and you set line breakpoints in every kind of place where the variable is used you can do it this way but it's kind of awkward so the easy way to do this is to set a field watch point or field break point and when i click here on the field [Music] declaration you can see that it asks me if i want actually a field or a line break point and the line breakpoint here is uh uh happens because there is a an initializer for this here so you may be interested in in this initializer code so in debugging the code itself but we are not interested in that so we set a field breakpoint here and we can specify if we want to be stopped when the field is modified or even accessed so in our case maybe we set both and we restart the application so the first the first set to to this field of course is the initialization and then we resume and the next one is boo and we can check where it is called from right now because this tech trace is available and we can see that method do something is really do something with the object because it's kind of randomly calls methods from there so using this technique we can easily detect every place where the state is changed and see how how it is changed so sometimes it's not obvious who who does that using the field breakpoints it's easy okay so what's next and yes as long as we selected the modification here and the access finally we will appear in the read so this is a read obviously not the modification and if you're really interested once again you can combine it with the logging so like for every modification of the field [Music] we will log a stack trace and we then for example stop here and we restart it and we can see that after this do something it will provide us with all the places that changed the field so you can combine it any way you want what's next um another interesting breakpoint type and actually the last one is the exception breakpoint and so consider this code it does something and then it does something with an exception inside the loop uh so let's run it first and you can see that there are a lot of exceptions happening there so we are probably interested in the exact cause of this exception so we set a breakpoint inside the exception handler here inside the catch and we have an exception here and it's the arithmetic exception division by zero the stack trace of the exception is in the stack trace field of the exception and you can navigate to the frames from here and see that the exception actually happened inside the this method call and it was called from from this method and it was called from from our do something this is good already but we already lost all the runtime information so for example here we can see where the exception happened but we don't know the values of the numbers it would be nice to be able to stop uh in the place where the exception happened like before the throw not after inside the cage so this is what exception breakpoints are for actually so we can go to the breakpoints dialog and we can add a new exception breakpoint for example for arithmetic exception and you can see it here and we continue the application and now you can see that we stopped right on the fro statement so this is different than what we had before because now we have the exception so this is the exception object and it has the same stack trace and which we've seen before well not the same because it's different place but you got it and here you have all the runtime information so you have the values of the field so it's it's a regular stop in in the debugger so you can do whatever you want with the stack with the variables with everything else and if you do the step over from here because you are right before the throw you will stop in the catch uh corresponding to this exception so in our case it's it's our catch we've seen before so compare like here and there so there you have all the information here you have only the stack trace like the names of the frames and also if you are not interested in the particular breakpoint but you are rather interested in any breakpoint there is a special default any exception breakpoint and you can enable that and now you will stop on any exception in the application uh well usually it's too much but in in this case it's it's nice to see all the exceptions and you can check which kinds of exceptions are there so this is an npe and we can remove this breakpoint now and also we have this number format exception and you can check the stack traces and you can check how you got there so let's restart the application and now you can see that the exceptions may be coming from the code uh which are not ours so this do something we really don't care about and actually all exceptions will be caught inside that do something but this we still stop on these exceptions and you can control that in the exception breakpoint and i will show it to you how so there's a new filter for exception breakpoints called catch class filters and here you specify where the catch for this exception has to be located uh in order to stop on the fro statement because in in the program when the fro happens actually jvm is able to detect where the catch corresponding catch is and in the debugger when exception breakpoints happens uh debugger already knows where the catch will be so you can specify that you only interested in the exceptions that will be caught in your class so now we can continue and you can see that all the exceptions from here are skipped so we only stop on breakpoints which will be caught inside the our exception breakpoint class because we stated here also you can see in the settings that there is a new code or uncode uh checkboxes and uh well quote is is an exception which is called somewhere so there's a corresponding cache block somewhere and the uncode exception is the exception which is uncaught so there is no catch block anywhere and such exceptions will terminate the threat where they happen so for example if we unset the code exception and this we can then set as well and continue we will stop only on this exception and this is obviously the division by zero or ifmatic exception and it is uncaught and it will cause a program termination so if we are interested in the exceptions which kind of cause uh thread for a program termination like this we can specify that in the exception breakpoints so in large applications in idea for example of course there are not that many unquote exceptions because we cannot kind of afford to to stop idea on every exception uh so for large code base unquote exceptions are not that kind of often happens but sometimes they are okay advanced stepping so last time in the essentials part uh we saw the step over step into step out like the simple steps and and i call them simple because uh they have a button on the toolbar because everything which you have the button on the toolbar is simple because everybody used that but there's also another button here it's hidden right now because we are in the top frame but when we get somewhere deeper you will see how we can use that so this is our example of the endless application reading from the user doing some processing filtering nothing interesting actually so this is a filter method which is not that interesting as well let's stop in the process method so for example we stopped in on the line with the print line print line and we want to know how we got there so the arc value now is 204 well obviously when we entered the method it was a hundred so what this code does well we can we can check that with our eyes or uh most obviously we want to debug it again like step by step so how do we do that that we already at the end of the method so this is where the drop frame uh is really useful so what it does is basically it throws away everything you've done so far in the method in the current method and brings you to the place right before the method call so in this case if we click here we stop and we step back right before the process was called and now we can step into that again so if we continue we will stop on the breakpoint again and we can drop it again and we can step into again and we can continue that as much as many times as we want so here now that we entered the method from the beginning we can do some steps and we can enter some methods to figure out how how we got to this breakpoint here uh remember that uh if the state of the object or some other objects is changed in in the process of execution of this method this information will not be kind of rollback because the debugger cannot do that it doesn't remember everything you've done in the method but all the local variables all the local information is just thrown away and if you are inside the try finally block it will ask you if you want to execute finally block just in case because sometimes people kind of lock something and in the final block they unlock or free resources so if you just throw away everything you've done so far you may leave some garbage so it will ask you if you really want to do that without executing the final block or you want to execute them and it will execute it for you and then you will you will enter the method again and you can do that and you can do anything you want from the beginning uh you can do that for any number of methods actually on the stack so for example if you're inside the max you can drop this one and then drop this one and then step into that again so there's no limitation just just one that the main method the the only frame you cannot drop that because it makes no sense well it may make but it's a limitation uh what else you can do here so for example you are stopped in the filter and let's stop in the filter where the result is false so yeah right now so we can evaluate using alt click famous alt click and the return value will be false so what if we want it to be true and so once again we can hack the the read value set it to some some some value which passes this filter and then it will return true but there is an easier way to change the return value of the method there is an action you can use it from the context menu here or from the main menu i guess here somewhere and the action is called force return it will ask you about what you want to return and we say we want to return true so we return true and we do can we can do that not only from the return line so that we can do it from any line in the method like from the beginning from the middle from anywhere you just state that you don't want to run the method anymore you just want to return and this is what you want to return so in this case we return true so obviously we will go to the process now and this is really useful when you want to change the behavior of the application uh and the only behavior you want to change is the return value of something so you can do that from here and another useful thing is the throw exception uh so if you want to check how your program behaves if if an exception happens so for example do you have the catch block around everything or you want to check how the particular kind of the exception is handled inside your code this is also possible so from any place once again you can um run the throw exception action it is also available in the run menu and you specify what exact exception you want to throw here so uh as in every other place in the debugger it evaluates the value and and use it as as the return value as a an exception to fro uh so it's it's just like the any other expression so for example log expression it is evaluated and the value is used for something for logging in that particular case so here we say we want to throw a new illegal state exception and let's write something here and we throw it and you can see that we stopped immediately in the dispatch unquote exception it's a thread method for well for dispatching unhandled uncode exceptions because every thread has a such default dispatcher so we can see that the exception is not actually caught it caused the application death uh but sometimes it is useful not only for that but once again as i said uh you can check how the particular kinds of exceptions are handled in your code so if you have the catch block you will stop in the catch block and see how it is processed further okay so these were the advanced stepping actions let's go on remote debug uh not always the application you want to debug is on your machine and not always it is on the [Music] same i don't know even even in the same country so it may be anywhere in in the uh in the world actually uh so how do you connect to that machine from from your idea there's a special remote configuration for that so in the remote configurations there's a remote there's a remote configuration so here you specify the host and port of the machine of your machine and if you want the um if you want to attach to another process you specify that you want to attach and if you want it vice versa or the reverse you you specify that you want to listen to the connections from from the remote jvm and you specify the port and you get the line which you need to provide to the remote java process in order to be able to connect to that process so i already copied this line to the run configuration of this program so here you can see vm options i added it here and i can run it so i don't use debug i use run you can say you can see that the process is listening for transport at address 5007 and what we do is we run the debug configuration now and it will attach to that configuration you can imagine that this run is happening on a very different machine somewhere else and we type something here and you can see that we stopped inside the debugger on on this machine how is it is it useful so for example if you have the idea on your machine and it has bugs um and you want someone to to debug your situation or your setup so what you need to do is you need to specify this line to the toolbox or any other way you can access the vm options of the idea so you specify it there you start the idea you tell your ip or machine name and the port number to your colleague and they will create the remote run configuration and attach to your machine from their site so what's here in the command line which is provided the transport is the socket it it actually doesn't matter there on windows there's a shared memory transport but it's all the same server is yes once again if you want to someone to attach to your machine and it is said to know if you want to attach to the debugger yourself and suspend is no if you don't want the process to be suspended until the debugger is attached this is useful for example if you want someone to debug the startup process of the application then you specify suspend yes and the application will be suspended until the debugger is attached so so that they can can debug the the initialization of the application and the address is you just need to specify the port or you can leave it blank and the port will be auto detected and and printed in the console but you need to leave the asterisk here because starting from java 9 they figured out that many many web servers running java on the internet has the debug port opened and um well with the ability to attach to to a web server with the debugger you can do virtually anything with that so they added this asterisk um as a security um solution i don't want to say solution because it doesn't solve anything but uh if you don't specify this asterisk now you will be able to connect only from your local machine so only from the machine which the process is running at and you can also specify the ip address or the name of the machine which you want to connect from and it will allow those connections or you can specify the asterisk and saying that you know that you accept any connections from anywhere so now everyone specifies the asterisk and we have the same as before okay so uh now you know how to debug the remote colleagues from munich for example uh renderers okay so how much time do we have not much uh consider this example and this is the same human example we've had before but i named it human too just because it's in the same class so once again human has an age and a name and man extends human too and woman is a human too so we have free person here initialized and it's the same as it was before so we debug it and as before we stopped here but here to be able to understand what this object is about we need to check its fields and this is not really kind of good because for example here we see that the inside the collections there are three of them and if we are interested in in the exact kind of object properties we need to expand them and then so on and so forth so it's not really nice what can we do with this well actually all objects in the debugger are presented in this tree with the renderers so renderers shows what's gonna be shown here after the type and what's gonna be shown inside the kind of inside this node so as a sub nodes and by default we show the tostring value so the method to string of an object is executed and the value is shown here so we don't have the two string implemented for this class so we have nothing here and by default all the fields are shown as the sub nodes here for example all is the collection is a list and you can see that we have size equals to 3 here well actually for um arraylist i'm i'm i don't think this is a default to string value and also inside we don't have all the fields for the arraylist but other but we have the logical structure of the object so in this case the elements in the collection and this is because we render some types with the built-in renderers for collections for example and if you go to the context menu and select view as you will see all the renderers available for this object and for list it's a list obviously and you can switch to the default to string or an object and the difference is that object does not evaluate two string methods so this is the default to string for an array list and just listing all the objects inside and the fields are also shown so if you are not kind of a big fan of of the logical representation of your collection you can easily switch to the default from here so how do we change it for our classes first of all we can disable all the renderers at once as i said before renderers invoke methods and sometimes it may be slow for example for remote connections or it may cause issues with the object states if if your tostring for example change something and sometimes it happens uh multiple invocations of the tostring may cause troubles so the easiest way to do that is from the context menu you just select mute renders and it will disable all the renders making them actually lazy so this is a clickable link here now so if you're still interested in the size of the object you can click here and it will be evaluated and for for these we don't yet have any renders we'll implement them now so what if i want to have the tostring for this object i can go here and implement it so this is kind of this straightforward solution but which may not be kind of available because for example this class may be a library class or you are interested as a developer in some properties of the class and other developers may not be interested in them so there's an easier solution in the debugger for this and which is the create new renderer so you specify the select the class view as create and it will open a new render dialogue for you so this is red it's a bug don't look at that so here you can specify the expression which will be used used as a tostring and by default of course it's just the tostring so it's not that interesting in our case so we for example want to show the name of the person and also the age of the person so we can do it like this and we click on ok and now on every kind of every object it will be shown after the type so we can switch to the collection and now you can see that we have the name and age here we don't need to expand anything and there's nothing written for the woman object and that is because we created this for man so we can go here and and specify only human too and now we have it for any object extending the human to class so what else um as i said before you can switch those renders easily and you can make them lazy as i said before but per renderer so for example here you can click on demand and it will not evaluate those expression every time but rather do that when you need that so you can click on an object which you need this to be evaluated and it will evaluate it just like mute but only for one renderer what else can you do more funny stuff so let's disable this for now and here we have a simple implementation of multi-map which is a map containing a list of values for one key or a collection of values so it's it's a well it's not a copy it's a simplified version of multi-map we have in the idea source code base so if you debug it as long as multi-map is not a collection or a map so it does not implement like common interfaces it doesn't have a renderer so you can see that even though we added something there we don't see the size we don't see the elements so we we have to go further inside the object structure to be able to see what's inside so once again we can create a renderer for this and for size we want to take the my map size which is the internal structure kept inside and for the children so the sub nodes of of the object we want to show the entry set and you need to specify the array because it it requires an array so now you can see that the presentation of the object changed and it looks more like what we want to see there we can go further and then create renderers for the entries themselves if we want to but i think you got the point and what if you want to share this really nice renderer with your colleagues and there is an easy way now and this way is a debugger render annotation from the jetbrains annotations package available on moden and everywhere and you can add this annotation debug render to the class you want the debugger to to show and you specify the expressions which i've shown to you before so the text is the two-string presentation of the class that has children is the easy check if the node is expandable and the children array is the expression to be evaluated to get the actual children of the node and then you put this code to the code base and any other person debugging this code in the idea will see the object presented this way and this is what is done in the idea source code base for several for example for the multi-map i took it from there and for some other collections which do not extend the standard interfaces or the standard java collections classes so that we in the debugger we can see the logical structure this is actually what people usually want thank you that's it for today questions ah take the mic please so um is there any particular reason why you add that annotation but not just implement the string method photo string uh yes you can you can do this inside the two string but not this so uh you cannot change the presentation of the children of the note uh to string yes you can do that in the two strings okay thanks thank you very much for the talk you showed this logging expressions for breakpoints and idea can log this expression to console but is there a feature or maybe feature request to writing these logs into a file is it possible i think there is a request [Laughter] right now you can you can log all the console output to the file but not separately the debugger output munich maybe questions from you yeah i have one can you hear me uh can you speak louder because is it better now check check can you hear me okay cool uh maybe you can uh tell us a bit uh like what the difference uh like you told us about method and field breakpoints and nowadays they're fast in china and before they were uh implemented in a different way uh so maybe like a couple of minutes about this like i think it's called emulated method yeah yeah i got it i got it yes so i don't want to deep dive into this um the question is about method breakpoints um so there's a checkbox here saying emulated and um for many years we told our users not to use method breakpoints because they are really really slow and they really slow because when the jvm has a method breakpoint it will uh interpret every everything which is slow uh i don't know remember exactly the version where we implemented it differently so this emulation here enabled by default what it does it um do the search for all the methods overriding the method which you specified the breakpoint for and it set a line breakpoint inside the first line on them in the method and this is uh so much faster that we can finally use that and the emulation is the default and in some cases it doesn't work for example if you don't have the debug line in for for the class or it doesn't work for native methods but in all other cases it works and it works like several hundred times faster so we can finally use that so have i answered the question yeah call thank you more questions then thank you and hopefully to see you on the next session you
Info
Channel: IntelliJ IDEA by JetBrains
Views: 20,354
Rating: undefined out of 5
Keywords: debugging java, java, debugging in intellij, intellij java, intellij idea tutorial, intellij idea, debugger
Id: 40Og3hTV--k
Channel Id: undefined
Length: 73min 3sec (4383 seconds)
Published: Fri Feb 19 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.