2012-02-03 92 views
2

我嘗試做以下(不知道如果我失去了一些東西,或者如果這是不可能的):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] ...

+0

您正在調用AttachCurrentThread並使用返回的env指針不是嗎? – mcnicholls 2012-02-03 12:53:32

+0

@mcnicholls:是的。之後,我做了一個GetObjectClass,使用我從原始線程中記住的jobject實例,當我執行env-> CallVoidMehtod(jobj,...)時,我也使用這個實例實例,其中env是調用AttachCurrentThread時返回的內容。 – Mark 2012-02-03 13:52:27

+0

你能展示更多代碼嗎?你在做什麼聽起來很對;全局引用可以被任何線程使用,直到你刪除它。 – 2012-02-03 14:01:01

回答

3

你似乎被忽略的NewGlobalRef結果你必須使用其結果在其他線程,而不是原來jobj

+0

就是這樣。謝謝! – Mark 2012-02-06 06:55:13