1

当本机方法调用(直接或间接)某个 Linux 系统调用时,我如何在 Java 中设置一个断点?

4

2 回答 2

1

这不是一个断点,但至少它为您提供了堆栈跟踪,这可能是您所需要的。此外,如果需要,Systemtap 语言确实允许您做更多的事情,而不仅仅是打印堆栈跟踪。

在 IcedTea JVM 源代码中,您将找到一个SystemTap 文件,其中包含可用于从正在运行的 IcedTea(带有 Hotspot)JVM 获取堆栈跟踪的函数。据我了解,使用这些函数,您可以从 SystemTap 支持的任何事件中获取 Java 堆栈跟踪 - 甚至从内核事件中。

请注意,尽管名称相同,但这些 jstack 函数与 JDK 提供的 jstack(1) 命令行实用程序无关。它们通过内存检查工作,而不是通过回调 JVM,因此它们非常特定于 Hotspot internals,因此可能不适用于非基于 Hotspot 的 JVM。

注意:Systemtap 不能在默认的 Debian 内核上完全工作,因此您可能需要在基于 Debian 的系统上编译自己的内核。此问题不会影响 Fedora 或 Red Hat。

于 2012-07-21T08:55:26.853 回答
0

理论上,可以使用 Java 的提前 (AOT) 编译器对应用程序进行本地编译,然后使用本地调试器在系统调用上设置断点或捕获点。(奖励:然后您将获得完整的堆栈跟踪,包括本机方法调用的所有 C 函数,以及无缝调试这些 C 函数的能力。)

您可能想要使用知道如何对 AOT 编译器生成的名称进行解码的调试器。例如,gdb 知道如何对 gcj 生成的名称进行解码,因此 gcj 与 gdb 的组合应该可以工作。

这种组合的问题是 gcj 仍然停留在部分JDK 1.5 兼容性,并且没有人费心去做 OpenJDK 类库中的合并工作(2009 年在 gcj 邮件列表中建议)。因此,gcj 从来都不是一个流行的选择——人们经常无意中使用它(特别是在 Debian 和 Ubuntu 上),但是当他们遇到问题时,他们倾向于切换到更标准的 JDK 而不是报告错误。

使用 AOT 编译器进行本机编译也比在认为有必要时让 JRE JIT 编译代码慢得多。

于 2012-07-21T08:20:01.457 回答