2011-03-28 104 views
9

我已經調用了一個本地程序,它創建了另一個線程,它將自己附加到JVM。現在我想訪問JVM的方法,但是失敗了。這裏是代碼:JNI - 線程和jobject的問題

// 
// This is the native function that gets called first. 
// it creates another thread which runs, and also calls the printing-methods in my 
// java applet. 
// 
JNIEXPORT void JNICALL Java_EIGC_1Applet_app_1native_native_1start(JNIEnv* jenv, jobject job) { 

    printAppletConsole(jenv,job,"unused atm"); 
    // save current java VM; 
    // save main applet class; 
    // used by main thread 
    jenv->GetJavaVM(&applet_java_jvm); 
    m_job = job; 


    // create the working and start it 
    applet_thread_main = new EIGC_Applet_thread(&main); 
    applet_thread_main->start(); 
} 


// 
// This is the running thread that was created 
// This will run and call the printing method in the applet 
// 
unsigned __stdcall main(void* args) { 
    // The JNIEnv 
    JNIEnv* jenv = new JNIEnv(); 

    // attach thread to running JVM 
    applet_java_jvm->AttachCurrentThread((void**)jenv,NULL); 

    // main running loop 
    while (true) { 
     Sleep(1000); 
     printAppletConsole(jenv,m_job,"unused"); 
    } 

    applet_thread_main->stop(); 
    return 0; 
    } 


// 
// Calls the "writeConsole()" method in applet which prints "test" in a JTextArea 
// 
void printAppletConsole(JNIEnv* jenv,jobject job,char* text) { 
    jclass cls = jenv->GetObjectClass(job); 
    jmethodID mid = jenv->GetMethodID(cls,"writeConsole","()V"); 
    if (mid==NULL) { 
      printf("Method not found"); 
    } 
    else { 
     jenv->CallVoidMethod(job,mid); 
    } 
} 

我有一個問題;

1)在新創建的線程中,當我嘗試調用printAppletConsole時,JVM掛起,它掛在GetObjectClass()上。爲什麼是這樣?

我懷疑是因爲我已經創建了一個新的線程,我需要訪問jobject的新實例,但是我不知道如何..

謝謝!

回答

7
m_job = job; 

這只是保持當你返回到java是無效的本地引用。你需要與NewGlobalRef做一個全球參考並存儲。

JNIEnv* jenv = new JNIEnv(); 
applet_java_jvm->AttachCurrentThread((void**)jenv,NULL); 

應該是:

JNIEnv* jenv = 0: 
applet_java_jvm->AttachCurrentThread(&jenv,NULL); 

編輯:對於舊版本的JNI,使用:

JNIEnv* jenv = 0: 
applet_java_jvm->AttachCurrentThread((void **) &jenv,NULL); 
+0

1.所以例如new_job = NewGlobalRef(m_job)在printConsole功能?功能完成後,我必須刪除new_job嗎? 2.你確定JNIEnv初始化嗎?它崩潰,如果我做JNIEnv * jenv = 0,並且編譯器也不喜歡&jenv,因爲它不是void **指針。謝謝你,先生! – KaiserJohaan 2011-03-28 14:54:42

+1

不,請在'Java_EIGC_1Applet_app_1native_native_1start'中使用'm_job = jenv-> NewGlobalRef(job)'。當你完全使用它時,也調用'jenv-> DeleteGlobalRef(m_job)'。 – Erik 2011-03-28 14:58:36

+0

我明白了。非常感謝! – KaiserJohaan 2011-03-29 07:18:13