运行和调试 Java
Visual Studio Code 允许你通过 Debugger for Java 扩展来调试 Java 应用程序。它是一个基于 Java Debug Server 的轻量级 Java 调试器,它扩展了 Language Support for Java™ by Red Hat。
以下是支持的调试功能列表
- 启动/附加
- 断点
- 异常
- 暂停和继续
- 单步进入/跳出/单步跳过
- 变量
- 调用堆栈
- 线程
- 调试控制台
- 评估
- 热代码替换
Java 调试器是一个开源项目,欢迎贡献者通过 GitHub 仓库进行协作
如果您在使用以下功能时遇到任何问题,可以通过提交问题联系我们。
安装
要在 Visual Studio Code 中获得完整的 Java 语言支持,你可以安装 Extension Pack for Java,其中包括 Debugger for Java 扩展。
有关如何开始使用扩展包的详细信息,可以查看 Java 入门教程。
配置
默认情况下,调试器会自动查找主类并在内存中生成默认的启动配置来启动你的应用程序,从而实现开箱即用。
如果你想自定义并保存你的启动配置,你可以在**运行和调试**视图中选择**创建 launch.json 文件**链接。
launch.json
文件位于工作区(项目根文件夹)的 .vscode
文件夹中。
有关如何创建 launch.json
的更多详细信息,请阅读启动配置;有关 Java 配置选项的更多详细信息,可以阅读配置选项。
运行和调试
调试器扩展提供了多种方式来运行和调试你的 Java 应用程序。
从 CodeLens 运行
你将在 main()
函数的 CodeLens 上找到**运行|调试**。
从编辑器菜单运行
另一种开始调试的方法是从顶部编辑器标题栏中选择**运行 Java**或**调试 Java**菜单。
按 F5 运行
按 F5,调试器将自动找到项目的入口点并开始调试。你还可以从 VS Code 侧边栏的**运行和调试**视图开始调试会话。更多信息请参见 在 VS Code 中调试。
调试单个文件
除了支持调试由构建工具管理的 Java 项目外,VS Code 还支持在没有任何项目的情况下调试单个 Java 文件。
调试会话输入
VS Code 中的默认调试控制台不支持输入。如果你的程序需要从终端输入,你可以使用 VS Code 内的集成终端 (⌃` (Windows, Linux Ctrl+`)) 或外部终端来启动它。你还可以使用用户设置 java.debug.settings.console
为所有 Java 调试会话配置一个全局控制台。
断点
Debugger for Java 支持各种断点,如行断点、条件断点、数据断点和日志点。
断点 - 条件断点
借助表达式求值,调试器还支持条件断点。你可以设置断点在表达式求值为 true 时中断。
断点 - 数据断点
你可以让调试器在变量值改变时中断。请注意,数据断点只能在调试会话中设置。这意味着你需要先启动你的应用程序并在一个常规断点上中断。然后你可以在**变量**视图中选择一个字段并设置数据断点。
断点 - 日志点
Java 调试器也支持日志点。日志点允许你在不编辑代码的情况下向调试控制台发送输出。它们与断点不同,因为它们不会停止应用程序的执行流程。
断点 - 触发断点
触发断点是一种在另一个断点命中后自动启用的断点。当代码中出现仅在特定先决条件发生后才出现的故障情况时,它们非常有用。
可以通过右键单击字形边距,选择 添加触发断点,然后选择哪个其他断点启用此断点来设置触发断点。
表达式求值
调试器还允许你在**监视**窗口和调试控制台中对表达式进行求值。
热代码替换
调试器支持的另一个高级功能是“热代码”替换。热代码替换(HCR)是一种调试技术,Debugger for Java 通过调试通道将类更改传输到另一个 Java 虚拟机(JVM)。HCR 促进了实验性开发和迭代试错编码。有了这个新功能,你可以启动一个调试会话并在你的开发环境中更改一个 Java 文件,调试器将在正在运行的 JVM 中替换代码。不需要重新启动,这就是为什么它被称为“热”。下面是关于如何在 VS Code 中使用 Debugger for Java 的 HCR 功能的图示。
你可以使用调试设置 java.debug.settings.hotCodeReplace
来控制如何触发热代码替换。可能的设置值为
manual
- 单击工具栏以应用更改(默认)。auto
- 编译后自动应用更改。never
- 禁用热代码替换。
单步筛选
该扩展支持单步筛选,以筛选出你在调试时不希望看到或单步执行的类型。通过此功能,你可以在 launch.json
中配置要筛选的包,以便在单步执行时可以跳过它们。
配置选项
有许多选项和设置可用于配置调试器。例如,使用启动选项可以轻松配置 JVM 参数和环境变量。
请查阅 Language Support for Java™ by Red Hat 扩展的文档以获取有关设置项目的帮助。
对于许多常用设置,VS Code Java 调试器配置中提供了示例。该文档解释了 Java 调试器如何为你自动生成配置,以及如果需要修改它们,如何通过主类、不同的参数、环境、附加到其他 Java 进程以及使用更高级的功能来做到这一点。
以下是可用于 Launch
和 Attach
的所有配置。有关如何编写 launch.json
文件的更多信息,请参阅调试。
启动
mainClass
(必需) - 程序的完全限定类名(例如 [java 模块名/]com.xyz.MainApp)或 Java 文件路径。args
- 传递给程序的命令行参数。使用"${command:SpecifyProgramArgs}"
来提示输入程序参数。它接受一个字符串或一个字符串数组。sourcePaths
- 程序的额外源目录。调试器默认从项目设置中查找源代码。此选项允许调试器在额外的目录中查找源代码。modulePaths
- 用于启动 JVM 的模块路径。如果未指定,调试器将从当前项目自动解析。$Auto
- 自动解析当前项目的模块路径。$Runtime
- 当前项目“runtime”范围内的模块路径。$Test
- 当前项目“test”范围内的模块路径。!/path/to/exclude
- 从模块路径中排除指定的路径。/path/to/append
- 将指定的路径附加到模块路径。
classPaths
- 用于启动 JVM 的类路径。如果未指定,调试器将从当前项目自动解析。$Auto
- 自动解析当前项目的类路径。$Runtime
- 当前项目“runtime”范围内的类路径。$Test
- 当前项目“test”范围内的类路径。!/path/to/exclude
- 从类路径中排除指定的路径。/path/to/append
- 将指定的路径附加到类路径。
encoding
- JVM 的file.encoding
设置。如果未指定,将使用“UTF-8”。可能的值可以在支持的编码中找到。vmArgs
- JVM 的额外选项和系统属性(例如 -Xms<size> -Xmx<size> -D<name>=<value>),它接受一个字符串或一个字符串数组。projectName
- 调试器搜索类的首选项目。在不同的项目中可能存在重复的类名。此设置在调试器启动程序时查找指定的主类时也有效。当工作区有多个 Java 项目时,此项是必需的,否则表达式求值和条件断点可能无法工作。cwd
- 程序的工作目录。默认为${workspaceFolder}
。env
- 程序的额外环境变量。envFile
- 包含环境变量定义文件的绝对路径。stopOnEntry
- 启动后自动暂停程序。console
- 启动程序的指定控制台。如果未指定,则使用java.debug.settings.console
用户设置指定的控制台。internalConsole
- VS Code 调试控制台(不支持输入流)。integratedTerminal
- VS Code 集成终端。externalTerminal
- 可以在用户设置中配置的外部终端。
shortenCommandLine
- 当项目具有长类路径或大的 VM 参数时,启动程序的命令行可能会超过操作系统允许的最大命令行字符串限制。此配置项提供了多种方法来缩短命令行。默认为auto
。none
- 使用标准命令行 'java {options} classname {args}' 启动程序。jarmanifest
- 将类路径参数生成到一个临时的 classpath.jar 文件,并使用命令行 'java -cp classpath.jar classname {args}' 启动程序。argfile
- 将类路径参数生成到一个临时参数文件,并使用命令行 'java @argfile {args}' 启动程序。此值仅适用于 Java 9 及更高版本。auto
- 自动检测命令行长度,并确定是否通过适当的方法缩短命令行。
stepFilters
- 在单步执行时跳过指定的类或方法。classNameFilters
- [已弃用 - 由skipClasses
取代] 在单步执行时跳过指定的类。类名应为完全限定名。支持通配符。skipClasses
- 在单步执行时跳过指定的类。你可以使用内置变量如“$JDK”和“$Libraries”来跳过一组类,或添加特定的类名表达式,例如java.*
,*.Foo
。skipSynthetics
- 单步执行时跳过合成方法。skipStaticInitializers
- 单步执行时跳过静态初始化方法。skipConstructors
- 单步执行时跳过构造函数方法。
附加
hostName
(必需) - 远程被调试程序的主机名或 IP 地址。port
(必需) - 远程被调试程序的调试端口。processId
- 使用进程选择器选择要附加的进程,或使用整数形式的进程 ID。${command:PickJavaProcess}
- 使用进程选择器选择要附加的进程。- 一个整数 PID - 附加到指定的本地进程。
timeout
- 重新连接前的超时值,单位为毫秒(默认为 30000 毫秒)。sourcePaths
- 程序的额外源目录。调试器默认从项目设置中查找源代码。此选项允许调试器在额外的目录中查找源代码。projectName
- 调试器搜索类的首选项目。在不同的项目中可能存在重复的类名。当工作区有多个 Java 项目时,此项是必需的,否则表达式求值和条件断点可能无法工作。stepFilters
- 在单步执行时跳过指定的类或方法。classNameFilters
- [已弃用 - 由skipClasses
取代] 在单步执行时跳过指定的类。类名应为完全限定名。支持通配符。skipClasses
- 在单步执行时跳过指定的类。你可以使用内置变量如“$JDK”和“$Libraries”来跳过一组类,或添加特定的类名表达式,例如java.*
,*.Foo
。skipSynthetics
- 单步执行时跳过合成方法。skipStaticInitializers
- 单步执行时跳过静态初始化方法。skipConstructors
- 单步执行时跳过构造函数方法。
用户设置
java.debug.logLevel
: 发送到 VS Code 的调试器日志的最低级别,默认为warn
。java.debug.settings.showHex
: 在**变量**中以十六进制格式显示数字,默认为false
。java.debug.settings.showStaticVariables
: 在**变量**中显示静态变量,默认为false
。java.debug.settings.showQualifiedNames
: 在**变量**中显示完全限定的类名,默认为false
。java.debug.settings.showLogicalStructure
: 在**变量**中显示 Collection 和 Map 类的逻辑结构,默认为true
。java.debug.settings.showToString
: 在**变量**中为所有重写了 'toString' 方法的类显示 'toString()' 值,默认为true
。java.debug.settings.maxStringLength
: 在**变量**或**调试控制台**中显示字符串的最大长度。超过此限制的字符串将被截断。默认值为0
,表示不进行截断。java.debug.settings.hotCodeReplace
: 在调试期间重新加载已更改的 Java 类,默认为manual
。请确保 Java Language Support 扩展的java.autobuild.enabled
未被禁用。有关用法和限制的更多信息,请参阅热代码替换维基页面。- manual - 单击工具栏应用更改。
- auto - 编译后自动应用更改。
- never - 从不应用更改。
java.debug.settings.enableHotCodeReplace
: 启用 Java 代码的热代码替换。请确保 VS Code Java 的自动构建未被禁用。有关用法和限制的更多信息,请参阅热代码替换维基页面。java.debug.settings.enableRunDebugCodeLens
: 在主入口点上为运行和调试按钮启用 CodeLens 提供程序,默认为true
。java.debug.settings.forceBuildBeforeLaunch
: 在启动 Java 程序前强制构建工作区,默认为true
。java.debug.settings.console
: 用于启动 Java 程序的指定控制台,默认为integratedTerminal
。如果你想为特定的调试会话自定义控制台,请修改launch.json
中的console
配置。internalConsole
- VS Code 调试控制台(不支持输入流)。integratedTerminal
- VS Code 集成终端。externalTerminal
- 可以在用户设置中配置的外部终端。
java.debug.settings.exceptionBreakpoint.skipClasses
: 在异常处中断时跳过指定的类。你可以使用内置变量如“$JDK”和“$Libraries”来跳过一组类,或添加特定的类名表达式,例如java.*
,*.Foo
。java.debug.settings.stepping.skipClasses
: 在单步执行时跳过指定的类。你可以使用内置变量如“$JDK”和“$Libraries”来跳过一组类,或添加特定的类名表达式,例如java.*
,*.Foo
。java.debug.settings.stepping.skipSynthetics
: 单步执行时跳过合成方法。java.debug.settings.stepping.skipStaticInitializers
: 单步执行时跳过静态初始化方法。java.debug.settings.stepping.skipConstructors
: 单步执行时跳过构造函数方法。java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest
: 一次 JDWP 请求中可以请求的最大变量或字段数。值越高,在展开变量视图时请求被调试程序的频率越低。同时,大的数值也可能导致 JDWP 请求超时。默认为 100。java.debug.settings.jdwp.requestTimeout
: 当调试器与目标 JVM 通信时,JDWP 请求的超时时间(毫秒)。默认为 3000。java.debug.settings.vmArgs
: 启动 Java 程序的默认 VM 参数。例如,使用 '-Xmx1G -ea' 将堆大小增加到 1GB 并启用断言。如果你想为特定的调试会话自定义 VM 参数,可以修改launch.json
中的 'vmArgs' 配置。java.silentNotification
: 控制是否可以使用通知来报告进度。如果为 true,则改用状态栏报告进度。默认为false
。
故障排除
如果你在使用调试器时遇到问题,可以在 vscode-java-debug GitHub 仓库中找到详细的故障排除指南。
解释的常见问题包括
- Java 语言支持扩展启动失败。
- 构建失败,是否要继续?
- *.java 不在类路径上。只会报告语法错误。
- 程序错误:无法找到或加载主类 X。
- 程序抛出 ClassNotFoundException。
- 热代码替换失败。
- 请在 launch.json 中指定远程被调试程序的主机名和端口。
- 求值失败。原因:无法求值,因为线程已恢复。
- 找不到带有 main 方法的类。
- 启动调试器时,没有 vscode.java.startDebugSession 的 delegateCommandHandler。
- 无法解析类路径。
- 不支持请求类型 "X"。仅支持 "launch" 和 "attach"。
反馈和问题
你可以在 vscode-java-debug 仓库中找到完整的问题列表。你可以提交一个错误或功能建议,并参与社区驱动的 vscode-java-debug Gitter 频道。
后续步骤
继续阅读以了解:
- 调试 - 了解如何在 VS Code 中为任何语言的项目使用调试器。
以及关于 Java 的