Chrome 调试器

GraalVM 支持调试宿主语言应用程序,并提供了 Chrome DevTools 协议的内置实现。这允许您将兼容的调试器(例如 Chrome 开发者工具)连接到 GraalVM。

要调试宿主语言应用程序,请将 --inspect 选项传递给命令行启动器,例如以下 Node.js HelloWorld 程序的示例:

var http = require('http');

var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello World!\n");
});

server.listen(8000);

console.log("Server running at https://:8000/");
  1. 将此程序保存为 HelloWorld.js,然后运行:
    $JAVA_HOME/bin/node --inspect HelloWorld.js
    Debugger listening on ws://127.0.0.1:9229/SBqxI5YIqtREaDrXkFr8hLE0HL1AfKx8TjkI8qPMq2s
    For help, see: https://graalvm.java.net.cn/tools/chrome-debugger
    For example, in Chrome open: devtools://devtools/bundled/js_app.html?ws=127.0.0.1:9229/SBqxI5YIqtREaDrXkFr8hLE0HL1AfKx8TjkI8qPMq2s
    
  2. 在浏览器中导航到 https://:8000/ 以启动 Node 应用程序。

  3. 在单独的 Chrome 浏览器选项卡中打开 devtools:... 链接。

  4. 导航到 HelloWorld.js 文件并在第 4 行设置一个断点。

  5. 刷新 Node.js 应用程序,您会看到命中断点。

现在您可以检查堆栈、变量,在工具提示中评估变量和选定的表达式等。例如,将鼠标悬停在 response 变量上,您可以检查其属性,如下图所示:

Chrome Inspector

有关 Chrome DevTools 调试功能的详细信息,请查阅 JavaScript 调试参考

此调试过程适用于 GraalVM 支持的所有宿主语言。其他语言(如 R 和 Ruby)可以像 JavaScript 一样轻松调试,包括在宿主语言互操作性期间跨越语言边界。

检查选项 #

Node 启动器 #

GraalVM 的 Node.js 运行时接受与基于 V8 JavaScript 引擎的 Node.js 相同的选项,例如:

--inspect[=[host:]<port number>]

这会启用检查器代理,并默认在端口 9229 上侦听。要在不同端口上侦听,请指定可选的端口号:

--inspect-brk[=[host:]<port number>]

这仅适用于 node 启动器。

其他语言启动器 #

其他宿主语言启动器(例如 jspythonRscriptrubyllipolyglot)接受 --inspect[=[host:]<port number>] 选项,但默认情况下会在应用程序代码的第一行暂停。

--inspect.Suspend=(true|false)

如果指定 --inspect.Suspend=false,则会禁用初始暂停。

其他常用检查选项 #

所有启动器还接受以下附加选项:

  • --inspect.Path=<path> 允许用户指定生成连接 URL 的自定义路径。注意:浏览器中打开的任何已知此 URL 的网站都可以连接到调试器。因此,可预测的路径可能被恶意网站滥用,以在您的计算机上执行任意代码,即使您在防火墙后面。因此,默认情况下路径是随机生成的。
  • --inspect.SourcePath=<source path> 指定表示源路径的目录或 ZIP/JAR 文件列表。当被检查的应用程序包含对源文件的相对引用时,其内容将从相对于此源路径解析的位置加载。例如,这在 LLVM 调试期间很有用。路径在 UNIX 系统上由 : 分隔,在 MS Windows 上由 ; 分隔。
  • --inspect.Secure=(true|false) 当为 true 时,使用 TLS/SSL 保护调试协议。除了将 WS(WebSocket)协议更改为 WSS 之外,提供调试对象元数据的 HTTP 端点也会更改为 HTTPS。这与 chrome://inspect 页面不兼容,因为它无法提供调试对象信息并启动调试器。请直接通过打印的 WSS URL 启动调试。使用标准的 javax.net.ssl.* 系统选项提供包含 TLS/SSL 加密密钥的密钥库信息,或使用以下选项:
    • --inspect.KeyStore - 密钥库文件路径
    • --inspect.KeyStoreType - 密钥库文件类型(默认为 JKS)
    • --inspect.KeyStorePassword - 密钥库密码
    • --inspect.KeyPassword - 用于恢复密钥的密码,如果与密钥库密码不同
  • --inspect.WaitAttached=(true|false) 当为 true 时,在检查器客户端连接之前,不执行任何宿主语言源代码。与 --inspect.Suspend=true 不同,执行在客户端连接后立即恢复。这确保了检查器客户端不会错过任何执行。默认为 false
  • --inspect.SuspensionTimeout 设置调试器暂停的超时时间。超时时间到期后,调试会话将断开。超时值由一个正整数值和随后的时间单位组成。例如,“15m”或“10s”。有效的时间单位是“ms”表示毫秒,“s”表示秒,“m”表示分钟,“h”表示小时,“d”表示天。默认情况下没有设置超时。

高级调试选项 #

以下选项适用于语言专家和语言开发者:

  • --inspect.Initialization=(true|false) 当为 true 时,此选项会检查语言初始化阶段。当初始暂停处于活动状态时,这会在语言初始化开始时暂停,不一定在应用程序代码开始时暂停。默认为 false
  • --inspect.Internal=(true|false) 当为 true 时,内部源也会被检查。内部源可能提供语言实现细节。默认为 false

检查器后端编程式启动 #

嵌入者可以向 Engine/Context 提供适当的检查器选项以启动检查器后端。以下代码片段提供了可能的启动示例:

import org.graalvm.polyglot.*;

class DebuggerSample {
    public static void main(String... args) {
        String port = "4242";
        String path = java.util.UUID.randomUUID().toString();
        Context context = Context.newBuilder("js")
                    .option("inspect", port)
                    .option("inspect.Path", path)
                    .build();
        String hostAdress = "localhost";
        String url = String.format(
                    "chrome-devtools://devtools/bundled/js_app.html?ws=%s:%s/%s",
                    hostAdress, port, path);
    }
}

在 OpenJDK 上运行时,必须声明以下 Maven 依赖项才能将 Chrome 检查器工具与嵌入式代码一起使用:

<dependency> 
    <groupId>org.graalvm.polyglot</groupId> 
    <artifactId>polyglot</artifactId> 
    <version>${graalvm.polyglot.version}</version>
</dependency>
<dependency>
    <groupId>org.graalvm.tools</groupId>
    <artifactId>chromeinspector</artifactId>
    <version>${graalvm.polyglot.version}</version>
</dependency>

Chrome 检查器工具始终作为 GraalVM 上的工具可用。无需在此处显式声明任何依赖项。

联系我们