2016-12-25 79 views
2

我試圖在Java JNI中緩存MethodId和JClass,但是當我使用緩存的值時,我遇到了EXE_BAD_ACCESS。當我要求這些值與使用它們的函數內聯時,錯誤就消失了。我發現我需要使用全局引用,但這並沒有解決段錯誤。JNI class ID segfault

相關信息到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 *,螺紋*)+ 0×15

OS是蘋果10.12。 JDK 1.8.0_25。

此外,到目前爲止測試只有單線程和JNI環境是相同的。 ENV的

印刷描述:(JNIEnv的*)的env = 0x00007fcc3e0011e8 ENV的印刷的說明:(JNIEnv的*)的env = 0x00007fcc3e0011e8

兩者initStatic和將來的使用都在 「螺紋4」 與相同的env實例(由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; 
}