如何在 Linux 上使用 GDB 调试 Java -JNI ?

任何人都可以指导如何使用GDB调试器在Linux上调试JNI代码(如果可能的话,请建议其他选项)。

    -My JNI project when running on Linux is leading to a JVM crash.
    -The CPP code has been compiled into .so files.
    -I run the project like  this : *java xyz.jar -commandline_args_to_project*.

我已经安装了Gdb,但不知道如何使用它来调试项目。另外,我是否必须使用 -g 选项 t 调试 .so 文件编译.cpp文件?


答案 1
  1. 启动您的 Java 应用程序
  2. 使用顶部,ps,...
  3. 用这个 pid 启动 gdb
  4. 附加程序代码
  5. 像往常一样使用 gdb 进行调试

这篇博客文章解释了整个事情。


答案 2

我发现以下方式非常有趣。通过将下面的文件链接到要调试的jni库,当动态链接器加载库时,由于gcc构造函数属性,它会自动启动当前jvm的gdbserver。

只需从命令行或 eclipse 使用远程 gdb,即可轻松进行调试。我只设置了如果我在调试模式下构建,我目前还没有实现检测jvm是否在调试中启动,只允许此时此刻,但可能很容易。

我只是简单地从文章中改编了这个概念:http://www.codeproject.com/Articles/33249/Debugging-C-Code-from-Java-Application

#ifndef NDEBUG // If we are debugging

#include <stdlib.h>
#include <iostream>
#include <sstream>

namespace debugger {
    static int gdb_process_pid = 0;

    /**
     * \brief We create a gdb server on library load by dynamic linker, to be able to debug the library when java begins accessing it.
     * Breakpoint have naturally to be set.
     */
    __attribute__((constructor))
    static void exec_gdb() {
        // Create child process for running GDB debugger
        int pid = fork();

        if (pid < 0) {
            abort();

        } else if (pid) {
            // Application process

            gdb_process_pid = pid; // save debugger pid
            sleep(10); /* Give GDB time to attach */

            // Continue the application execution controlled by GDB
        } else /* child */ {
            // GDBServer Process

            // Pass parent process id to the debugger
            std::stringstream pidStr;
            pidStr << getppid();

            // Invoke GDB debugger
            execl("/usr/bin/gdbserver", "gdbserver", "127.0.0.1:11337", "--attach", pidStr.str().c_str(), (char *) 0);

            // Get here only in case of GDB invocation failure
            std::cerr << "\nFailed to exec GDB\n" << std::endl;
        }
    }
}
#endif

此外,它还允许在安装了 gdbserver 的嵌入式设备上进行调试,并在开发 pc 上调试 gdb-multiarch。

从 eclipse 内部进行调试时,它会在 C/C++ 调试器和 Java 调试器之间自动跳转。您只需要启动两个调试会话:java会话和远程C / C++会话,该会话在127.0.0.1:11337上运行。


推荐