Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI calling Java from C++ with multiple threads

I'm working on a project, where I call Java functions from C++ code (using JNI) and I have a problem about multithreading. I want to call Java searching function and for each call I want to make a separate thread. I have a singleton MainClass and nested Query class. Query class is inherited from QThread. Code looks like this

MainClass::MyQuery query("<some search query>");
query.LaunchQuery();


//functions of Query   
void MainClass::MyQuery::LaunchQuery() const
{
    this->start();
}

void MainClass::Query::run()
{
    const MainClass& mainClass = MainClass::GetInstance();
    const jclass& obj = mainClass.GetClass();
    JNIEnv& env = mainClass.GetJavaEnvironment();
    jmethodID methodId = env.GetMethodID(obj, "SearchQuery", "(Ljava/lang/String;)V"); //Run-time error

    if(methodId != 0)
    {
        //calling "SearchQuery" function
    }

Now, if run this code in a single thread - everything is fine, but if try to run above code - using multithreading, it causes run-time error by message "Unhandled exception at 0x777715de in MyApp.exe: 0xC0000005: Access violation reading location 0x000000ac." when I try to get method id. I've tried also with boost::thread but result was the same.

So why it fails when I'm doing it in a separate thread, when in the same thread everything is fine? Any ideas?

like image 644
nabroyan Avatar asked Aug 05 '13 10:08

nabroyan


1 Answers

Scroll down to 'Attaching to the VM' in the JNI docs :

http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/invocation.html

The JNI interface pointer (JNIEnv) is valid only in the current thread. Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer.

like image 69
Graham Griffiths Avatar answered Sep 20 '22 02:09

Graham Griffiths