2013-08-05 5 views
7

Pracuję nad projektem, w którym nazywam funkcje Java z kodu C++ (przy użyciu JNI) i mam problem z wielowątkowością. Chcę wywołać funkcję wyszukiwania Java i dla każdego połączenia chcę utworzyć osobny wątek. Mam klasa pojedyncza MainClass i zagnieżdżona klasa Query. Klasa Query jest dziedziczona po QThread. Kod wygląda następującoJNI wywoływanie Java z C++ z wieloma wątkami

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 
    } 

Teraz, jeśli uruchomić ten kod w jednym wątku - wszystko jest w porządku, ale jeśli próbujesz uruchomić powyższy kod - za pomocą wielowątkowości, powoduje błąd czasu wiadomością "Unhandled exception at 0x777715de in MyApp.exe: 0xC0000005: Access violation reading location 0x000000ac." gdy próbuję aby uzyskać identyfikator metody. Próbowałem również z boost::thread, ale wynik był taki sam.

Dlaczego więc nie działa, gdy robię to w oddzielnym wątku, gdy w tym samym wątku wszystko jest w porządku? Jakieś pomysły?

Odpowiedz

8

Przewiń w dół do 'Dołączanie do VM' w Dokumentach JNI:

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

interfejs JNI wskaźnik (JNIEnv) jest ważna tylko w bieżącym wątku. Jeśli inny wątek musi uzyskać dostęp do maszyny wirtualnej Java, musi najpierw zadzwonić AttachCurrentThread(), aby podłączyć się do maszyny wirtualnej i uzyskać wskaźnik interfejsu JNI.

+0

I dodam przykład tego http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls – nabroyan