I’m trying to call a Java function from C++.
This is my code so far:
#include <jni.h>
typedef struct JavaVMCreationResult {
JavaVM* jvm;
JNIEnv* env;
} JVMCreationResult;
JVMCreationResult* CreateJavaVM() {
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption opts[1];
opts[0].optionString = "-Djava.class.path=C:\\MyJavaClasses";
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
args.options = opts;
args.ignoreUnrecognized = JNI_TRUE;
JNI_GetDefaultJavaVMInitArgs(&args);
JNI_CreateJavaVM(&jvm, (void **) &env, &args);
JavaVMCreationResult* cres;
cres->jvm = jvm;
cres->env = env;
return cres;
}
int main() {
JVMCreationResult* cres = CreateJavaVM();
JavaVM* jvm = cres->jvm;
JNIEnv* env = cres->env;
jclass cls = env->FindClass("Main");
jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V"); // the evil line
}
I’m using Code::Blocks with MinGW GCC on Windows 7.
The last line in the main() function crashes the Program, but the compiler does not complain about anything. (Commenting out the jmethodID mid = env->GetSta... line makes the program “not crashing”)
I have uses javap -s Main to obtain the right method signature, also the class is a valid Java class.
Can you tell me why the Program crashes ? This example is just shown everywhere on the Internet but it doesn’t work for me. 🙁
This is the Java class:
public class Main {
public static void main(String[] args) {
System.out.println("This is from Java !");
}
}
SOLUTION
I wouldn’t have thought it, it seems unlogic to me that the program wasn’t crashing earlier when the struct wasn’t initialized. But this was really the issue.
This is the full and working code !
#include <jni.h>
#ifndef null
#define null NULL
#endif
typedef struct JavaVMCreationResult {
JavaVM* jvm;
JNIEnv* env;
} JVMCreationResult;
JVMCreationResult* CreateJavaVM() {
JavaVM* jvm;
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption opts[1];
opts[0].optionString = "-Djava.class.path=C:\\Users\\Claudia\\Desktop";
args.version = JNI_VERSION_1_6;
args.nOptions = 1;
args.options = opts;
args.ignoreUnrecognized = JNI_TRUE;
JNI_GetDefaultJavaVMInitArgs(&args);
JNI_CreateJavaVM(&jvm, (void **) &env, &args);
JVMCreationResult* cres = new JVMCreationResult();
cres->jvm = jvm;
cres->env = env;
return cres;
}
int main() {
JVMCreationResult* cres = CreateJavaVM();
JavaVM* jvm = cres->jvm;
JNIEnv* env = cres->env;
jclass cls = env->FindClass("Main");
if (cls) {
printf("Yes !\n");
}
else {
printf("No !\n");
}
jmethodID mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
env->CallStaticVoidMethod(cls, mid);
printf("At end of Program.");
}
Your variable “cres” is a point in the CreateJavaVM call that is never initialized, so you’re probably dereferencing a null or otherwise invalid pointer at that point.
One solution is to define cres (not a pointer to cres) in main, and pass a pointer to that to CreateJavaVM as a parameter, and then use the parameter inside CreateJavaVM to return the result.
Also it’s a good idea to check that jvm and env get non-null values after the JNI_CreateJavaVM call, and that cls and mid are likewise non-null after the calls to FindClass and GetStaticMethodID, respectively