2017-04-07 59 views
0

我在寫一個使用JNI與Jav​​a代碼進行通信的多線程C++程序。根據設計,以下方法(run())由線程運行,一次運行後,本地線程可能會切換。 (輪循式的線程分配)在性能路徑中正確使用JNI DetachCurrentThread

bool JavaModule::run() 
{ 
    initObjects(); 
    /*Attaching to the current thread 
    *and checking for JVM exceptions 
    *for each run 
    */ 
    Interpreter::getEnv()->CallObjectMethod(objid, msgid, NULL); 
    if (Interpreter::getEnv()->ExceptionCheck()) 
    { 
     getLogger().error("ERR: JVM Exception occurred when running the script"); 
     return false; 
    } 

    //Detaching from the current thread 
    //There is a performance hit when detaching the Environment each time 
    Interpreter::detachEnv(); 
    return true; 
} 

此調用程序的性能路徑,如果我嘗試連接和分離從當前線程環境存在較大的性能問題。附件在getEnv()中看起來像這樣。

static JNIEnv* Interpreter::getEnv() 
{ 
    JNIEnv *env; 
    int status = jvm->GetEnv((void**)&env, JNI_VERSION_1_6); 
    if (status < 0) 
    { 
     status = jvm->AttachCurrentThread((void**)&env, NULL); 
     if (status < 0) 
     { 
      return nullptr; 
     } 
    } 
    return env; 
} 

JVM是定義爲static JavaVM* jvm;

類成員的分離的代碼看起來如下。

static bool Interpreter::detachEnv() 
{ 
    if (jvm->DetachCurrentThread() == JNI_OK) 
    { 
     return true; 
    } 
    return false; 
} 

在這個級別的代碼有沒有關於線程和線程的創建水平不會有關於JVM的思想觀念。

我的問題是什麼將是一個很好的解決方案安全地分離線程沒有性能影響?

+1

您不應該分離未明確附加的線程。也就是說,你需要跟蹤你的'JNIEnv *'是來自'GetEnv'還是'AttachCurrentThread',並且在後一種情況下只調用'DetachCurrentThread'。 – Michael

+0

@Michael喜歡在流程結束時保持緩存並清理所有內容? –

+0

我已經發布了有關過去的答案:http://stackoverflow.com/a/30026231/1524450 – Michael

回答

0

請勿將性能關鍵線程附加或分離到jvm。 JVM需要與垃圾收集器同步,垃圾收集器是一個大規模單線程臨界區。

如果您需要一個性能關鍵的線程與jvm進行通信,您需要使用某種異步消息傳遞。

您也可以在線程創建&加入時附加和分離線程,但您仍然必須與其他方法中的gc同步。

+0

很難用設計創建一個異步模型。因爲Java程序是使用C++代碼調用的,上面的方法是它的起點。 –