fwcd / kotlin-debug-adapter

Kotlin/JVM debugging for any editor/IDE using the Debug Adapter Protocol
MIT License
110 stars 19 forks source link

Unable to stop at breakpoints and continue execution #65

Closed nela closed 1 year ago

nela commented 1 year ago

Hey,

Thanks for your work on this project! Looking forward to using it. I am however unable to use it properly yet. I use neovim with nvim-dap for my current setup.

System

$ ./gradlew -v

------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------

Build time:   2022-08-05 21:17:56 UTC
Revision:     d1daa0cbf1a0103000b71484e1dbfe096e095918

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.5 (Eclipse Adoptium 17.0.5+8)
OS:           Linux 5.15.0-52-generic amd64

Setup

Relevant configuration (hardcoded the paths to ensure it is working properly - changed when testing different projects):

{
        type = 'kotlin',
        request = 'launch',
        name = "Kotlin",
        projectRoot = '/home/nela/projects/ktest/app',
        mainClass = 'ktest.AppKt',
        auto_continue_if_many_stopped = false,
}

Issues

I'm having troubles with stopping at breakpoints and continuing execution after the breakpoint.

Using the Kotlin Quick Start, the debugger is unable to stop at given breakpoints. It outputs the greeting line and then [INFO] eventBus Sent exit event. Adding a loop such as : for (i in 1..5) { println(i) } and setting a breakpoint gives the following error:

[WARN] server    Could not fetch scopes, invalid stack frame: Thread has been resumed

Trying it out on another project the debugger indeed stops at given breakpoints, but stepping over or continuing gives the following error:

[ERROR] async0    Internal error: java.lang.IllegalThreadStateException
[ERROR] java.util.concurrent.CompletionException: java.lang.IllegalThreadStateException
[ERROR]     at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315)
[ERROR]     at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320)
[ERROR]     at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1807)
[ERROR]     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[ERROR]     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[ERROR]     at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR] Caused by: java.lang.IllegalThreadStateException
[ERROR]     at jdk.jdi/com.sun.tools.jdi.JDWPException.toJDIException(JDWPException.java:75)
[ERROR]     at jdk.jdi/com.sun.tools.jdi.EventRequestManagerImpl$EventRequestImpl.set(EventRequestManagerImpl.java:233)
[ERROR]     at jdk.jdi/com.sun.tools.jdi.EventRequestManagerImpl$EventRequestImpl.setEnabled(EventRequestManagerImpl.java:195)
[ERROR]     at jdk.jdi/com.sun.tools.jdi.EventRequestManagerImpl$EventRequestImpl.enable(EventRequestManagerImpl.java:180)
[ERROR]     at org.javacs.ktda.jdi.JDIThread.performStep(JDIThread.kt:49)
[ERROR]     at org.javacs.ktda.jdi.JDIThread.stepLine(JDIThread.kt:45)
[ERROR]     at org.javacs.ktda.jdi.JDIThread.stepOver(JDIThread.kt:37)
[ERROR]     at org.javacs.ktda.adapter.KotlinDebugAdapter$next$1.invoke(KotlinDebugAdapter.kt:310)
[ERROR]     at org.javacs.ktda.adapter.KotlinDebugAdapter$next$1.invoke(KotlinDebugAdapter.kt:309)
[ERROR]     at org.javacs.kt.util.AsyncExecutor.execute$lambda-1(AsyncExecutor.kt:16)
[ERROR]     at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804)
[ERROR]     ... 3 more
[INFO] eventBus  Sent exit event

Setting the breakpoint at another place, the debugger does execute the line under the breakpoint (it shouldn't) and produces following error:

[ERROR] server    Internal error: java.lang.reflect.InvocationTargetException
[ERROR] java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
[ERROR]     at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:67)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:120)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:261)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:190)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:194)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:94)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:113)
[ERROR]     at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
[ERROR]     at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
[ERROR]     at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
[ERROR]     at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
[ERROR]     at java.base/java.lang.Thread.run(Thread.java:833)
[ERROR] Caused by: java.lang.reflect.InvocationTargetException
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[ERROR]     at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[ERROR]     at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[ERROR]     at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[ERROR]     at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$null$0(GenericEndpoint.java:65)
[ERROR]     ... 11 more
[ERROR] Caused by: org.javacs.ktda.util.KotlinDAException: Could not find stackTrace with ID 2
[ERROR]     at org.javacs.ktda.adapter.KotlinDebugAdapter.scopes(KotlinDebugAdapter.kt:361)
[ERROR]     ... 16 more

The author of nvim-dap seems also to have tried running the Kotlin Debug Adapter, experiencing the same issues - which is why I am posting here.

Any thoughts on how to proceed with a fix?

themkat commented 1 year ago

Was the application built before debugging? I have gotten some weird errors if not building, or if build is older.

nela commented 1 year ago

Yep, the application(s) build and run successfully.

$ ./gradlew build

BUILD SUCCESSFUL in 1s
8 actionable tasks: 8 up-to-date

Also built and run prior to running debugger.

themkat commented 1 year ago

Would it be possible for you to log the request/responses (json objects) of the debug adapter to file? (in Emacs I can do this with dap-print-io, but unsure about the various vim-variants). Might be that the neovim plugin sends data in a way that confuses the language server or something :/ Would be easier to look for possible issues in that regard if I could see the request/responses. Larger chunks of the logs might also help if you could upload that :)

Tried cloning the quickstart project now, and was able to use it without issues in Emacs. The arguments you have supplied seems to be the same as I used when setting up the dap-kotlin setup in Emacs (might be worth a look for inspiration in case I have overlooked something above).

nela commented 1 year ago

Thanks for the reply! I've been looking into the issue and it turns out that it the error indeed was with nvim-dap and the way it handles thread execution. Here is the link to the discussion and fix for the problem. Although, there still might be some issues regarding two stopped events for the same thread without any continue/step in-between - see this comment

Here is a gist showing full logs between nvim-dap end Kotlin Debug Adapter.

I am also experiencing some issues with the spring boot projects. Using a spring-boot-kotlin demo, the Debugger seems to have problems with dependency resolutions. Here is the output I get when trying to set breakpoints and debug:

[INFO] main      Connected to client
[INFO] async1    Found mvn at /home/nela/.local/share/asdf/shims/mvn
[INFO] async1    Run [/home/nela/.local/share/asdf/shims/mvn, dependency:list, -DincludeScope=test, -DoutputFile=/tmp/deps15176148338603586867.txt, -Dstyle.color=never] in /home/nela/projects/kotlin-tutorials/spring-boot-kotlin
[INFO] async1    Run [/home/nela/.local/share/asdf/shims/mvn, dependency:sources, -DincludeScope=test, -DoutputFile=/tmp/sources2061694013933146372.txt, -Dstyle.color=never] in /home/nela/projects/kotlin-tutorials/spring-boot-kotlin
[WARN] async1    Couldn't find io.netty:netty-transport-native-epoll:4.1.34.Final in /home/nela/.m2/repository/io/netty/netty-transport-native-epoll/4.1.34.Final/netty-transport-native-epoll-4.1.34.Final.jar
[INFO] async1    Run [/home/nela/.local/share/asdf/shims/mvn, dependency:list, -DincludeScope=test, -DoutputFile=/tmp/deps3469807033879373704.txt, -Dstyle.color=never] in /home/nela/projects/kotlin-tutorials/spring-boot-kotlin
[INFO] async1    Found 120 artifacts in /home/nela/projects/kotlin-tutorials/spring-boot-kotlin/pom.xml
[WARN] async1    Couldn't find io.netty:netty-transport-native-epoll:4.1.34.Final in /home/nela/.m2/repository/io/netty/netty-transport-native-epoll/4.1.34.Final/netty-transport-native-epoll-4.1.34.Final.jar
[INFO] async1    Starting JVM debug session with main class com.baeldung.springbootkotlin.KotlinDemoApplication
Error: Main method not found in class com.baeldung.springbootkotlin.KotlinDemoApplication, please define the main method as:
   public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application
[INFO] eventBus  Sent exit event

I find it strange that warnings for not finding libs is issued, because they do exists on the specified path. I assume this has something to do with setting the mainClass in spring boot projects. Any advice on how to approach this?

themkat commented 1 year ago

@nela , Have you named the class with @JvmName? If not I would guess that you could add Kt to the end of the name to make it work. Something like com.baeldung.springbootkotlin.KotlinDemoApplicationKt. The Kotlin compiler adds Kt to the filenames when generating classes.

nela commented 1 year ago

The issue must have been the improper mainClass configuration. Anyhow, my initial issue was resolved as stated above so I'll go ahead and close this. Thanks for the help!

mairs8 commented 2 months ago

@nela i also had issues with the auto_continue_if_many and dependency injections. keen to understand if you were able to effectively write and debug in neovim on these more complex projects. how did it go?

nela commented 2 months ago

@mairs8 I've managed to get it working with this config, although it's been some time since I've used it so some tweaking might be necessary. I did use it for a short time, however, it kept bothering me that it data was shown in a Java context, rather than Kotlin context. Ultimately, I had to switch to IntelliJ due to the performance difficulties of Kotlin LSP and DAP.