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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9256176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:32:28  来源:igfitidea点击:

How to Debug Java -JNI using GDB on linux ?

javalinuxgdbjava-native-interfaceshared-libraries

提问by Twaha Mehmood

Can anyone guide on how to debug a JNI code on Linux using GDB debugger(if possible please suggest other options).

任何人都可以指导如何使用 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*.

I have the Gdb installed but am not getting how we can debug the project using it. Also do I necessarily need to compile the .cpp files with -g option t debug .so files?

我安装了 Gdb,但不知道如何使用它调试项目。另外我是否一定需要使用 -g 选项 t debug .so 文件编译 .cpp 文件?

采纳答案by Hymanrabbit

  1. Start your java application
  2. Look up the pid using top, ps, ...
  3. Start gdb with this pid
  4. Attach your program code
  5. Debug as usual using gdb
  1. 启动您的 Java 应用程序
  2. 使用 top, ps, ... 查找 pid
  3. 用这个pid启动gdb
  4. 附上您的程序代码
  5. 像往常一样使用 gdb 调试

This blog postexplains the whole thing.

此博客帖子解释了整个事情。

回答by twid

Linkby tm.sauron is right But would be less convenient when we have many parameters to pass to java command like my project has about several line of param to pass. So in that case we can use IDE to start application and breaking it to point when we want to debug in native library. Ofcourse native library need to be created in debug mode.

tm.sauron 的链接是正确的但是当我们有很多参数要传递给 java 命令时会不太方便,比如我的项目有大约几行参数要传递。所以在这种情况下,我们可以使用 IDE 来启动应用程序,并在我们想要在本机库中调试时中断它。当然本机库需要在调试模式下创建。

回答by daminetreg

I found the following way really interesting. By linking the file below to the jni library you want to debug, when the library get loaded by the dynamic linker it automatically starts a gdbserver for the current jvm, thanks to the gcc constructor attribute.

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

Simply using remote gdb from command line or from eclipse make it easy to debug then. I only setup that if I build in debug mode, I haven't implemented for the moment to detect if jvm was started in debug, to only allow this at this moment, but could be easy.

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

I simply adapted the concept from the article here : http://www.codeproject.com/Articles/33249/Debugging-C-Code-from-Java-Application

我只是修改了这里文章中的概念: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

Additionally it also allows debugging on embedded devices with gdbserver installed and gdb-multiarch on your development pc.

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

While debugging from within eclipse it jump automatically between the C/C++ debugger and the Java debugger. You just have to start both debugging session : the java one and the remote C/C++ one which runs on 127.0.0.1:11337.

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