我正在开发一个非常庞大且复杂的 C++ 应用程序,该应用程序在几个不相关的地方使用 JNI 来完成不同的任务。平台是 RHEL 6。因为我不知道应用程序是否已经创建了 JNI,所以我使用这种方法来查找 JVM 并附加到它:
JOI_RetCode JavaObjectInterface::initJVM()
{
if (jvm_ == NULL)
{
// Is there an existing JVM already created?
jsize jvm_count = 0;
jint result = JNI_GetCreatedJavaVMs (&jvm_, 1, &jvm_count);
if (result != JNI_OK)
return JOI_ERROR_CHECK_JVM;
if (jvm_count == 1)
{
// Yes - use it.
result = jvm_->GetEnv((void**) &jenv_, JNI_VERSION_1_6);
switch (result)
{
case JNI_OK:
logger::log(CAT_JNI, LL_DEBUG, "Attached to an existing JVM.");
jenv_ = env;
break;
case JNI_EDETACHED:
result = jvm_->AttachCurrentThread((void**) &jenv_, NULL);
if (result != JNI_OK)
return JOI_ERROR_ATTACH_JVM;
needToDetach_ = true;
logger::log(CAT_JNI, LL_DEBUG, "Attached to an existing JVM from another thread.");
break;
case JNI_EVERSION:
logger::log(CAT_JNI, LL_DEBUG, "Attaching to a JVM of the wrong version.");
return JOI_ERROR_JVM_VERSION;
break;
default:
logger::log(CAT_JNI, LL_DEBUG, "Unknown error Attaching to an existing JVM.");
return JOI_ERROR_ATTACH_JVM;
break;
}
}
else
{
// No - create a new one.
result = createJVM();
if (result != JNI_OK)
return JOI_ERROR_CREATE_JVM;
needToDetach_ = false;
logger::log(CAT_JNI, LL_DEBUG, "Created a new JVM.");
}
}
return JOI_OK;
}
JVM 指针被定义为类数据成员,如下所示:
JavaVM* jvm_;
JNIEnv* jenv_;
现在,当在我调用该方法之前在其他地方创建 JVM 时,结果是对 JNI_GetCreatedJavaVMs() 的调用返回一个 JVM 指针,对 GetEnv() 的调用返回 JNI_OK,并使用看起来有效的指针更新 jenv_。到目前为止,一切都很好。但是,当我接下来这样做时:
jclass javaClass = jenv_->FindClass(className);
我抛出异常。我无法从异常本身获取任何数据,因为 stderr 被重定向到 /dev/null,所以如果我调用 ExceptionDescribe() ,输出将进入地狱。询问异常对象需要一个有效的 JNI 来调用 FindClass("Throwable"),所以这也不起作用。
对 FindClass() 的调用很好,因为当我创建第一个 JVM 时,它运行良好。
谁能帮我找到我必须在这里某个地方犯的愚蠢错误?谢谢,尤瓦尔。