问题
I have a Java class in which I have a function which must be called from my C code. The function is the following:
public void endTrial(){
//Code
}
So I have created the following code in my C file:
JNIEXPORT void JNICALL package_endTrialJava();
JNIEXPORT void JNICALL package_endTrialJava(){
jobject javaObjectRef = env->NewObject(javaClassRef, javaMethodRef);
env->CallVoidMethod(javaObjectRef, javaMethodRef);
}
But to be able to call this function with the env
variable, I have created this function which is called whenever I launch my program.
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());
}
}
And I have these global variables declared in my code as well, so that the call to initJNI() can store the JNIEnv variable.
JNIEnv* env ;
jobject obj ;
But my program crashed so it seems that storing the JNIEnv
variable does not work. Is there any workaround then?
回答1:
You cannot/should not store the JNIEnv
pointer. Is is only valid for the current thread.
But you can use AttachCurrentThread
to get a JNIEnv
pointer for your current thread.
Or if you know that it is already attached you can use GetEnv
.
And beside of that you do not mention how you use the global jobject obj
but keep in mind that you need to take care that those references stay valid long enough. NewGlobalRef
is the way to go.
Untested:
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);
}
来源:https://stackoverflow.com/questions/38976639/jni-environment-pointer