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

时间:2012-02-13 05:54:17

标签: java linux gdb java-native-interface shared-libraries

任何人都可以指导如何使用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 debug .so文件编译.cpp文件吗?

3 个答案:

答案 0 :(得分:12)

  1. 启动您的Java应用程序
  2. 使用top,ps,...查找pid
  3. 使用此pid启动gdb
  4. 附上您的程序代码
  5. 使用gdb
  6. 照常调试

    此博客post解释了整个事情。

答案 1 :(得分: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和gdb-multiarch的嵌入式设备上进行调试。

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

答案 2 :(得分:0)

tm.sauron的

Link是正确的但是当我们有许多参数传递给java命令时会不太方便,就像我的项目有几行param要传递一样。因此,在这种情况下,我们可以使用IDE启动应用程序,并在我们想要在本机库中进行调试时将其分解。需要在调试模式下创建Ofcourse本机库。