Skip to content

Latest commit

 

History

History
411 lines (372 loc) · 20.3 KB

Configuration.md

File metadata and controls

411 lines (372 loc) · 20.3 KB

Java Debug Configuration

Table of Contents

The debugger provides two kinds of configuration: launch.json and settings.json (User Settings), see the README for the supported configuration list. launch.json is used to control the configuration per debug session, and the user setting is shared by the whole workspace or VS Code.

Auto generate the launch.json

When you run the program via Run|Debug CodeLens or Run/Debug context menu, the debugger automatically generates the launching configuration for you. runMenu

Modify the launch.json

If you don't see .vscode/launch.json in your VS Code window, you can go to "Run and Debug" viewlet to create an initial launch.json. create launch.json

On the other hand, the debugger provides multiple configuration templates to help you to easily add a new configuration. When you type "java" or "" in launch.json, it will trigger auto-completion suggestions. launchConfig

In case you want to manually edit the configuration, below are the explanation and samples about the common debug configurations.

Main

  • mainClass - mainClass is used to define your program entry, and it's the most important configuration. The debugger provides three options to help you configure this key, see the samples below.

    • "mainClass": ""
      If you have no idea about what to set here, just leave it empty. The debugger will search all possible main classes from the workspace, then prompt you the list to choose for launch.
      emptyMainClass

    • "mainClass": "${file}"
      If you have multiple main Java files, use this to auto switch to your current focus program. The debugger will resolve the main class from current active Java file, and set it as the launching main class. currentFile

    • "mainClass": "com.microsoft.app.myApp"
      The fully qualified class name, generally it's filled by the debugger's auto generation.
      mainClass

  • projectName - The preferred project in which the debugger searches for classes. It's required for the evaluation feature. Most of the time, the debugger will auto generate the configuration for you. In case you want to manually configure it, here are the rules.

    • When you open a maven project, the project name is the artifactId.
    • When you open a gradle project, the project name is the baseName or the root folder name.
    • When you open other Java files, leave the launch.json empty and allow the debugger auto generates the project name for you.

    Pro Tip: The easiest way to get the project name is to install Java Dependency Viewer extension, the top node in the JAVA DEPENDENCIES view is your project name.
    java-dependency-viewer

Arguments

  • args - Program arguments which are used to pass application configuration to your program, and they are accessible via "args" String array parameter in your main method public static void main(String[] args). It accepts three kinds of value, see the samples below.

    • "args": "arg0 arg1"
      Space separated String value. programArgs

    • "args": ["arg0", "arg1"]
      An array of String.

    • "args": "${command:SpecifyProgramArgs}"
      The debugger will prompt you with an input box to type the args value before launching the program. This is convenient when you have a program running against multiple data set.
      specifyArgs

  • vmArgs - VM arguments are used to configure JVM options and platform properties. Most of these arguments have a prefix (-D, -X, -XX). For example, -Xms256m arguments defines the initial Java heap size to 256MB. And you can also use -DpropertyName=propertyValue to configure system properties for your program. These properties are read via API System.getProperty(propertyName). It accepts a String or an array of String, see the samples below.

    • "vmArgs": "-Xms256m -Xmx1g -Dserver=production"
      Space separated String value.
    • "vmArgs": ["-Xms256m", "-Xmx1g", "-Dserver=production"]
      An array of String.

Environment

  • console - The specified console to launch the current program. Current default value is integratedTerminal. You could customize it via the global user setting java.debug.settings.console for the whole workspace, or console in launch.json for each debug session. The console option in launch.json (if provided) takes precedence over java.debug.settings.console in user settings.

    • "console": "internalConsole"
      VS Code debug console (input stream not supported). If you're developing backend application, internalConsole is recommended. internalConsole

    • "console": "integratedTerminal"
      VS Code integrated terminal. If you're developing console application with io input requirements, you must use the terminal to accept user input. For example, use Scanner class for user input.
      integratedTerminal

    • "console": "externalTerminal"
      External terminal that can be configured in user settings. The user scenario is same as integrated terminal. The difference is opening an external terminal window to run your program.
      externalTerminal

  • env - The extra environment variables for the program. It's accessible via System.getenv(key). It accepts key-value pairs.

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "type": "java",
                  "name": "Launch Hello",
                  "request": "launch",
                  "env": {
                      "HOST": "127.0.0.1",
                      "PORT": 8080
                  }
              }
          ]
      }
  • envFile - Absolute path to a file containing environment variable definitions.

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "type": "java",
                  "name": "Launch Hello",
                  "request": "launch",
                  "envFile": "${workspaceFolder}/.env"
              }
          ]
      }

Don't step into the specified classes or methods

  • stepFilters - Skip the specified classes or methods you don't want to step into. Class names should be fully qualified. Wildcard is supported.
    • Skip the class loader.

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "type": "java",
                  "name": "Launch Hello",
                  "request": "launch",
                  "stepFilters": {
                      "skipClasses": [
                          "java.lang.ClassLoader",
                      ]
                  }
              }
          ]
      }

      skipClassLoader

    • Skip the JDK classes.

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "type": "java",
                  "name": "Launch Hello",
                  "request": "launch",
                  "stepFilters": {
                      "skipClasses": [
                          "$JDK"
                      ]
                  }
              }
          ]
      }

      skipJDK

    • Skip the constructors and the synthetic methods.

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "type": "java",
                  "name": "Launch Hello",
                  "request": "launch",
                  "stepFilters": {
                      "skipSynthetics": true,
                      "skipStaticInitializers": true,
                      "skipConstructors": true
                  }
              }
          ]
      }

      skipMethods

Attach to a debuggee

  • hostName - The host name or ip address of the debuggee you want to attach.
  • port - The port of the debuggee you want to attach.

Before attaching to a debuggee, your debuggee program must be started with debug mode. The standard command line for debug mode is like java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -cp bin MyApp, and then the debug port of your debuggee is 5005.

{
    "type": "java",
    "name": "Debug (Attach)",
    "request": "attach",
    "hostName": "localhost",
    "port": 5005
}

In some cases, you may want to start your program with the external builder and launcher, then you can configure these jobs in tasks.json and attach to it. For example, launching springboot application via mvn command, and then attach a debugger.

Attach to mvn task

  1. Configure your command in .vscode/tasks.json - The mvn task is a background task, you should use problemMatcher filter to tell VS Code it's ready.
     {
         "label": "mvnDebug",
         "type": "shell",
         "command": "mvn spring-boot:run -Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005\"",
         "isBackground": true,
         "problemMatcher": [{
             "pattern": [{
                 "regexp": "\\b\\B",
                 "file": 1,
                 "location": 2,
                 "message": 3
             }],
             "background": {
                 "activeOnStart": true,
                 "beginsPattern": "^.*Attaching agents:.*",
                 "endsPattern": "^.*Listening for transport dt_socket at address.*"
             }
         }]
     }
  2. Configure preLaunchTask and the debug port in .vscode/launch.json.
    {
        "type": "java",
        "name": "Debug (Attach)",
        "request": "attach",
        "hostName": "localhost",
        "port": 5005,
        "preLaunchTask": "mvnDebug"
    }
  3. F5 will launch the mvn task, and attach the debugger. See the demo.
    attachToMvn

Attach to embedded maven tomcat server

  • pom.xml sample for embedded tomcat server.
  ...
  <plugin>
      <groupId>org.apache.tomcat.maven</groupId>
      <artifactId>tomcat7-maven-plugin</artifactId>
      <version>2.2</version>
  </plugin>
  ...
  • The steps to attach to the embedded maven tomcat server.
  1. Use .vscode/tasks.json to configure run-tomcat and stop-tomcat tasks.
  {
      "version": "2.0.0",
      "tasks": [
          {
              "label": "run-tomcat",
              "type": "shell",
              "command": "MAVEN_OPTS=\"$MAVEN_OPTS -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n\" ./mvnw tomcat7:run",
              "group": "build",
              "isBackground": true,
              "problemMatcher": [{
                  "pattern": [{
                      "regexp": "\\b\\B",
                      "file": 1,
                      "location": 2,
                      "message": 3
                  }],
                  "background": {
                      "activeOnStart": true,
                      "beginsPattern": "^.*Listening for",
                      "endsPattern": "^.*transport dt_socket at address.*"
                  }
              }]
          },
          {
              "label": "stop-tomcat",
              "type": "shell",
              "command": "echo ${input:terminate}}",
              "problemMatcher": []
          }
      ],
      "inputs": [
          {
              "id": "terminate",
              "type": "command",
              "command": "workbench.action.tasks.terminate",
              "args": "run-tomcat"
          }
      ]
  }
  1. Use .vscode/launch.json to configure the attach configuration. Use preLaunchTask to run tomcat before the attach, and postDebugTask to stop tomcat after the debug ends.
  {
      "version": "0.2.0",
      "configurations": [
          {
              "type": "java",
              "name": "Debug (Attach)",
              "request": "attach",
              "hostName": "localhost",
              "port": 5005,
              "preLaunchTask": "run-tomcat",
              "postDebugTask": "stop-tomcat"
          }
      ]
  }
  1. F5 will auto start the tomcat server and attach the debugger. The demo below will show how to debug spring mvc in tomcat.
    attachToEmbeddedTomcat

If you want to try to debug your Java webapps in a standalone tomcat server, please try VS Code Tomcat for Java extension.

If you want to try to debug embedded tomcat server with gradle plugin, see the gradle sample.

Use javac as the builder and attach to java process

  1. Configure the javac builder and java runner jobs in .vscode/tasks.json.
    {
        "version": "2.0.0",
        "tasks": [
            {
                "label": "build",
                "type": "shell",
                "command": "javac -g -sourcepath ./**/*.java -d ./bin"
            },
            {
                "label": "debug",
                "dependsOn": "build",
                "type": "shell",
                "command": "java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005 -cp bin app.SimpleCalc",
                "isBackground": true,
                "problemMatcher": [{
                    "pattern": [{
                        "regexp": "\\b\\B",
                        "file": 1,
                        "location": 2,
                        "message": 3
                    }],
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": "^.*Listening for",
                        "endsPattern": "^.*transport dt_socket at address.*"
                    }
                }]
            }
        ]
    }
  2. Configure preLaunchTask and the debug port in .vscode/launch.json.
    {
        "version": "0.2.0",
        "configurations": [
            {
                "type": "java",
                "name": "Debug (Attach)",
                "request": "attach",
                "hostName": "localhost",
                "port": 5005,
                "preLaunchTask": "debug"
            }
        ]
    }
  3. F5 will run the tasks and attach the debugger. See the demo.
    attachToJava

Modify the settings.json (User Setting)

  • java.debug.settings.console - The specified console to launch Java program, defaults to integratedTerminal. If you want to customize the console for a specific debug session, please use console option in launch.json instead. terminal

  • java.debug.settings.forceBuildBeforeLaunch - Force building the workspace before launching java program, defaults to true. Sometimes you may be bothered with the message "Build failed, do you want to continue?", you could disable this setting to suppress the message.

  • java.debug.settings.onBuildFailureProceed - Sometimes you may be bothered with the message "Build failed, do you want to continue?", you could use this setting to suppress the message and proceed.

  • java.debug.settings.hotCodeReplace - Reload the changed Java classes during debugging, defaults to manual. It supports manual, auto, never.

    • manual - Click the toolbar to apply the changes.
      hcr
    • auto - Automatically apply the changes after saved.
    • never - Never apply the changes.
  • java.debug.settings.enableRunDebugCodeLens - Enable the code lens provider for the Run and Debug buttons over main entry points, defaults to true.

    • true - Show the code lens.
      codelens
    • false - Show the Run/Debug link in the hover.
      hover

FAQ

1. No way to take input.

If you are using Scanner(System.in) to get the user input, you need change the user setting java.debug.settings.console to integratedTerminal or externalTerminal.

2. Code output is not in the DEBUG CONSOLE panel but Terminal.

By default, the debugger uses the terminal to launch your program for better accepting user input. And you will see the original command line is displayed at the top of the terminal. If you want a cleaner console to show your code output, you could try to change the user setting java.debug.settings.console to internalConsole. Please notice that the internal console (VS Code built-in DEBUG CONSOLE) doesn't support user input.

3. The classpath changed when using terminal.

In order to avoid the command line being too long, the debugger will shorten your classpath into classpath.jar (for JDK 8 only) or argsfile (for JDK 9 and above) by default. If your program need read the original classpath value (for example, System.getProperty("java.class.path")), you could try to change the console to internalConsole, or use a higher JDK (9 and above) to launch your program.

4. Failed to launch debuggee in terminal with TransportTimeoutException.

When launching failed in terminal, then you could try to change the user setting java.debug.settings.console to internalConsole.