2013-01-25 44 views
4

我正在編寫一些代碼來獲得一個派生線程從C++調用靜態Java方法。JNI:調用GetStaticMethodID爆炸

調用該方法的位如果放置在來自Java的本地調用中,但不是來自附加JNIEnv的線程,則該位可以正常工作。

我給自己定一個JavaVM的*如下:

jint JNI_OnLoad(JavaVM* jvm, void* reserved) 
{ 
    LOGI("Setting Java Virtual Machine"); 

    ThreadJNIEnvironment::javaVM = jvm; 

    return JNI_VERSION_1_6; 
} 

這不會被調用。

我然後產卵另一個線程,並從這個線程我做到以下幾點:

JNIEnv* env; 
jint ret = ThreadJNIEnvironment::javaVM->AttachCurrentThread(&env, NULL); 

LOGI("AttachCurrentThread returned %d", ret); 

jclass interfaceClass = env->FindClass("com/ecmsys/mcb/model/McbInterface"); 
jmethodID testMethod = env->GetStaticMethodID(interfaceClass, "Test", "()V"); 
env->CallStaticVoidMethod(interfaceClass, testMethod); 

AttachCurrentThread返回0

GetStaticMethod雖然打擊了以下錯誤:

Fatal signal 11 (SIGSEGV) at 0x0000002c (code=1)..... 

我只是看不到我做了什麼讓它不高興......哦,等等......你不能從一個產生的線程訪問Java應用程序類而不做一些設置......

jint JNI_OnLoad(JavaVM* jvm, void* reserved) 
{ 
    LOGI("Setting Java Virtual Machine"); 
    ThreadJNIEnvironment::javaVM = jvm; 

    JNIEnv* env; 


    jvm->AttachCurrentThread(&env, NULL); 
    jclass mcbInterface = env->FindClass("com/ecmsys/mcb/model/McbInterface"); 
    ThreadJNIEnvironment::interfaceClass = env->NewGlobalRef(mcbInterface); 

    return JNI_VERSION_1_6; 
} 

那麼做到這一點:

JNIEnv* env; 
jint ret = ThreadJNIEnvironment::javaVM->AttachCurrentThread(&env, NULL); 

LOGI("AttachCurrentThread retured %d", ret); 

if(ThreadJNIEnvironment::interfaceClass) 
{ 
    jmethodID testMethod = env-->GetStaticMethodID(static_cast<jclass>ThreadJNIEnvironment::interfaceClass), "Test", "()V"); 
    env->CallStaticVoidMethod(static_cast<jclass>(ThreadJNIEnvironment::interfaceClass), testMethod); 
} 


ThreadJNIEnvironment::javaVM->DetachCurrentThread(); 

你生活和學習!

回答

4

查找異常後檢查異常interfaceClassenv->ExceptionCheck()),或者只是檢查它是否爲非NULL。課堂查找很可能失敗。

+1

interfaceClass確實是NULL,謝謝。當從本地Java調用調用時,它工作正常。我會弄清楚我現在做錯了什麼! –

+1

事實證明,當調用JNI_OnLoad時,我需要爲接口類創建一個全局引用,然後使用它而不是從新線程的JNIEnv實例中查找它。 –

+3

您可能還需要緩存方法ID(您不需要爲此提供參考),並且應該爲該類使用弱全局引用。您需要參考,因爲您已經超出了單個JNI調用範圍的類引用(您獲得的初始引用是本地引用)。 – technomage