{"id":483131,"date":"2024-06-14T12:45:56","date_gmt":"2024-06-14T11:45:56","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=idea&#038;p=483131"},"modified":"2024-07-08T14:07:42","modified_gmt":"2024-07-08T13:07:42","slug":"debugger-upskill-debug-without-breakpoints","status":"publish","type":"idea","link":"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2024\/06\/debugger-upskill-debug-without-breakpoints","title":{"rendered":"Debugger Upskill: Debug Without Breakpoints"},"content":{"rendered":"<p>In a typical debugging scenario, you would set breakpoints to tell the debugger when to suspend your program. A breakpoint usually corresponds to the moment that marks the starting point for further investigation.<\/p>\n<p>Deciding where to set a breakpoint can be challenging. There might be situations where the exact line is unclear, or you might prefer to pause the program based on timing rather than specific code.<\/p>\n<p>In this article, we\u2019ll look at IntelliJ IDEA\u2019s <i>Pause Program<\/i>  feature \u2013 a lesser known debugging technique that can be extremely powerful in some scenarios, including the ones described above. We\u2019ll discuss its use cases and limitations, as well as discover the secret stepping trick.<\/p>\n<h2>What <i>Pause Program<\/i> does?<\/h2>\n<p><i>Pause Program<\/i> is a feature in IntelliJ IDEA\u2019s debugger that enables you to arbitrarily suspend your application at any given point in time. What\u2019s more, you don\u2019t even have to be familiar with the application code. In fact, you can just ignore it altogether!<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/flounder.dev\/img\/pause-button-dark.png\" width=\"692px\" alt=\"Pause button on the debugger's toolbar\"\/><\/p>\n<p>To pause a program, click <i>Pause Program<\/i> on the debugger\u2019s toolbar. Then, the program will suspend right in the middle of whatever it\u2019s doing.<\/p>\n<h2>Limitations<\/h2>\n<p>At first sight, a paused program may look exactly like the one that has been suspended at a breakpoint. However, this is only true to a certain extent.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/flounder.dev\/img\/paused-program-dark.png\" width=\"692px\" alt=\"Debugger looks the same regardless of whether Pause or a breakpoint was used to suspend the app\"\/><\/p>\n<p>It would be correct to consider <i>Pause Program<\/i> a sort of enhanced thread dump. You can still inspect variables and threads just as you typically would, but some of the more advanced debugging features, like <i>Evaluate Expression<\/i>, won\u2019t work.<\/p>\n<h2>Use cases<\/h2>\n<p>There are countless ways you can use <i>Pause Program<\/i>, which can often be used interchangeably with traditional breakpoints. However, there are scenarios where using <i>Pause Program<\/i> is a more fitting approach. Let\u2019s consider a couple of them.<\/p>\n<h3>Unresponsive apps<\/h3>\n<p>If the UI freezes or seems unresponsive, it&#8217;s usually because the UI thread is blocked or busy with a time-consuming task.<br \/>\n<img decoding=\"async\" src=\"https:\/\/flounder.dev\/img\/inspect-blocked-thread-dark.png\" width=\"692px\" alt=\"The stack of the blocked UI thread shows what method it is currently executing\"\/><br \/>\n<i>Pause Program<\/i> could be useful in both those cases, as it allows you to <a href=\"https:\/\/blog.jetbrains.com\/pt-br\/idea\/2021\/10\/unfreeze-your-apps\">pause the application while it\u2019s unresponsive<\/a> and examine the call stack of the UI thread. This is often sufficient to diagnose the problem.<\/p>\n<h3>Missing sources<\/h3>\n<p>As previously mentioned, <i>Pause Program<\/i> allows you to simply ignore the source code, which might be missing for you anyway. Although this scenario is not very common, when you do encounter it, breakpoints wouldn\u2019t be of any help. That\u2019s where <i>Pause Program<\/i> <a href=\"https:\/\/flounder.dev\/posts\/debugger-god-mode\/\" target=\"_blank\" rel=\"noopener\">comes in<\/a>!<\/p>\n<h3>Locks<\/h3>\n<p>If you suspect a synchronization problem, such as a deadlock or a livelock, <i>Pause Program<\/i> might help you find the exact threads and locks causing the issue.<br \/>\n<img decoding=\"async\" src=\"https:\/\/flounder.dev\/img\/debug-locks-with-pause-dark.png\" width=\"692px\" alt=\"The list of threads shows which threads have ended up in a deadlock\"\/><\/p>\n<p>In this case, pause the program and inspect the thread list. It will show which threads are blocked. By navigating to the execution point, you\u2019ll also see the critical sections they are locked in. This information might help guide you toward a solution.<\/p>\n<h2>Secret stepping trick<\/h2>\n<p>As we pointed out earlier, <i>Pause Program<\/i> indeed limits your access to some of the advanced debugger features. If you\u2019ve tried to use certain features while an application is paused, you may have seen an error message that reads <i>Cannot evaluate methods after Pause action<\/i>.<br \/>\n<img decoding=\"async\" src=\"https:\/\/flounder.dev\/img\/debugger-god-mode\/cannot-evaluate-after-pause-dark.png\" width=\"370px\" alt=\"An error message saying 'Cannot evaluate methods after Pause'\"\/><\/p>\n<p>Nevertheless, there is a workaround for this restriction.<br \/>\nAfter you have paused an application, proceed by performing any stepping action. A simple <i>Step Into<\/i> or <i>Step Over<\/i> will do. Once that\u2019s done, you\u2019ll find yourself in a regular debugging session, similar to when you suspend an application using a breakpoint.<br \/>\nAll advanced features are now unlocked!<\/p>\n<h2>Conclusion<\/h2>\n<p>That\u2019s it for today! We hope you find these tips and tricks useful.<br \/>\nIf there\u2019s something specific about Java debugging you want us to cover, don\u2019t hesitate to reach out! Your feedback will help in prioritizing and publishing the content that is most interesting and valuable to you.<\/p>\n","protected":false},"author":1206,"featured_media":483574,"comment_status":"closed","ping_status":"closed","template":"","categories":[4759,2347],"tags":[632,264,31,40],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/483131"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/types\/idea"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/users\/1206"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/comments?post=483131"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/483131\/revisions"}],"predecessor-version":[{"id":491410,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/idea\/483131\/revisions\/491410"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media\/483574"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/media?parent=483131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/categories?post=483131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/tags?post=483131"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/pt-br\/wp-json\/wp\/v2\/cross-post-tag?post=483131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}