我嘗試做以下(不知道如果我失去了一些東西,或者如果這是不可能的):JNI,Mulithreading和調用方法
我有一個Java類(在這種特殊情況下一個Servlet )調用本地方法。
在這種本地方法中,我產生了一個新線程,並且在該線程中我想調用該Java對象上的一個方法。這甚至有可能嗎?
我在被調用的原始方法(原始線程)中嘗試的方法是記住JavaVM實例,以便稍後可以將其他線程附加到它上面(似乎可行),併爲此創建一個NewGlobal參考jobject:
JavaVM *vm;
env->GetJavaVM(&vm);
env->NewGlobalRef(jobj)
我不知道是如何檢索另一個線程中的jobject。如果我只是通過它虛擬機崩潰,我假設由於非法線程訪問。如果我爲這個類創建一個新的對象,我就不會有我需要的確切對象。
任何想法?
謝謝 馬克
一些額外的代碼(方法名稱等遮擋):
The method that is called from the servlet:
JNIEXPORT jstring JNICALL ABC (JNIEnv *env, jobject jobj, some more arguments
{
JavaVM *vm;
env->GetJavaVM(&vm);
env->NewGlobalRef(jobj);
// spawning new thread (I'm using boost libraries)
boost::thread t = boost::thread(boost::bind(&XYZ::DEF, instance of XYZ, vm, &jobj);
...
}
void XYZ::DEF(JavaVM* vm, jobject* jobj)
{
JNIEnv* env;
vm->GetEnv((void**)&env, JNI_VERSION_1_2);
vm->AttachCurrentThread((void**)&env, NULL);
... then eventually calling another method, but still the same thread, where I'm doing this:
jobject bb = env->NewDirectByteBuffer(...,...); // this crashed when I just used the env from the original thread, seems to work since I'm attaching the second thread to the VM.
// it crashes somewhere during the following code:
jclass cls = env->GetObjectClass(jobj);
jmethodID mid = env->GetMethodID(cls, "callback", "(I)V");
env->CallVoidMethod(jobj, mid, 13);
崩潰,產生這樣的「一個致命的錯誤已被JRE檢測...問題的框架:V [libjvm.so + 0x3e9220] ...
您正在調用AttachCurrentThread並使用返回的env指針不是嗎? – mcnicholls 2012-02-03 12:53:32
@mcnicholls:是的。之後,我做了一個GetObjectClass,使用我從原始線程中記住的jobject實例,當我執行env-> CallVoidMehtod(jobj,...)時,我也使用這個實例實例,其中env是調用AttachCurrentThread時返回的內容。 – Mark 2012-02-03 13:52:27
你能展示更多代碼嗎?你在做什麼聽起來很對;全局引用可以被任何線程使用,直到你刪除它。 – 2012-02-03 14:01:01