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();
你生活和學習!
interfaceClass確實是NULL,謝謝。當從本地Java調用調用時,它工作正常。我會弄清楚我現在做錯了什麼! –
事實證明,當調用JNI_OnLoad時,我需要爲接口類創建一個全局引用,然後使用它而不是從新線程的JNIEnv實例中查找它。 –
您可能還需要緩存方法ID(您不需要爲此提供參考),並且應該爲該類使用弱全局引用。您需要參考,因爲您已經超出了單個JNI調用範圍的類引用(您獲得的初始引用是本地引用)。 – technomage