{"id":1380,"date":"2020-11-17T16:27:23","date_gmt":"2020-11-17T15:27:23","guid":{"rendered":"https:\/\/www.thomaskeller.biz\/blog\/?p=1380"},"modified":"2025-06-26T09:26:16","modified_gmt":"2025-06-26T08:26:16","slug":"debugging-with-gradle","status":"publish","type":"post","link":"https:\/\/www.thomaskeller.biz\/blog\/2020\/11\/17\/debugging-with-gradle\/","title":{"rendered":"Debugging with Gradle"},"content":{"rendered":"\n<p>If you want to debug something that is build \/ run with Gradle, you have a few options. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"alignleft size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"660\" height=\"828\" src=\"https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.56.51.png\" alt=\"\" class=\"wp-image-1381\" style=\"width:124px;height:155px\" srcset=\"https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.56.51.png 660w, https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.56.51-359x450.png 359w\" sizes=\"auto, (max-width: 660px) 100vw, 660px\" \/><\/figure>\n<\/div>\n\n\n<p>In all cases, your IDE needs to be set up to listen to a remote JDWP (Java Debug Wire Protocol) connection. In IntelliJ this looks like this: Go to &#8220;Edit configurations&#8221;, hit the &#8220;+&#8221; button on the top left corner, select &#8220;Remote&#8221; and give your run configuration a name. Leave the other configuration options as-is. (As Gradle will always start the debug server for us, we leave &#8220;Attach to remote JVM&#8221; selected.) Finally, hit &#8220;OK&#8221;.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"alignleft size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"651\" src=\"https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-1024x651.png\" alt=\"\" class=\"wp-image-1382\" srcset=\"https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-1024x651.png 1024w, https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-450x286.png 450w, https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-768x488.png 768w, https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-1536x976.png 1536w, https:\/\/www.thomaskeller.biz\/blog\/wp-content\/uploads\/2020\/11\/Bildschirmfoto-2020-11-17-um-15.57.17-2048x1301.png 2048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n<\/div>\n\n\n<p>Now to the actual debugging.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging JUnit tests<\/h3>\n\n\n\n<p>More often than not you cannot debug a unit test properly inside the IDE. Even if you use the Gradle builder in IntelliJ for example there are times where the IDE simply won&#8217;t get the classpath right and your tests fail with obscure errors.<\/p>\n\n\n\n<p>Now with Gradle we don&#8217;t need to start the tests from within the IDE to debug them, luckily! All we need is this:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> .\/gradlew app:testDebug --tests MyAwesomeTest --debug-jvm<\/pre>\n\n\n\n<p>This is an example from an Android project, but you can think of any other test flavor here. With <code>--tests<\/code> we define the test we&#8217;d like to run (to avoid having to wait for all tests of the module to be executed) and <code>--debug-jvm<\/code> lets Gradle wait for our debugger to attach, before the test is executed.<\/p>\n\n\n\n<p>Now you can put breakpoints into your code and start the pre-configured &#8220;Gradle&#8221; run configuration in &#8220;Debug&#8221; mode. As soon as you see &#8220;&#8230; connected&#8221; in the IDE, the command line execution will continue, execute your test and eventually stop on your breakpoints.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Debugging Gradle build scripts<\/h3>\n\n\n\n<p>Debugging Gradle build scripts itself is possible by starting any Gradle command with an additional, slightly different argument:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.\/gradlew myAwesomeTask -Dorg.gradle.debug=true<\/pre>\n\n\n\n<p>Here again, Gradle will start up and wait for your IDE to connect to the debug server, then continue executing your task and eventually stop on your breakpoints.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">I can&#8217;t connect to my debugger!<\/h3>\n\n\n\n<p>If you run your debugger on a different server or inside a Docker container, ensure that you open the debug server for all ports, not just <code>localhost<\/code>, which is the default, by adding<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>-Dorg.gradle.debug.host=*<\/code><\/pre>\n\n\n\n<p>or by configuring it for your test execution like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>tasks.withType&lt;Test> {\n    debugOptions.host.set(\"*\")\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Not so fast, my breakpoints are not hit!<\/h3>\n\n\n\n<p>Well, it wouldn&#8217;t be Gradle if it would be that easy, right? Right!<\/p>\n\n\n\n<p>Issue is that in a &#8220;properly&#8221; configured Gradle project there are probably multiple things set up to speed up your build. First and foremost, a running Gradle Daemon in the background might be re-used and you might fail to attach to that Daemon again once you disconnected from it once. So, best option here is to disable the usage of a global daemon for your run and just spawn a specific daemon for the command you want to debug:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.\/gradlew --no-daemon ...<\/pre>\n\n\n\n<p>(There is also an <code>org.gradle.daemon.debug<\/code> option to debug the daemon itself, but I never found a useful way of working with this. Would be helpful for feedback on this one :))<\/p>\n\n\n\n<p>Secondly, you might have a build cache set up (either locally or remote). If you run tasks that ran through successful once, Gradle will just use the default outputs and skip task execution completely. (You&#8217;ll notice that usually when the Gradle output says something like &#8220;x tasks executed, y tasks cached, &#8230;&#8221;.) So, disable caching temporarily as well:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">.\/gradlew --no-daemon --no-build-cache ...<\/pre>\n\n\n\n<p>Lastly, specifically if you execute tests, you should remove the previous test results, so your test is actually executed again:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">rm -rf app\/build\/reports &amp;&amp; \\\n  .\/gradlew --no-daemon --no-build-cache ...<\/pre>\n\n\n\n<p>Now your breakpoints should be hit for real. Happy debugging!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you want to debug something that is build \/ run with Gradle, you have a few options. In all cases, your IDE needs to be set up to listen to a remote JDWP (Java Debug Wire Protocol) connection. In IntelliJ this looks like this: Go to &#8220;Edit configurations&#8221;, hit the &#8220;+&#8221; button on the &hellip; <a href=\"https:\/\/www.thomaskeller.biz\/blog\/2020\/11\/17\/debugging-with-gradle\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Debugging with Gradle<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-1380","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts\/1380","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/comments?post=1380"}],"version-history":[{"count":8,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts\/1380\/revisions"}],"predecessor-version":[{"id":1455,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts\/1380\/revisions\/1455"}],"wp:attachment":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/media?parent=1380"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/categories?post=1380"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/tags?post=1380"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}