Ich versuche zum ersten Mal, eine JVM von C++ über JNI zu laden, aber ich kann nicht scheinen, es zu funktionieren. Ich erhalte einen segfault, wenn ich JNI_CreateJavaVM aufruft.Segfault auf JNI_CreateJavaVM
Der Code ist ziemlich geradlinig (meist aus einem Online-Beispiel kopiert):
#include<stdio.h>
#include<jni.h>
using namespace std;
int main(int argc, char** argv) {
printf("Initializing JVM\n");
JavaVM *jvm;
JNIEnv *env;
printf("Setting up args\n";
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
printf("Attempting to create JVM\n");
jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
if(rc != JNI_OK) {
printf("didn't work :(\n");
}
else {
printf("JVM load succeeded!\n");
jint ver = env->GetVersion();
printf("Version: %i.%i\n", (ver>>16)&0x0f, ver&0x0f);
printf("Cleaning up\n");
delete options;
jvm->DestroyJavaVM();
}
printf("Done\n");
}
Mein LD_LIBRARY_PATH /usr/java/jdk1.6.0_45/jre/lib/amd64/server enthält, welche der Pfad enthält eine Bibliothek libjvm.so. Es gibt ein paar andere libjvm.so Bibliotheken auf meinem System, aber die meisten von ihnen sind für Java 1.4. Es gibt nur noch eine andere jdk 1.6 libjvm.so und ich habe es auch mit den gleichen Ergebnissen versucht.
ich kompilieren mit:
g++ -g -c src/jniExpCppPart.cpp -I/usr/java/jdk1.6.0_45/include -I/usr/java/jdk1.6.0_45/include/linux -o obj/jniExpCppPart.o
g++ obj/jniExpCppPart.o -L/usr/java/jdk1.6.0_45/jre/lib/amd64/server -ljvm -o exe/jniExp
Und wenn ich es innerhalb gdb laufen lasse, erhalte ich die ersten drei Druckanweisungen, gefolgt von:
Program received signal SIGSEGV, Segmentation fault
0x0000003249479e27 in strncmp() from /lib64/libc.so.6
(gdb) bt
#0 0x0000003249479e27 in strncmp() from /lib64/libc.so.6
#1 0x00002aaaaacd8c10 in Arguments::process_sun_java_launcher_properties(JavaVMInitArgs*)() from /usr/java/jdk1.6.0_45/jre/lib/amd64/server/libjvm.so
#2 0x00002aaaab2cfe7d in Thread::create_vm(JavaVMInitArgs*, bool*)() from /usr/java/jdk1.6.0_45/jre/lib/amd64/server/libjvm.so
#3 0x00002aaaaafcc800 in JNI_CreateJavaVM() from /usr/java/jdk1.6.0_45/jre/lib/amd64/server/libjvm.so
#4 0x0000000000400761 in main(argc=1, argv=0x7fffffffe568) at src/jni/ExpCppPart.cpp:22
Meine Vermutung ist, dass das Problem mehr hat tun, wie meine Umgebung eingerichtet ist oder wie ich die ausführbare Datei anstelle des Codes erstellte. Es ist ein paar Jahre her, dass ich mich wirklich damit beschäftigt habe, gemeinsame Bibliotheken zu verlinken, also ist es definitiv möglich, dass ich etwas vermasselt habe.
Irgendwelche Ideen, was ich falsch machen könnte?
Update Ich versuchte, die Bibliothek mit dlopen stattdessen zu laden (weil ich es in einigen Linux-Code sah, der JNI verwendet). Es machte keinen Unterschied, aber ich dachte, ich würde es hier einbeziehen, um zu sehen, ob es jemanden einen Hinweis darauf gibt, was ich falsch machen könnte.
Noch einmal kopiere ich das von Hand von einem System, das nicht mit dem Internet verbunden ist, so dass es einige Tippfehler geben kann.
#include<stdio.h>
#include<jni.h>
#include<dlfcn.h>
using namespace std;
//Create type for pointer to the JNI_CreateJavaVM function
typedef jint (*CreateJvmFuncPtr) (JavaVM**, void**, JavaVMInitArgs*);
//New method returns pointer to the JNI_CreateJavaVM function
CreateJvmFuncPtr findCreateJvm() {
CreateJavaFuncPtr createJvm = NULL;
void* jvmLib = dlopen("libjvm.so", RTLD_LAZY); //Get handle to jvm shared library
char* error = dlerror(); //Check for errors on dlopen
if(jvmLib = NULL || error != NULL) {
printf("FailedToLoadJVM\n");
}
//Load pointer to the function within the shared library
createJvm = (CreateJvmFuncPtr) dlsym(jvmLib, "JNI_CreateJavaVM");
error = dlerror();
if(error != NULL) {
printf("Success\n");
}
return createJVM;
}
int main(int argc, char** argv) {
printf("Initializing JVM\n");
JavaVM *jvm;
JNIEnv *env;
printf("Setting up args\n";
JavaVMInitArgs vm_args;
JavaVMOption* options = new JavaVMOption[1];
options[0].optionString = "-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_6;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = false;
printf("Attempting to create JVM\n");
//Old code: jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
//New code:
CreateJvmFuncPtr createJVM = findCreateJvm();
printf("findCreateJVM() returned 0x%x\n", createJVM);
jint rc = createJVM(&jvm, (void**)&env, &vm_args);
//End new code
if(rc != JNI_OK) {
printf("didn't work :(\n");
}
else {
printf("JVM load succeeded!\n");
jint ver = env->GetVersion();
printf("Version: %i.%i\n", (ver>>16)&0x0f, ver&0x0f);
printf("Cleaning up\n");
delete options;
jvm->DestroyJavaVM();
}
printf("Done\n");
}
Der Ausgang (ähnlich wie zuvor) zeigt, dass alles, was erfolgreich ist, bis er eine segfault von innerhalb der JNI_CreateJavaVM Methode löst.
So scheint es, dass zumindest das Programm die Bibliothek/Funktion gut finden kann. Aber etwas schief geht, wenn es heißt. Für mich deutet dies darauf hin, dass es sich entweder nur um ein einfaches API-Missverständnis handeln könnte (ich übergebe es etwas anderes als das, was ich sein sollte) oder dass es etwas Seltsames mit der gemeinsam genutzten Bibliothek gibt. Könnte dies möglicherweise verursacht werden, wenn die gemeinsam genutzte Bibliothek für eine Architektur/Wortgröße kompiliert wurde, für die mein Programm nicht kompiliert wurde? Wenn ja, wie kann ich die Zielarchitektur sowohl für mein Programm als auch für die Bibliothek überprüfen?
mit segfault Ich habe das Gefühl, der Code, den Sie verwenden, hat einen logischen Fehler. da ein segfault versucht, auf Speicher zuzugreifen, der nicht dort ist, wie wenn Sie über die Grenzen eines Arrays gehen. Es ist auch sinnvoll, die ersten drei Druckanweisungen zu erhalten, da die Zeile 'jint rc = JNI_CreateJavaVM (& jvm, (void **) && env, & vm_args) fehlschlägt. ' – jgr208
Welchen Befehl verwenden Sie, um das Programm auszuführen? kompiliere auch mit -Wall und -Werror – jgr208
Ich laufe nur mit ./exe/jniExp Oder mit gdb, gdb exe/jniExp gefolgt von run – NateW