Debugger for Java 全配置属性盘点

VSCode 生态中,由 Microsoft 出品的 Debugger for Java 扩展是 Java 开发者日常调试的核心工具。它基于 Java Debug Server 与 Eclipse JDT 配合,通过 DAP(Debug Adapter Protocol)将完整的 Java 调试能力接入 VSCode,支持启动调试、附加调试、断点、异常断点、热替换、表达式求值、步骤过滤等丰富特性。该扩展的配置体系由两部分组成:一是写入 launch.json 的调试会话级配置,二是写入 settings.json 的全局用户设置。

本文基于 vscode-java-debug-main 项目与 java-debug-main 项目的源码,按扩展激活、启动调试、附加调试、调试会话运行、配置热更新五大主流程逐一盘点全部可配置属性,并描述各属性在流程中的行为逻辑,帮助开发者精准驾驭每一个配置项。

配置属性总览

Debugger for Java 的全部配置属性分布在两个位置:扩展 package.jsoncontributes.configuration 节点定义了用户级设置(java.debug.settings.*java.silentNotification),共 27 项;contributes.debuggers[0].configurationAttributes 节点定义了 launch.jsonlaunchattach 两种请求类型的会话级配置。下文按流程顺序逐一列出全部属性,包括属性名、类型、默认值及功能说明。

用户设置全量列表

属性名 类型 默认值 说明
java.debug.logLevel enum: error, warn, info, verbose warn 调试器发送到 VSCode 的最低日志级别
java.silentNotification boolean false 是否使用状态栏而非通知来报告进度
java.debug.settings.showHex boolean false 变量视图中是否以十六进制显示数值
java.debug.settings.showStaticVariables boolean false 变量视图中是否显示静态变量
java.debug.settings.showQualifiedNames boolean false 变量视图中是否显示类全限定名
java.debug.settings.showLogicalStructure boolean true 变量视图中是否显示 CollectionMap 的逻辑结构
java.debug.settings.showToString boolean true 变量视图中是否显示重写 toString 方法的类的 toString()
java.debug.settings.maxStringLength number 0 变量视图或调试控制台中字符串的最大显示长度,0 表示不截断
java.debug.settings.numericPrecision number 0 格式化 double 时的精度,0 表示默认精度
java.debug.settings.hotCodeReplace enum: auto, manual, never manual 调试期间重新加载已更改 Java 类的方式
java.debug.settings.enableRunDebugCodeLens boolean true 是否在 main 方法上启用 RunDebug CodeLens
java.debug.settings.forceBuildBeforeLaunch boolean true 启动 Java 程序前是否强制编译工作空间
java.debug.settings.onBuildFailureProceed boolean false 构建失败时是否直接继续启动
java.debug.settings.console enum: internalConsole, integratedTerminal, externalTerminal integratedTerminal 启动 Java 程序的默认控制台
java.debug.settings.vmArgs string "" 启动 Java 程序的默认 VM 参数
java.debug.settings.exceptionBreakpoint.exceptionTypes array [] 要中断的异常类型列表
java.debug.settings.exceptionBreakpoint.allowClasses array [] 允许异常断点中断的类位置,支持通配符
java.debug.settings.exceptionBreakpoint.skipClasses array [] 异常断点触发时跳过的类,支持内置变量与通配符
java.debug.settings.stepping.skipClasses array [] 步骤时跳过的类,支持内置变量与通配符
java.debug.settings.stepping.skipSynthetics boolean false 步骤时是否跳过合成方法
java.debug.settings.stepping.skipStaticInitializers boolean false 步骤时是否跳过静态初始化方法
java.debug.settings.stepping.skipConstructors boolean false 步骤时是否跳过构造函数
java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest number 100 单次 JDWP 请求可请求的变量或字段最大数量,最小值 1
java.debug.settings.jdwp.requestTimeout number 3000 JDWP 请求超时时间(毫秒),最小值 100
java.debug.settings.jdwp.async enum: auto, on, off auto 是否允许调试器异步发送 JDWP 命令
java.debug.settings.debugSupportOnDecompiledSource enum: on, off on 是否在反编译源码上启用调试支持
java.debug.settings.suspendAllThreads boolean false 命中断点或异常停止时是否暂停所有线程,仅对新会话生效

launch.json 配置全量列表

属性名 类型 默认值 适用请求 说明
mainClass string "" launch 程序入口主类全限定名、模块名前缀形式或 Java 文件路径,必填
projectName string "" launch/attach 调试器搜索类时的首选工程名,表达式求值依赖此配置
javaExec string "" launch 启动程序使用的 java 可执行文件路径
args array | string "" launch 传递给程序的命令行参数
vmArgs array | string "" launch JVM 启动参数与系统属性
modulePaths array [] launch 模块路径,支持 $Auto$Runtime$Test!<path>
classPaths array [] launch 类路径,支持 $Auto$Runtime$Test!<path>
sourcePaths array [] launch/attach 额外的源码目录
encoding string UTF-8 launch JVM 的 file.encoding 设置
cwd string ${workspaceFolder} launch 程序的工作目录
env object {} launch 程序的环境变量
envFile array | string ${workspaceFolder}/.env launch 环境变量定义文件路径
stopOnEntry boolean true launch 启动后是否自动暂停程序
console enum: internalConsole, integratedTerminal, externalTerminal integratedTerminal launch 启动程序使用的控制台类型
shortenCommandLine enum: none, jarmanifest, argfile, auto auto launch 命令行过长时的缩短策略
stepFilters object 见子属性 launch/attach 步骤跳过的类或方法过滤器
hostName string localhost attach 远程调试进程的主机名或 IP 地址
port number | string - attach 远程调试进程的调试端口
processId enum: ${command:PickJavaProcess} | integer - attach 本地进程 ID 或进程选择器
timeout number 30000 attach 重新连接前的超时时间(毫秒)

stepFilters 子属性与类路径变量

子属性名 类型 默认值 说明
skipClasses array ["$JDK", "junit.*"] 步骤时跳过的类,支持内置变量与通配符
skipSynthetics boolean false 是否跳过合成方法
skipStaticInitializers boolean false 是否跳过静态初始化方法
skipConstructors boolean false 是否跳过构造函数
变量 含义
$Auto 自动从当前工程解析对应作用域路径
$Runtime 当前工程 runtime 作用域路径
$Test 当前工程 test 作用域路径
!<path> 从解析结果中排除指定路径

扩展激活与运行入口准备流程

扩展在用户打开 Java 文件、初始化调试配置、执行 SpecifyProgramArgsPickJavaProcess 命令等事件触发时激活。激活后首先获取 Java 语言服务器 API,由于调试功能依赖语言服务器处于标准模式,若检测到当前处于轻量模式,会弹出对话框询问是否切换到标准模式;若处于混合模式,则订阅模式变更事件,等待标准服务器就绪后继续,等待期间进度报告器会显示导入项目的提示。

语言服务器就绪后,扩展根据 java.debug.settings.enableRunDebugCodeLens 决定 main 方法的运行入口形式:若为 true,则在 main 方法上方注册 CodeLens,显示 RunDebug 两个可点击按钮;若为 false,则改为注册悬停提示,仅在鼠标悬停于 main 方法时显示运行入口链接。该配置在调试会话期间变更时,扩展会动态销毁旧的提供者并注册新的提供者,无需重启 VSCode 即可生效。

扩展在构建、启动、附加等耗时操作期间会通过进度报告器显示进度。java.silentNotification 影响所有进度报告器的显示位置:若为 true,则原本显示在通知位置的进度会降级到窗口状态栏左侧,显示一个带旋转图标和任务名的状态栏项,点击可跳转到 Java 构建状态详情;若为 false,则使用 VSCode 原生的通知进度条。该配置在每次创建新的进度报告器时都会重新读取,因此运行时变更可立即对后续操作生效。

java.debug.settings.hotCodeReplace 在扩展启动时初始化热代码替换功能。该配置会被映射为一个上下文键,与调试工具栏菜单的可见性条件配合,决定热替换按钮是否显示。仅当值为 manual 且当前处于调试模式(非运行模式)时按钮才会显示;值为 auto 时按钮不显示但会自动应用类变更;值为 never 时按钮完全不显示且不处理类变更。扩展还会监听调试会话的启动与切换事件,动态更新该上下文键,确保运行模式下不显示热替换按钮。

启动调试流程

当用户通过 F5、CodeLens、右键菜单或 launch.json 触发调试时,VSCode 会依次调用配置提供器的两个解析方法。第一个方法负责在缺少配置时生成内存中的默认配置:若传入的配置是空对象(仅包含是否运行模式的字段),则生成一个临时配置,类型设为 java,名称设为 Java Debug,请求类型设为 launch,并标记为调试器内部生成。第二个方法是请求处理的核心,首先合并平台特定配置节,然后根据 request 字段进入 launchattach 两个分支:launch 分支按严格顺序执行主类校验、构建、参数合并、类路径解析、命令行缩短决策、程序启动等子流程;attach 分支与 launch 分支有部分子流程相同,差异在下一节说明。本节先讲 launch 分支的完整子流程,各子流程以段落形式依次说明。

请求处理开始时首先合并平台特定的配置节,这一子流程对 launchattach 两个分支都会执行。launch.json 中可以针对 windowslinuxosx 分别配置不同的属性,流程会根据当前操作系统选择对应的平台节,将其所有键值覆盖到全局配置对象中,然后清除平台节字段。这一设计简化了后续解析逻辑,无需再关心平台差异。

主类解析是启动流程中最复杂的环节。若 mainClass 已显式配置且不是文件路径,则向语言服务器校验主类与 projectName 的有效性:校验返回主类与项目名各自的合法性标志,若任一不合法且存在修复建议,会弹出错误对话框提供 Fix 按钮,点击后展示候选项供用户选择,选中的主类与项目名会被持久化回 launch.json;若无修复建议,则抛出用户错误终止流程。若 mainClass 为空或为文件路径,则尝试将其作为文件路径解析主方法:若该文件无可执行主方法,则回退到最近使用的启动配置(扩展会在每次成功启动后记录最近使用的主类、项目名与工作区文件夹);若仍无可用配置,则向用户展示主类选择列表。这一机制使得用户在当前编辑的 Java 文件没有 main 方法时,也能智能回退到上次启动的配置。

主类解析完成后,若 java.debug.settings.forceBuildBeforeLaunchtrue,则触发工作空间构建。构建委托给语言服务器执行,返回状态分为成功、失败、有错误、已取消、Gradle 构建服务编译错误五种。若返回已取消或进度报告器被取消,则终止启动;若返回成功则继续;其他状态进入构建失败处理流程。失败处理的行为由 java.debug.settings.onBuildFailureProceed 决定:若为 true,直接继续启动,不弹任何对话框;若为 false,则先扫描所有打开文件的诊断信息统计 Java 错误的类型与数量,若检测到错误且构建状态不是 Gradle 构建服务编译错误,则自动打开 PROBLEMS 面板(因为 Gradle 构建服务项目的错误不会出现在 PROBLEMS 中)。随后弹出错误对话框,提供三个选项:Continue 仅本次继续,Always Continue 永久继续并自动将 onBuildFailureProceed 写入为 trueFix... 弹出修复建议菜单,包含清理工作区缓存、更新项目配置、打开日志文件、查看故障排除指南四项。为避免构建过快导致用户看不到"编译中"提示,若构建耗时小于 150 毫秒,会额外延迟 150 毫秒再处理结果。

构建通过后进入环境变量合并阶段。流程以 env 配置为基础,若 envFile 为字符串则解析该文件并合并,若为数组则遍历所有文件依次合并。文件解析使用 dotenv 库,并会自动剥离文件开头的 BOM 头。若文件不存在或解析失败,抛出用户错误提示无法加载环境文件。最终合并结果写回 env 字段。

VM 参数合并时,launch.json 中的 vmArgs 优先级高于 java.debug.settings.vmArgs。流程检测 vmArgs 是否严格等于 undefined(而非空字符串),若为 undefined 则回退到全局设置的 vmArgs,这意味着用户在 launch.json 中将 vmArgs 显式设为空字符串时不会回退到全局设置。vmArgsargs 都支持字符串与字符串数组两种形式,若为数组则拼接为字符串,拼接时对包含空格或双引号的参数进行转义并用双引号包裹。流程还会自动追加两类有益的 VM 参数:若语言服务器检测到项目启用了预览特性,则自动追加 --enable-preview,并校验目标运行时版本兼容性;若目标 JVM 版本大于等于 14,则自动追加 -XX:+ShowCodeDetailsInExceptionMessages(JEP-358,提供详细的空指针异常信息),但若用户已在 vmArgs 中包含此参数则不重复追加。

控制台选择的优先级为 launch.jsonconsole 大于 java.debug.settings.console 大于默认值 integratedTerminal。流程检测 console 是否为 falsy 值(包括空字符串),若为 falsy 则回退到全局设置。控制台选定后还有两项联动:若为 integratedTerminal 且未显式配置调试控制台选项,则自动设为不自动打开,避免调试启动时焦点被切换到调试控制台;若为 internalConsole 且未显式配置 encoding,则自动将 encoding 设为 UTF-8,因为 VSCode 调试控制台默认使用 UTF-8 显示输出。

类路径解析分两种情况:若 classPathsmodulePaths 均为空,则让语言服务器自动解析,返回的模块路径与类路径分别赋值给对应字段;若任一非空,则对每个非空数组进行变量替换与排除处理。变量替换处理 $Auto$Runtime$Test 三种变量:若包含 $Test 则作用域为测试,若包含 $Auto 则作用域为自动,若仅包含 $Runtime 则作用域为运行时,然后向语言服务器请求该作用域的路径并替换变量位置,替换仅发生一次以避免重复。!<path> 排除项会被收集起来,区分文件与目录两种排除方式:文件采用精确匹配,目录采用前缀匹配,最终从结果中过滤掉被排除的路径。若路径非绝对路径,会拼接工作区文件夹路径后再规范化。若最终类路径与模块路径均为空,则抛出用户错误提示用户在 launch.json 中手动指定。

Java 可执行文件与工作目录处理阶段:若 javaExec 为空,则让语言服务器根据项目 JDK 解析 java 可执行文件路径;若非空,则校验文件是否存在,不存在则抛出用户错误。cwd 若未配置则回退到工作区文件夹路径。argsvmArgs 若为数组则拼接为字符串。此阶段还会填充 stepFilters,该子流程对 launchattach 两个分支都会执行:若该字段不存在则直接跳过;若存在,则对其中的 skipClasses 进行变量替换,仅当包含 $JDK$Libraries 时才向语言服务器请求展开为具体的类名列表,否则直接透传。该步骤还兼容旧版的 classNameFilters 字段,将其合并到 skipClasses 后清除,实现平滑迁移。

命令行缩短决策阶段:若 shortenCommandLine 未配置或为 auto,则自动决策。决策分两步:首先根据目标 JVM 版本选择推荐方案,JDK 8 及以下推荐 jarmanifest(生成临时 classpath.jar),JDK 9 及以上推荐 argfile(生成临时 @argfile);然后判断是否真的需要缩短。是否需要缩短因控制台类型而异:对于 internalConsole,需要向语言服务器查询实际命令行长度,再与各平台的最大命令行长度阈值比较,Windows 约为 30000 字符,macOS 约为 260000 字符减去环境长度,Linux 约为 2097000 字符减去环境长度,同时还要校验单个类路径长度是否超过 Linux 的参数最大长度限制;对于终端类控制台(integratedTerminalexternalTerminal),只要类路径或模块路径条目数大于 1 就启用缩短,因为终端启动命令本身的长度限制更严格。环境长度计算会遍历 env 中所有键值对,累加键长度、值长度与分隔符长度。若所有检测均不需要缩短,则使用标准命令行启动。

流程最后清理内部临时字段并返回最终配置。若配置来源为内部生成或 launch.json,且主类解析成功,则将配置的副本保存为最近使用的启动配置,记录主类、项目名与工作区文件夹,供下次启动时智能回退使用。随后调试适配器使用 javaExec 解析出的 java 路径执行程序,按 console 类型选择启动方式:integratedTerminal 在集成终端中启动并支持标准输入交互,externalTerminal 在外部终端窗口中启动,internalConsole 在调试控制台中启动但不支持标准输入。程序启动后若 stopOnEntrytrue,则立即在主方法入口处暂停。

附加调试流程

附加调试流程进入 requestattach 的分支。该分支与 launch 分支共享平台属性合并与步骤过滤器填充两个子流程,处理逻辑完全一致,此处不再重复。本节仅说明 attach 分支特有的部分。attach 支持两种附加方式:通过 hostNameport 直连远程调试端口,或通过 processId 附加到本地 Java 进程。

hostNameport 同时存在且 port 为合法整数,则进入直连模式。流程会将 port 转换为数字类型,并清除 processId 字段避免后续混淆。这一模式适用于已知远程调试端口的场景,如远程服务器、Docker 容器、嵌入式设备等。

processId 已配置,则进入进程选择模式。首先检测 processId 是否为 ${command:PickJavaProcess},若是则终止本次解析,交由 VSCode 的进程选择器命令处理,用户在弹出的列表中选择目标 Java 进程后会再次触发解析;若为数字则查询该进程的调试端口信息,若查询不到或该进程未启用调试模式,则弹出错误提示并终止。查询成功后清除 processId,将 hostName 设为 localhostport 设为查询到的调试端口。若 hostNameportprocessId 均未配置,则抛出用户错误提示用户在 launch.json 中指定。

timeout 控制附加连接的超时时间,默认 30000 毫秒。在附加调试的实际执行阶段,调试适配器会发送一个测试 JDWP 请求测量网络延迟,并将延迟值存储到调试上下文中。该延迟值会记录到日志中,并作为 java.debug.settings.jdwp.asyncauto 模式决策依据。

调试会话运行流程

调试会话启动后,配置属性的影响从启动阶段转入运行阶段。这一阶段的属性主要影响断点、步骤、变量查看、热替换等运行时行为,且大部分支持热更新,无需重启会话即可生效。

java.debug.settings.suspendAllThreads 是一个具有会话级固化特性的配置。调试会话在创建时会读取该配置并固化存储,此后整个调试会话期间不再读取该配置,这意味着运行时修改该配置不会影响当前会话,仅对下一次启动的调试会话生效。该值会传递给所有断点、观察点、异常断点的暂停策略:当值为 true 时,命中断点或异常时暂停所有线程;当为 false 时仅暂停触发事件的线程。由于该值在会话启动时固化,配置说明中明确指出仅对新调试会话生效。

java.debug.settings.debugSupportOnDecompiledSource 控制对反编译源码的调试支持。当调试器需要解析非文件 URI(如 JDT 内部的类文件 URI)的源码时,会先尝试从类文件本身获取源码范围:若类文件自带源码信息,则直接使用该信息解析为抽象语法树;若类文件没有源码信息且此配置为 on,则通过内容提供者调用反编译器获取源码内容,再交给解析器处理。反编译路径会根据类文件所属的 Java 项目决定解析环境:若类文件有对应的 Java 项目,则使用该项目的编译环境;否则使用空环境并显式指定编译器选项(源码级别、目标平台、合规级别、预览特性启用)。由于反编译需要额外加载反编译器并解析源码,该功能可能影响调用栈视图的加载速度。当配置为 off 时,无源码的类文件将无法在源码视图中显示,调用栈中对应帧也无法进行源码级调试。

异常断点的行为由 exceptionBreakpoint.exceptionTypesallowClassesskipClasses 三个配置共同决定。异常断点处理器在首次处理请求时,从 VSCode 的过滤器参数中提取"已捕获异常"与"未捕获异常"两个勾选标志,并注册调试设置变更监听。当三个异常断点配置中任一发生变更时,前端会设置一个"异常过滤器已更新"标志发送给服务端,监听器检测到该标志后才会重新设置异常断点,避免无关配置变更触发昂贵的断点重建。异常断点的设置逻辑分两种情况:当 exceptionTypes 为空时,创建一个针对所有异常的断点请求,并将 allowClasses 作为类包含过滤器、skipClasses 作为类排除过滤器应用到该请求;当 exceptionTypes 非空时,对每个异常类型分别处理,先创建类加载监听请求监听该类型的未来类加载,在类加载时动态创建对应的异常断点,同时遍历已加载的同类类立即创建断点。这种设计支持了对尚未加载的异常类型的断点能力。skipClasses 中的 $JDK$Libraries 变量会由前端展开为具体的类名列表后再传递给服务端。

步骤执行由 stepping.skipClassesskipSyntheticsskipStaticInitializersskipConstructors 四个配置共同控制。skipClasses 中的 $JDK$Libraries 变量同样会在前端展开为具体类名列表,展开后的过滤器发送给服务端存储。当用户执行步入或步出时,会将 skipClasses 作为类排除过滤器应用到步骤请求中。skipSyntheticsskipStaticInitializersskipConstructors 三个布尔标志则在步骤事件触发时判断是否跳过:若步骤事件发生在合成方法、静态初始化方法或构造函数中,且对应标志为 true,则自动继续执行下一步而不暂停。步过操作不应用类过滤器,因为其语义是同一方法内的行级跳转。

变量视图的显示由 showHexshowQualifiedNamesshowStaticVariablesshowLogicalStructureshowToStringmaxStringLengthnumericPrecision 七个配置共同控制。showStaticVariables 决定是否列出静态变量:仅当该值为 true 且当前栈帧所在方法为静态方法时,才会列出静态变量;对于非静态方法的栈帧,静态变量通过 this 对象的字段展示。当启用异步 JDWP 时,静态变量的获取会切换为异步拉取。showLogicalStructureshowToString 受异步 JDWP 状态联动影响:仅当未启用异步 JDWP,或虽启用异步但 JDWP 延迟低于可用阈值,且对应配置为 true 时,才真正启用逻辑结构视图或 toString 视图。这一机制避免在高延迟网络下因发起大量 JDWP 请求而拖慢变量视图响应。showHexshowQualifiedNamesmaxStringLengthnumericPrecision 由变量格式化器在格式化变量值时读取,分别控制数值的进制、类名的显示形式、字符串的截断长度、double 的格式化精度。

这五个布尔开关还通过上下文键驱动右键菜单的显示状态。扩展会将每个配置值映射为开关上下文键,与菜单的可见性条件配合,实现 Show as HexShow as Dec 等互斥菜单项的动态切换。当用户通过右键菜单切换某项时,扩展会根据配置的当前作用域(工作区文件夹、工作区、全局)选择合适的写入位置更新 settings.json,然后立即刷新变量视图,无需重启调试会话。此外,VSCode 内置的 debug.autoExpandLazyVariables 配置控制懒展开变量,扩展在切换该配置时会强制将 showToString 设为 true,因为懒展开变量依赖 toString 视图机制才能工作。

java.debug.settings.jdwp.asyncauto 模式基于网络延迟自动决策:若配置为 on 则始终启用异步;若为 off 则始终禁用;若为 auto 则仅当 JDWP 网络延迟超过 15 毫秒时才启用异步。该延迟值在附加调试时通过发送测试请求测量得出。设计考量是以 1 秒作为调试适配协议请求的可接受延迟,单线程策略下每条 JDWP 请求约 15 毫秒延迟可保证响应性,1 秒内可发送约 66 条 JDWP 请求,足以覆盖断点、线程、调用栈、步骤、继续等大部分操作;超过此延迟时切换为多线程异步模式,通过工作窃取线程池并发执行 JDWP 请求以提升远程调试响应速度。异步模式启用后,变量获取会切换为异步版本,通过并发拉取局部变量、this 变量与静态变量。但异步模式会禁用逻辑结构视图与 toString 视图(除非延迟低于阈值),因为这两个特性需要发起大量 JDWP 请求,在异步并发下可能导致请求顺序问题。

java.debug.settings.jdwp.limitOfVariablesPerJdwpRequest 控制单次 JDWP 请求的变量分页大小。在批量获取字段值或局部变量值时,会按此值对字段列表分页,每页调用一次批量获取。当一次性传递的变量数量过大时,JDI 可能抛出超时异常,因此采用分页方式分块拉取。值越大则展开变量视图时请求 debuggee 的频率越低,但同时也越容易触发 JDWP 请求超时。java.debug.settings.jdwp.requestTimeout 控制 JDWP 请求的超时时间。前端在发送设置更新时会强制将 limitOfVariablesPerJdwpRequest 与 1 取最大值、将 requestTimeout 与 100 取最大值,避免用户配置出无效值。

java.debug.settings.hotCodeReplace 的三种模式在运行时构成一个状态机,由前端与服务端协同实现。服务端根据配置决定是否注册资源变更监听:仅当模式不为 never 时才监听构建后事件,never 模式下完全跳过资源变更监听以避免不必要的开销。当监听到类文件变更时,服务端提取变更的类文件路径并发布热替换事件,由处理器转换为调试适配协议事件发送给前端。前端处理两类事件:当收到构建完成事件且配置为 auto 时,自动应用类变更并在状态栏显示"应用代码变更"进度;当配置为 manual 时,前端仅展示工具栏按钮,等待用户点击后触发应用;当配置为 never 时,按钮不显示且不处理构建完成事件。当热替换失败时,前端会检查失败消息是否在已抑制原因集合中:若不在则弹出对话框询问是否重启调试会话,提供重启、不重启、不再提示(将该失败消息加入已抑制集合,后续相同失败不再提示)三个选项。该集合在调试会话终止时清空,确保下次调试会话重新提示。

配置热更新流程

Debugger for Java 的配置传递分为启动时传递与运行时热更新两条路径。启动时,launch.json 配置通过启动调试流程完整解析后传递给调试适配器;运行时,java.debug.settings.* 配置通过设置更新命令序列化为 JSON 发送给语言服务器。

java.debug.logLevel 在传递给服务端前会从通用日志级别转换为 Java 日志级别:verbose 转为精细级别,warn 转为警告级别,error 转为严重级别,info 转为信息级别,其他值默认转为精细级别。转换后的级别会随其他设置一起发送给服务端,控制调试器日志的输出阈值。

配置提供器在构造时会注册配置变更监听器,当 java.debug.* 配置发生变更时执行热更新决策。决策逻辑为:若当前存在活动调试会话,则立即发送设置更新进行热更新,并清除脏标记;若不存在活动调试会话,则仅设置脏标记,在下一次启动调试时统一同步。设置更新函数会从 java.debug 配置节读取所有设置,构建包含步骤过滤器、异常过滤器、异常过滤器更新标志、JDWP 分页大小、JDWP 超时、异步模式、日志级别、Java 主目录等字段的 JSON 对象发送给服务端。其中步骤过滤器与异常过滤器的 skipClasses 会经过变量替换,异常过滤器更新标志根据变更事件是否影响异常断点三项配置来计算,JDWP 分页大小与超时会与最小值取最大值。若发送失败仅记录警告日志,不阻塞调试会话。

配置的覆盖优先级遵循 VSCode 标准层次:文件夹级大于工作区级大于用户级大于默认值。launch.json 中的配置优先级高于 java.debug.settings.* 全局设置,这一规则在 vmArgsconsole 等属性的回退逻辑中均有体现。当用户通过右键菜单修改变量视图配置时,扩展会检测该配置的当前作用域:若已存在工作区文件夹级值则更新到工作区文件夹级,若已存在工作区级值则更新到工作区级,否则更新到全局级,确保变更写入与当前生效作用域一致的位置。

配置最佳实践

对于远程调试场景,建议将 java.debug.settings.jdwp.async 设为 on 以提升高延迟网络下的响应速度,同时适当增大 jdwp.requestTimeout 避免超时;对于变量较多的复杂对象,可调整 jdwp.limitOfVariablesPerJdwpRequest 在请求频率与超时风险之间取得平衡。

对于多线程调试场景,若需要观察其他线程状态,可将 java.debug.settings.suspendAllThreads 设为 true,但需注意该配置仅对新会话生效,且会显著增加断点命中时的暂停开销。

对于大型项目,若频繁遇到命令行过长导致的启动失败,可显式将 shortenCommandLine 设为 argfile(JDK 9+)或 jarmanifest(JDK 8)以绕过 auto 模式的检测延迟;若构建失败提示打扰开发节奏,可将 onBuildFailureProceed 设为 true 直接跳过构建失败提示。

对于反编译源码调试,若调用栈视图加载明显变慢,可尝试将 java.debug.settings.debugSupportOnDecompiledSource 设为 off 关闭反编译回退,仅对自带源码的类文件提供源码级调试。

对于团队协作,推荐将统一的 vmArgsconsolestepFilters 配置写入 .vscode/settings.json 共享,会话级配置则在 launch.json 中按需覆盖,确保团队调试体验一致。

posted @ 2026-08-09 15:20  减瓦~  阅读(8)  评论(0)    收藏  举报