JNI"env-> GetStaticMethodID()"崩溃的程序

Nik*_*s R 2 c++ java java-native-interface

我正在尝试从C++调用Java函数.到目前为止这是我的代码:

#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
}
Run Code Online (Sandbox Code Playgroud)

我在Windows 7上使用Code :: Blocks和MinGW GCC.main
()函数的最后一行崩溃了程序,但编译器没有抱怨任何事情.(注释掉该jmethodID mid = env->GetSta...行会使程序"崩溃")
我有javap -s Main用来获取正确的方法签名,该类也是一个有效的Java类.

你能告诉我程序崩溃的原因吗?这个例子只是在互联网上随处可见,但它对我不起作用.:(

这是Java类:

public class Main {
    public static void main(String[] args) {
        System.out.println("This is from Java !");
    }
}
Run Code Online (Sandbox Code Playgroud)

我不会想到它,对我来说似乎没有逻辑,当结构未初始化时程序没有崩溃.但这确实是个问题.
这是完整且有效的代码!

#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.");
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ric 5

您的变量"cres"是CreateJavaVM调用中永远不会初始化的一个点,因此您可能在该点取消引用null或其他无效指针.

一种解决方案是在main中定义cres(不是指向cres 的指针),并将指向的指针传递给CreateJavaVM作为参数,然后使用CreateJavaVM中的参数返回结果.

在JNI_CreateJavaVM调用之后检查jvm和env是否获得非空值是个好主意,并且在分别调用FindClass和GetStaticMethodID之后,cls和mid同样是非null的.