JNI 类 ID 段错误

Posted

技术标签:

【中文标题】JNI 类 ID 段错误【英文标题】:JNI class ID segfault 【发布时间】:2016-12-25 21:50:57 【问题描述】:

我曾尝试在 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 和未来使用都在具有相同 env 实例的“线程 4”上(由 JNI 传递,未缓存)。还有其他线程,但是segfault和init在同一个线程上。

【问题讨论】:

【参考方案1】:

问题是我没有意识到 ->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;

【讨论】:

以上是关于JNI 类 ID 段错误的主要内容,如果未能解决你的问题,请参考以下文章

Java JNI 错误 java.lang.UnsatisfiedLinkError: xxxx()V

c++ 类向量中的段错误

在类对象段错误中使用 boost::interprocess,为啥?

用封装的栈回溯类捕获段错误

这段代码的验证错误怎么可能?

静态数组仅在类定义内溢出堆栈(段错误 11),否则不会......?