我有一个Java类,其中有一个必须从我的C代码中调用的函数。
该函数如下:
public void endTrial(){
//Code
}
因此,我在C文件中创建了以下代码:
JNIEXPORT void JNICALL package_endTrialJava();
JNIEXPORT void JNICALL package_endTrialJava(){
jobject javaObjectRef = env->NewObject(javaClassRef, javaMethodRef);
env->CallVoidMethod(javaObjectRef, javaMethodRef);
}
但是,为了能够使用
env
变量调用此函数,我创建了此函数,每当我启动程序时都会调用该函数。JNIEXPORT void JNICALL package_initJNI(JNIEnv* en, jobject ob)
{
try {
// LOGD("(JNI) [FluidMechanics] loadVelocityDataSet()");
if (!App::getInstance())
throw std::runtime_error("init() was not called");
if (App::getType() != App::APP_TYPE_FLUID)
throw std::runtime_error("Wrong application type");
FluidMechanics* instance = dynamic_cast<FluidMechanics*>(App::getInstance());
android_assert(instance);
jclass dataClass = en->FindClass("fr/limsi/ARViewer/MainActivity");
javaClassRef = (jclass) env->NewGlobalRef(dataClass);
javaMethodRef = env->GetMethodID(javaClassRef, "endTrial", "()V");
env = en ;
obj = ob ;
} catch (const std::exception& e) {
throwJavaException(env, e.what());
}
}
而且我在代码中也声明了这些全局变量,以便对initJNI()的调用可以存储JNIEnv变量。
JNIEnv* env ;
jobject obj ;
但是我的程序崩溃了,因此似乎无法存储
JNIEnv
变量。那有什么解决方法吗? 最佳答案
您不能/不应该存储JNIEnv
指针。 Is仅对当前线程有效。
但是您可以使用AttachCurrentThread
来获取当前线程的JNIEnv
指针。
或者,如果您知道它已附加,则可以使用GetEnv
。
此外,您不会提及如何使用全局jobject obj
,但要记住,您需要注意这些引用的有效期足够长。 NewGlobalRef
是必经之路。
未经测试:
JavaVM* g_jvm = 0;
JNIEXPORT void JNICALL package_initJNI(JNIEnv* en, jobject ob)
{
....
// insted of the env store the VM
en->GetJavaVM(&g_jvm);
obj = en->NewGlobalRef(ob); // I don't think you need this
// and at some point you must delete it again
....
}
JNIEXPORT void JNICALL package_endTrialJava(){
JNIEnv* env;
g_jvm->AttachCurrentThread(&env, NULL); // check error etc
jobject javaObjectRef = env->NewObject(javaClassRef, javaMethodRef);
// this line makes not much sense. I think you don't need it if you use the global
// with the global it would be more like this
env->CallVoidMethod(obj javaMethodRef);
}
关于java - JNI环境指针,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38976639/