JNI类ID段错误

时间:2016-12-25 21:50:57

标签: java java-native-interface

我试图在Java JNI中缓存MethodId和JClass,但是当我使用缓存值时,我遇到了EXE_BAD_ACCESS。当我使用它们请求与函数内联的值时,错误消失了。我发现我需要使用全局引用,但这并没有解决段错误。

与jni缓存相关的信息(稍微过时的签名) - In JNI, how do I cache the class, methodID, and fieldIDs per IBM's performance recommendations?

部首:

extern jclass java_class_boolean;
extern jmethodID java_method_boolean;

CPP:

jclass java_class_boolean;
jmethodID java_method_boolean;
....
void initStatic(JNIEnv* env){
    java_class_boolean = env->FindClass("java/lang/Boolean");
    if (java_class_boolean){
        env->NewGlobalRef(java_class_boolean);
        java_method_boolean = env->GetMethodID(java_class_boolean, "<init>", "(Z)V");
    }
}

用法(不同的CPP类,导入共享标头):

    jclass bc = env->FindClass("java/lang/Boolean");
    jmethodID bm = env->GetMethodID(bc, "<init>", "(Z)V");

    std::cout << "\nClass new: ";
    std::cout << bc;
    std::cout << " Class old: ";
    std::cout << java_class_boolean;
    std::cout << "\nMethod new: ";
    std::cout << bm;
    std::cout << " Method old: ";
    std::cout << java_method_boolean;
    std::cout << "\n";
    result2 = env->NewObject(bc, bm, 1);

结果

  

新类:0x7fcce4430110旧类:0x7fcce6a23098方法新:   0x7fcce471c288方法旧:0x7fcce471c288

但是如果使用缓存类运行,则会产生段错误。

  

V [libjvm.dylib + 0x309bcf] alloc_object(_jclass *,Thread *)+ 0x15

操作系统是Mac 10.12。 JDK 1.8.0_25。

此外,目前的测试只是单线程,JNI env是相同的。

  

env的打印描述:(JNIEnv *)env = 0x00007fcc3e0011e8   env的打印描述:(JNIEnv *)env = 0x00007fcc3e0011e8

initStatic和将来的用法都在“线程4”上,具有相同的env实例(由JNI传递,而不是缓存)。还有其他线程,但segfault和init在同一个线程上。

1 个答案:

答案 0 :(得分:1)

问题是我没有意识到 - &gt; NewGlobalRef返回了一个对象。

我创建了此功能来解决问题。

inline jclass find_class_global(JNIEnv* env, const char *name){
    jclass c = env->FindClass(name);
    jclass c_global = 0;
    if (c){
        c_global = (jclass)env->NewGlobalRef(c);
        env->DeleteLocalRef(c);
    }
    return c_global;
}