mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
195 lines
16 KiB
Plaintext
195 lines
16 KiB
Plaintext
---
|
||
title: "调试"
|
||
description: "通过内置的 Debug Adapter Protocol 客户端设置断点、单步执行、查看变量和计算表达式。"
|
||
---
|
||
|
||
OpenIDEA 通过 [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/)(DAP)调试程序。每种语言在自己的语言定义(`languages/<id>.toml` 的 `[debugger]` 表)里指定调试适配器,调试运行配置时 IDE 会启动对应的适配器。命令和快捷键沿用 IntelliJ IDEA 的习惯,在 IDEA 里熟悉的操作大多可以直接用。
|
||
|
||
## 启动调试会话
|
||
|
||
只要[运行配置](/zh/guide/run)带有调试适配器,就可以调试:
|
||
|
||
- 点击 `main` 函数或测试旁边的边栏运行图标,选择 **调试**。
|
||
- 在工具栏的运行小部件里选好配置,点击调试按钮。
|
||
- **运行 › 调试** 调试当前选中的配置;**运行 › 调试…** 先选择配置;**运行 › 调试上下文配置** 调试光标处的程序或测试。
|
||
|
||
配置用哪个调试器,由 **运行 › 编辑配置…** 中的 **调试适配器** 字段决定。设为 **无** 即可关闭该配置的调试。
|
||
|
||
会话启动前,OpenIDEA 会先保存所有打开的文件。如果适配器没有安装,IDE 会给出提示;对于能自动安装的调试器,还会提供 **安装并调试**。
|
||
|
||
调试工具窗口(`⌘5` / `Alt+5`)每个会话一个标签页,包含两个视图:
|
||
|
||
- **线程和变量**:线程列表、选中线程的栈帧,以及选中帧的变量。库代码的帧默认折叠,用 **显示所有帧** 展开。
|
||
- **Console**:程序输出,以及一个输入行,可在选中帧里计算表达式。用 **浏览控制台历史**(`⌘⌥E` / `Ctrl+Alt+E`)翻看之前输入过的表达式。
|
||
|
||
<Note>这两个视图的标签名目前还没有翻译,中文界面下也显示英文。</Note>
|
||
|
||
## 支持的调试器
|
||
|
||
| 语言 | 调试适配器 | 获取方式 |
|
||
| --------------------------------- | ---------------------------------------- | ------------------------------------------------------------------ |
|
||
| Java | Microsoft java-debug(运行在 JDT LS 内) | 一键安装 |
|
||
| Kotlin | kotlin-debug-adapter | 一键安装 |
|
||
| C、C++、Objective-C、Swift | `lldb-dap` | 随 LLVM、Xcode(`xcrun -f lldb-dap`)和 Swift 6+ 工具链提供 |
|
||
| Rust、Zig | CodeLLDB | 一键安装 |
|
||
| Go | Delve(`dlv`) | 一键安装(通过 `go install`,需先装好 Go) |
|
||
| Python | debugpy | 一键安装一份私有副本,所有解释器共用;也可以 `pip install debugpy` |
|
||
| JavaScript、TypeScript(Node.js) | vscode-js-debug | 一键安装 |
|
||
| C#、F# | netcoredbg | 一键安装 |
|
||
| PHP | PHP Debug (Xdebug) | 适配器一键安装;PHP 本身需要装 Xdebug 3 扩展 |
|
||
| Shell 脚本 | Bash Debug | 一键安装 |
|
||
| Ruby | rdbg | `gem install debug` |
|
||
| Elixir | ElixirLS 调试器 | 一键安装 |
|
||
| Dart、Flutter | `dart debug_adapter` | 随 Dart / Flutter SDK 提供 |
|
||
| OCaml | earlybird | `opam install earlybird` |
|
||
| GDScript | Godot 编辑器 | Godot 4 |
|
||
|
||
C 和 C++ 的配置也可以改用 GDB 14 及以上版本(`gdb -i dap`):在 **调试适配器** 字段里选 **GDB(C、C++)**。IDE 不会自动安装 GDB,需要自己装(`apt install gdb`、`dnf install gdb`、`brew install gdb`)。
|
||
|
||
一键安装在 **设置 › 语言和框架 › 语言服务器** 里,调试器和语言服务器列在一起,可以在这里安装、更新,或者指定自己安装的版本。
|
||
|
||
<Warning>
|
||
在 macOS 上,CodeLLDB 和 Delve 可能要开启开发者模式后才能启动或附加。执行一次 `sudo DevToolsSecurity
|
||
-enable`,再重新启动调试会话。
|
||
</Warning>
|
||
|
||
## 断点
|
||
|
||
点击行号即可添加或移除行断点,也可以用 **切换行断点**(`⌘F8` / `Ctrl+F8`)。在边栏上:
|
||
|
||
- `⌥` 点击(`Alt` 点击)添加临时断点,命中一次后自动移除。
|
||
- `⇧` 点击(`Shift` 点击)添加不挂起程序的日志断点,并打开它的属性。
|
||
- 中键点击已有断点,启用或禁用它。
|
||
- 右键点击断点,编辑它的属性。
|
||
|
||
空行和只有注释的行不能加断点。默认情况下,行断点只能放在有调试器的语言文件里;如需放开限制,在 **设置 › 构建、执行、部署 › 调试器** 中打开 **允许在任意文件中设置断点**。
|
||
|
||
### 断点属性
|
||
|
||
| 选项 | 作用 |
|
||
| -------------------- | ---------------------------------------------------------------------- |
|
||
| **已启用** | 不删除断点,只是打开或关闭它。 |
|
||
| **挂起** | 关闭后,命中断点时程序继续运行(适合只记日志)。 |
|
||
| **条件** | 只有表达式为真时才停下。 |
|
||
| **命中次数** | 只有命中次数满足条件时才停下(语法由适配器决定,例如 `5` 或 `>= 5`)。 |
|
||
| **“已到达断点”消息** | 每次命中时在控制台输出一条消息。 |
|
||
| **计算并记录** | 每次命中时计算一个表达式并输出它的值。 |
|
||
|
||
断点对话框里也有这些选项,另外还有 **命中后移除**,勾选后断点变为临时断点。这些选项能否生效取决于适配器:条件、命中次数和日志消息都是 DAP 功能,大多数适配器支持,但不是全部。
|
||
|
||
### 其他断点类型
|
||
|
||
| 类型 | 添加方式 |
|
||
| ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| 临时行断点 | **切换临时行断点**(`⌘⌥⇧F8` / `Ctrl+Alt+Shift+F8`),或在边栏 `⌥` 点击 |
|
||
| 方法断点 | 在方法声明上执行 **切换方法断点**,或在断点对话框里点 **添加方法断点** |
|
||
| 字段监视点 | 在字段声明上执行 **切换字段监视点**,或在变量视图里对某个值选 **添加字段监视点**。可以选择在 **字段访问**、**字段修改** 或两者时挂起。 |
|
||
| 异常断点 | 断点对话框的 **异常断点** 部分列出适配器提供的异常过滤器(例如已捕获和未捕获的异常)。 |
|
||
|
||
方法断点和字段监视点需要适配器支持 DAP 的函数断点和数据断点。debugpy、java-debug、js-debug 和 CodeLLDB 的异常过滤器会直接列出;其他适配器的过滤器要用它调试过一次才会出现。
|
||
|
||
### 断点对话框
|
||
|
||
**查看断点…**(`⌘⇧F8` / `Ctrl+Shift+F8`)列出项目中的所有断点。可以在这里启用、编辑、删除断点和跳转到断点位置,打开 **静音断点**(暂时跳过所有断点而不删除),以及设置异常过滤器。**移除所有断点** 会清空列表。
|
||
|
||
断点按项目保存,重启后仍然保留。适配器无法设置的断点会标为未验证。
|
||
|
||
## 单步执行
|
||
|
||
下面的命令在 **运行** 菜单和调试工具窗口的工具栏上。
|
||
|
||
| 命令 | macOS | Windows / Linux |
|
||
| ---------------------------- | ------------- | --------------- |
|
||
| 恢复程序 | `⌘⌥R` 或 `F9` | `F9` |
|
||
| 暂停程序 | — | — |
|
||
| 步过 | `F8` | `F8` |
|
||
| 步入 | `F7` | `F7` |
|
||
| 智能步入 | `⇧F7` | `Shift+F7` |
|
||
| 步出 | `⇧F8` | `Shift+F8` |
|
||
| 强制步过 | `⌥⇧F8` | `Alt+Shift+F8` |
|
||
| 强制步入 | `⌥⇧F7` | `Alt+Shift+F7` |
|
||
| 运行到光标处 | `⌥F9` | `Alt+F9` |
|
||
| 强制运行到光标处 | `⌘⌥F9` | `Ctrl+Alt+F9` |
|
||
| 显示执行点 | `⌥F10` | `Alt+F10` |
|
||
| 重置帧 | — | — |
|
||
| 停止 | `⌘F2` | `Ctrl+F2` |
|
||
| 重新运行(在调试工具窗口中) | `⌘R` | `Ctrl+F5` |
|
||
|
||
- 当前行有多个调用时,**智能步入** 可以选择要进入哪一个。
|
||
- 带“强制”的命令会忽略途中的断点。
|
||
- 程序挂起时,行上还会出现一个内嵌的“运行到光标处”按钮(调试器设置中的 **显示内嵌的“运行到光标处”按钮**)。
|
||
- **重置帧** 回到选中帧所在方法的开头,需要适配器支持。
|
||
|
||
## 查看和修改值
|
||
|
||
程序挂起时:
|
||
|
||
- **变量** 视图显示选中帧的变量。右键点击某个值,可以 **设置值…**(`F2`)、**复制值**、**复制名称**、**跳转到源代码**(`F4`)和 **添加到监视**。
|
||
- 监视表达式显示在变量视图顶部,每次停下或切换帧时重新计算。用 **添加到监视** 添加,用 **移除监视** 删除。
|
||
- 在编辑器里悬停变量会显示它的值。`⌥` 点击(`Alt` 点击)或 **快速计算表达式**(`⌘⌥F8` / `Ctrl+Alt+F8`)计算鼠标下的表达式或选中的内容。
|
||
- 局部变量的值会内联显示在使用它们的行尾。
|
||
- **计算表达式…**(`⌥F8` / `Alt+F8`)打开对话框,在选中帧里计算任意表达式,带历史记录,也能把表达式加入监视。
|
||
|
||
表达式使用被调试程序的语言,由调试适配器计算,能写什么取决于适配器。
|
||
|
||
## 附加到正在运行的进程
|
||
|
||
**运行 › 附加到进程…**(`⌥⇧F5` / `Ctrl+Alt+F5`)列出调试器可以附加的本用户进程,按调试器分组:
|
||
|
||
| 分组 | 进程 |
|
||
| ---------------- | ------------------------------------------------------- |
|
||
| Java (JDWP) | 带 JDWP agent 启动的 JVM |
|
||
| Node.js | 用 `--inspect` 启动的 Node 进程 |
|
||
| Python (debugpy) | Python 进程(注入 debugpy,或连接它的 `--listen` 端口) |
|
||
| Go (Delve) | Go 二进制程序 |
|
||
| Native (LLDB) | 其他进程;装了 CodeLLDB 就用它,否则用 `lldb-dap` |
|
||
|
||
输入文字可按名称、PID 或命令行过滤。
|
||
|
||
### 远程调试配置
|
||
|
||
要调试在别处(另一台机器、容器里)启动的进程,在 **运行 › 编辑配置…** 里添加下面的配置。它们只能调试,不会启动进程。
|
||
|
||
| 配置 | 作用 |
|
||
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| **远程 JVM 调试** | 附加到带 JDWP agent 启动的 JVM,或者等待 JVM 主动连接(**调试器模式**:**附加到远程 JVM** / **监听远程 JVM**)。表单会给出远程 JVM 需要加的启动参数。 |
|
||
| **Go 远程** | 附加到用 `dlv --headless` 启动的 Delve 服务。 |
|
||
| **Python 远程调试 (debugpy)** | 附加到用 debugpy 监听的 Python 进程。 |
|
||
| **附加到 Node.js** | 附加到用 `--inspect` 启动的 Node.js 进程。 |
|
||
| **PHP 远程调试 (Xdebug)** | 监听 Xdebug 连接,用于 php-fpm 或容器里运行的 PHP。 |
|
||
| **附加到 Godot** | 调试 Godot 编辑器正在运行的游戏。 |
|
||
|
||
每个表单都有 **主机** 和 **端口** 字段,并给出远程端的启动命令。远程代码所在目录与本地不同时,用 **本地根目录** 和 **远程根目录** 做路径映射。
|
||
|
||
## 各语言的特有功能
|
||
|
||
- **Java HotSwap**:**运行 › 调试操作 › 重新加载已更改的类** 编译改动,并把变化的类重新加载到正在运行的 Java 调试会话中。已经在执行的帧要等返回后才会用上新代码。保存后 JDT LS 自动完成构建时,IDE 也会提示是否重新加载。
|
||
- **Maven 和 Gradle**:调试 Maven 或 Gradle 配置时,IDE 会让 JVM 带上 JDWP agent 启动,再用 java-debug 附加上去。
|
||
- **Dart / Flutter**:Dart 会话运行时可以用 **热重载** 和 **热重启**。
|
||
- **PHP**:如果 PHP 解释器没有加载 Xdebug,断点会被跳过;会话启动时 IDE 会提示。
|
||
- **Python**:**设置 › 构建、执行、部署 › Python 调试器** 中有 **调试时自动附加到子进程** 和 **兼容 Gevent**。
|
||
|
||
## 设置
|
||
|
||
**设置 › 构建、执行、部署 › 调试器**:
|
||
|
||
- **命中断点时显示调试窗口**、**在断点处聚焦应用程序**、**进程终止时隐藏调试窗口**。
|
||
- **断点**:**允许在任意文件中设置断点**、**显示内嵌的“运行到光标处”按钮**。
|
||
- **数据视图**:**内联显示值**、**按字母顺序对值排序**、**鼠标悬停时显示值工具提示**、**选中代码时显示值提示**、**值工具提示延迟(毫秒)**。
|
||
- **单步执行**:**不要步入库脚本**(Python 只调试自己的代码;JavaScript 跳过 `node_modules` 和 Node.js 内部代码)。
|
||
|
||
## 快捷键
|
||
|
||
| 操作 | macOS | Windows / Linux |
|
||
| ----------------- | ------ | --------------- |
|
||
| 调试 | `⌃D` | `Shift+F9` |
|
||
| 调试…(选择配置) | `⌃⌥D` | `Alt+Shift+F9` |
|
||
| 调试上下文配置 | `⌃⇧D` | — |
|
||
| 切换行断点 | `⌘F8` | `Ctrl+F8` |
|
||
| 查看断点… | `⌘⇧F8` | `Ctrl+Shift+F8` |
|
||
| 计算表达式… | `⌥F8` | `Alt+F8` |
|
||
| 附加到进程… | `⌥⇧F5` | `Ctrl+Alt+F5` |
|
||
| 调试工具窗口 | `⌘5` | `Alt+5` |
|
||
|
||
以上都是默认键位,可以在[键位映射](/zh/guide/keymap)设置中修改。
|