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

标签 java c++ 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
}

我在 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 !");
    }
}

解决方案

我没想到,在我看来,当结构未初始化时程序没有更早崩溃是不合逻辑的。但这确实是问题所在。
这是完整的工作代码!

#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.");
}

最佳答案

您的变量“cres”是 CreateJavaVM 调用中从未初始化的一个点,因此您可能在该点取消引用空指针或其他无效指针。

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

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

关于java - JNI "env->GetStaticMethodID()"程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7559059/

相关文章:

java - 获取 BufferedImage 的 RGB

java - 泛型可以推断出相关类型吗?

c++ - 递归读取 TCollection

c++ - 概念检查可以延迟到 C++ 中的类实例化吗?

c++ - STL 算法将整个容器而不是 .begin(), end() 作为 arg?

android - 无法使用 Superpowered 库为 arm64-v8a 创建 so 文件

c++ - JNI 使用静态 NTL 库构建共享库

c++ - 使用jni时如何清理jfloat

java - 显示数组排序

java - 识别集合中的重复项