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

21

有人能指导一下如何在Linux上使用GDB调试器调试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选项编译.cpp文件才能调试.so文件?

3个回答

19
  1. 启动您的Java应用程序
  2. 使用 top、ps 等查找进程 ID(pid)
  3. 使用此 pid 启动 gdb
  4. 附加您的程序代码
  5. 像往常一样使用 gdb 进行调试

这篇博客文章解释了整个过程。


4
我在链接找到了另一种方法。使用这种方法,我能够在GDB中启动我的项目并进行调试,因此不需要切换不同的shell。 - Twaha Mehmood

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调试会话和远程运行在127.0.0.1:11337上的C/C++调试会话。

0

链接由tm.sauron提供的建议是正确的,但当我们需要传递许多参数到Java命令时,会变得不太方便,就像我的项目需要传递几行参数一样。因此,在这种情况下,我们可以使用IDE启动应用程序,并将其分解到我们想要在本地库中调试的点。当然,本地库需要以调试模式创建。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接