Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI - problem with threads and jobject

I have called a native program which creates another thread, which attaches itself to the JVM. Now I want to access the methods of the JVM, but it fails. Here is the code:

//
// 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);
    }
}

I have one question;

1) In the newly created thread, the JVM just hangs when I try to call printAppletConsole, it hangs on the GetObjectClass(). Why is this?

My suspicion is that since I have created a new thread, I need to access a new instance of jobject, but Im not sure how..

Thanks!

like image 211
KaiserJohaan Avatar asked Mar 28 '11 14:03

KaiserJohaan


1 Answers

m_job = job;

This just keeps the local reference which is invalid as soon as you return to java. You need to make a global referene with NewGlobalRef and store that.

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

Should be:

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

EDIT: For older JNI versions, use:

JNIEnv* jenv = 0:
applet_java_jvm->AttachCurrentThread((void **) &jenv,NULL);
like image 187
Erik Avatar answered Oct 19 '22 01:10

Erik