Montag, 31. August 2020

Debugging Java with JDB or Vim

 Debugging Java with IntelliJ IDEA or VSCodium and its Java plugins (Debugger for Java, Language Support for Java(TM) by Red Hat) is kind of easy. But doing it without those tools is tricky.

Getting Java support in Vim with the help of vim-lsp and vim-lsp-settings is done quickly:

  • Adding a few lines of Plug into the .vimrc:
    • │     Plug 'prabirshrestha/async.vim'
    • │     Plug 'prabirshrestha/vim-lsp'
    • │     Plug 'mattn/vim-lsp-settings'
    • │     Plug 'prabirshrestha/asyncomplete.vim'
    • │     Plug 'prabirshrestha/asyncomplete-lsp.vim'
  • :PlugInstall will then install those.
  • Next open a java-file and install the language server:

Without further config fiddling my maven and gradle projects work.

Just debugging is a pain…

Prints all over the place is not a solution for everything. But using a big IDE just for that seems also a little wrong.

Running the debug-process with maven:

Because I couldn't figure it out easily in the beginning, I was using those for debugging via starting my tests via:

$ ./mvnw test -Punit-tests -Dtest=*UnitTest -Dmaven.surefire.debug

The maven.surefire.debug plugin will start a server, listening on port 5005 before it starts going over the tests.

Connecting via IntelliJ IDEA:

  • Adding a Debug-Run configuration
  • Adding information about the remote running debug-process

After adding it, you can connect to the remote debugging process. But when it is successfully connected, it will directly continue executing the code. So make sure to have set some breakpoints before you connect.

Connecting via VSCodium:

  • Again it needs a configuration: Run → Add Configuration → Java

 

  •  Which will create and open a little template configuration

  • Adjust it to have the remote connection inside

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "java",
            "name": "Debug (Launch) - Remote",
            "request": "attach",
            "hostName": "localhost",
            "port": 5005,
            "sourcePaths": ["src/main/java", "src/test/java"]
        }
    ]
}

After that it is again like with IntelliJ IDEA, start the debug-process, wait till it is ready to accept the connection, put some breakpoints in your code in VSCodium, hit "Run → Start Debugging" to connect to it and debug it.

Connecting with JDB:

This is a short one:

$ jdb -sourcepath src/main/java:src/main:src -attach 5005
This time it is connecting, but not directly continuing the debugging. The interface is not up to modern times. There is no readline support, so you don't have a history, can't edit somewhere in your command, no colors, …

Create your breakpoints with "stop at org.demo.app.Application:42" or "stop in org.demo.app.Application.methodname". Then you do "run" and it will execute the code hopefully up until your breakpoints. with "print" and "dump" you can look at objects, "step" and "next" get you forward a bit, "cont" a lot. More commands are listed under "help".

Connecting with Vim:

This one is a little bit more tricky.

  • First we need Vimspector. It is a frontend for debugger inside Vim. For installation we use Plug again and add inside the .vimrc:

    │     Plug 'puremourning/vimspector'

    :PlugInstall

  • Depending on your preferences they provide some default keybindings. One sane one would be:

    │ let g:vimspector_enable_mappings = 'HUMAN'

    With that you get the following keys bound:

    "   <F3>     VimspectorStop
    "   <F4>     VimspectorRestart
    "   <F5>     VimspectorContinue
    "   <F6>     VimspectorPause
    "   <F8>     VimspectorAddFunctionBreakpoint
    "   <F9>     VimspectorToggleBreakpoint
    "   \<F9>    VimspectorToggleConditionalBreakpoint
    "   <F10>    VimspectorStepOver
    "   <F11>    VimspectorStepInto
    "   <F12>    VimspectorStepOut

  • Now you need an adapter. You can install it from within Vim via:
    :VimspectorInstall vscode-java-debug
  • If you would run the debugger now by hitting F5, it would give you an error about missing configurations. Put a .vimspector.json file in your project folder and fill it with the following code:

    {
      "configurations": {
        "Java Attach": {
          "adapter": "vscode-java",
          "configuration": {
            "request": "attach",
            "hostName": "${host}",
            "port": "${port}",

            "projectName": "${projectName}",
            "sourcePaths": [
              "${workspaceRoot}/src/main/java",
              "${workspaceRoot}/src/test/java"
            ]
          }
        }
      }
    }

  • You can replace ${host} and ${port} directly here, else you will need to enter those again each time you let the debug run.
  • Adjust projectName to the name of your project or you will get the message "Cannot evaluate, please specify projectName in launch.json" when you want to use :VimspectorEval to evaluate code.
  • Running the debug via F5 now will ask for host and port, but also for another port for the DAP. This is the port of the debug server, which we still need to install.
  • The debug server for Java comes from Microsoft. Clone the git repository and do the as they suggest:
    ./mvnw clean install
  • This gives in my case the needed jar at:

    $HOME/.m2/repository/com/microsoft/java/com.microsoft.java.debug.plugin/0.28.0/com.microsoft.java.debug.plugin-0.28.0.jar
  • eclipse-jdt-ls will use that java-debug as a plugin, but for that we need to announce that to it. In our case we can use the lsp_settings inside the .vimrc to do so:

    let g:lsp_settings = {
        \ 'eclipse-jdt-ls': {
        \     'initialization_options': {
        \         'bundles': [
        \             '/home/$USER/.m2/repository/com/microsoft/java/com.microsoft.java.debug.plugin/0.28.0/com.microsoft.java.debug.plugin-0.28.0.jar'
        \         ]
        \     }
        \ }
    \ }

  • The DAP server will not start automatically when we want to do some debugging. Therefor we need to start it from within Vim by notifying the eclipse-jdt-ls to do so:

    :call lsp#send_request('eclipse-jdt-ls', {'method': 'workspace/executeCommand', 'params': {'command': 'vscode.java.startDebugSession'}, 'on_notification': function('lsp#utils#error')})

    This sends the request to start the debug session to the eclipse-jdt-ls, and puts the returned message as output on the vim messages as error. The important part is the result, which is the port that we will put into the DAPPort:

    {'response': {'id': 3, 'jsonrpc': '2.0', 'result': 43071}, 'request': {'id': 3, 'jsonrpc': '2.0', 'method': 'workspace/executeCommand', 'params': {'command': 'vscode.java.startDebugSession'}}}
Finally, having all parts installed and set up, we can do some debugging in Vim:
  • start the debug process via maven, which opens the port 5005
  • start the vscode.java-debug-session, which gives an open port, like 43071
  • put breakpoints in your code via F9
  • start debugging in Vim via F5, put in localhost as host, 5005 as port, and 43071 for DAPPORT

Edit:

Sometimes it happened for me, that the eclipse-jdt-ls doesn't want to start again, and :LspStatus will just give eclipse-jdt-ls: exited . Looking at the vim-lsp.log didn't give any meaningful or helpful information. Neither the log of the server found at: ~/.local/share/vim-lsp-settings/servers/eclipse-jdt-ls/data/.metadata/.log

But I found a little hint at the eclipse-jdt-ls repository about Java 9 or newer. Adding those extra and missing options:

--add-modules=ALL-SYSTEM --add-opens java.base/java.util=ALL-UNNAMED --add-opens java.base/java.lang=ALL-UNNAMED

to the end of the java-line in the ~/.local/share/vim-lsp-settings/servers/eclipse-jdt-ls/eclipse-jdt-ls file seems to help.

3 Kommentare:

  1. If you use YouCompleteMe you don't need to setup a DAP-Server as it comes with one. The interaction between YCM and Vimspector is pretty good.

    But anyway, thx for this article as setting up Vimspector for Java is kind of a struggle, at least for me :)

    AntwortenLöschen
  2. Got almost there, but at the end I see E716: Key not present in Dictionary: "eclipse-jdt-ls"

    Any suggestions?

    AntwortenLöschen
    Antworten
    1. Did you put it into the g:lsp_settings inside your vimrc, like mentioned above? And adjusted the bundles-path?

      Löschen

[Review/Critic] UDock X - 13,3" LapDock

The UDock X - 13.3" LapDock is a combination of touch display, keyboard, touch-pad and battery. It can be used as an extension of vari...