2013-08-05 40 views
7

Tôi đang làm việc trên một dự án, nơi tôi gọi các hàm Java từ mã C++ (sử dụng JNI) và tôi có một vấn đề về đa luồng. Tôi muốn gọi chức năng tìm kiếm Java và cho mỗi cuộc gọi, tôi muốn tạo một chuỗi riêng biệt. Tôi có một singleton MainClass và được lồng vào lớp Query. Lớp học Query được kế thừa từ QThread. Mã trông như thế nàyJNI gọi Java từ C++ với nhiều chủ đề

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 
    } 

Bây giờ, nếu chạy mã này trong một chủ đề duy nhất - tất cả mọi thứ là tốt, nhưng nếu cố gắng chạy trên mã - sử dụng đa luồng, nó gây ra lỗi thời gian chạy bằng tin nhắn "Unhandled exception at 0x777715de in MyApp.exe: 0xC0000005: Access violation reading location 0x000000ac." khi tôi cố gắng để lấy id phương thức. Tôi cũng đã thử với boost::thread nhưng kết quả là như nhau.

Vì vậy, tại sao nó không thành công khi tôi đang làm nó trong một chủ đề riêng biệt, khi trong cùng một chủ đề tất cả mọi thứ là tốt? Bất kỳ ý tưởng nào?

Trả lời

8

Cuộn xuống 'Gắn vào máy ảo' trong các tài liệu JNI:

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

Các JNI giao diện con trỏ (JNIEnv) chỉ có hiệu lực trong thread hiện hành. Nếu một thread khác cần truy cập vào máy ảo Java, nó phải gọi đầu tiên AttachCurrentThread() để đính kèm chính nó vào máy ảo và nhận được một con trỏ giao diện JNI.

+0

Và tôi sẽ thêm ví dụ cho http://stackoverflow.com/questions/12900695/how-to-obtain-jni-interface-pointer-jnienv-for-asynchronous-calls này – nabroyan

Các vấn đề liên quan