在 Gradle 和 IntelliJ 2016.3.5 中使用断点调试 JVM 应用程序(Java 或 Scala)

Debugging of a JVM application (Java or Scala) with breakpoints in Gradle and IntelliJ 2016.3.5

我有一个 JVM 应用程序,我需要在 IntelliJ 2016.3.5 中使用带有 Gradle 任务(运行 并作为依赖项进行测试)的断点进行调试。

关于如何使用 Gradle 和 IntelliJ 完成调试的各种来源:

  1. Debug Gradle plugins with IntelliJ
  2. Using Intellij to set breakpoints in gradle project(最有帮助)
  3. https://youtrack.jetbrains.com/issue/IDEA-119551
  4. https://youtrack.jetbrains.com/issue/IDEA-86465
  5. https://youtrack.jetbrains.com/issue/IDEA-119494

但是,这些来源要么已过时,要么适用于其他情况。我不想调试 Gradle 脚本,而是调试 运行 实际 Java/Scala 应用程序的 JVM。此外,最新版本的 IntelliJ 使用 Gradle 工具 API,它不提供关闭守护进程的选项。 JetBrains 的本机支持仅使用 运行 上的调试按钮提供,并直接测试任务,但如果它们被定义为来自另一个任务的依赖项(例如,检查)则不会提供。

根据消息来源,这是接下来要走的路:

run { // or test, doesn't matter
    jvmArgs "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
    // xor, or both, doesn't seem to make any difference
    debug true
}

无论如何,Gradle(或 JVM)随后将开始侦听端口 5005:

然后,我使用以下参数创建了一个远程配置:

但是当我启动 IntelliJ 远程调试任务时,它失败了:

我也尝试过使用端口 5006 和 suspend=n 但没有成功。在此之前,我尝试在 IntelliJ-Gradle 运行 任务中使用 Gradle 参数。然后,它确实连接了,但似乎连接到 Gradle 脚本而不是应用程序 JVM,因为它没有在断点处中断。如何解决这个问题?

同时,我自己找到了解决方案。如果您遇到类似问题,请使用调试选项按照上述方法进行操作。

test {
    debug true
}

但请确保在 IntelliJ 重启后在设置中接受外部连接:

然后,它连接到正确的 JVM 并使用远程任务在断点处中断:

但是,如果您重新启动 IntelliJ,并启用相同的选项(外部连接),则调试任务可能会因端口阻塞而失败:

因此,出于某种原因,IntelliJ 在重新启动后会阻止该端口,但必须启用调试任务才能运行的设置。这很奇怪,我不认为它打算那样做。

无论如何,如果您禁用设置并重新启动,端口将再次打开。然后,重新启用设置,不要重启,只是运行Gradle任务,还有调试任务。它会起作用。

我希望这可以帮助其他任何人寻找一种中间解决方案来调试使用 Gradle 和 IntelliJ 的 JVM 应用程序,其中包括令人困惑和部分过时的答案。如果有人有更好或更简单的建议,请随时附上您的答案。

调试 gradle 任务,如 'test'、'run',实际上所有 gradle 实现 JavaForkOptions 接口的任务,自 2014 年以来应该在 IntelliJ 中工作