Can anyone guide on how to debug a JNI code on Linux using GDB debugger(if possible please suggest other options).
-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?
The gdb allows you to examine and control the execution of code and is useful for evaluating the causes of crashes or general incorrect behavior. gdb does not handle Java™ processes, so it is of limited use on a pure Java program. It is useful for debugging native libraries and the JVM itself.
This blog post explains the whole thing.
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.
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.
I simply adapted the concept from the article here : 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With