2017-04-07 33 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++代码调用的,上面的方法是它的起点。 –