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

如何在linux上使用GDB调试Java-JNI?,java,linux,gdb,java-native-interface,shared-libraries,Java,Linux,Gdb,Java Native Interface,Shared Libraries,任何人都可以指导如何使用GDB调试器在Linux上调试JNI代码(如果可能,请建议其他选项) 我已经安装了Gdb,但不知道如何使用它调试项目。 我还需要使用-g选项t debug.so文件编译.cpp文件吗 启动java应用程序 使用top、ps、…查找pid 使用此pid启动gdb 附上你的程序代码 使用gdb进行常规调试 这篇博客解释了整个过程。by tm.sauron是正确的,但如果我们有许多参数要传递给java命令,那么就不那么方便了,就像我的项目有几行参数要传递一样。所以,在这种情况下

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

我已经安装了Gdb,但不知道如何使用它调试项目。 我还需要使用-g选项t debug.so文件编译.cpp文件吗

  • 启动java应用程序
  • 使用top、ps、…查找pid
  • 使用此pid启动gdb
  • 附上你的程序代码
  • 使用gdb进行常规调试

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

    by tm.sauron是正确的,但如果我们有许多参数要传递给java命令,那么就不那么方便了,就像我的项目有几行参数要传递一样。所以,在这种情况下,我们可以使用IDE启动应用程序,并在需要在本机库中调试时将其中断。当然,本机库需要在调试模式下创建。

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

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

    我只是将文章中的概念改写如下:

    \ifndef NDEBUG//如果我们正在调试
    #包括
    #包括
    #包括
    命名空间调试器{
    静态int gdb_进程_pid=0;
    /**
    *\brief我们通过动态链接器在库加载时创建一个gdb服务器,以便在java开始访问库时能够调试库。
    *必须设置断点。
    */
    __属性(构造函数)
    静态void exec_gdb(){
    //创建用于运行GDB调试器的子进程
    int-pid=fork();
    if(pid<0){
    中止();
    }否则如果(pid){
    //申请过程
    gdb_进程\u pid=pid;//保存调试器pid
    睡眠(10);/*给GDB时间连接*/
    //继续由GDB控制的应用程序执行
    }else/*儿童*/{
    //GDBServer进程
    //将父进程id传递给调试器
    std::stringstream-pidStr;
    我在找到了另一种方法。通过这种方法,我可以从GDB内部调试启动我的项目,因此它不需要切换不同的shell。
    
        -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*.
    
    #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