JNI环境指针

问题描述:

我有一个Java类,其中我有一个必须从我的C代码中调用的函数。 的功能如下:JNI环境指针

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指针。仅对当前线程有效。
但是,您可以使用AttachCurrentThread获取当前线程的JNIEnv指针。
或者如果你知道它已经连接,你可以使用GetEnv
除此之外,你没有提到你如何使用全球jobject obj,但请记住,你需要注意这些引用保持有效的时间足够长。 NewGlobalRef是要走的路。

未经测试:你的答复我添加的代码的缺失的部分,我initJNI函数来显示我如何使用jobject

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); 
} 
+0

感谢。你可以发布代码以说明如何在我的例子中使用它? – LBes

+0

@LBes:我想应该是这样的。我完全不了解你的例子。看起来你正在尝试创建一个新的对象,但你也存储一个对象。而你的'NewObject'call没有Ctor方法参考。所以这看起来很可疑。但我希望这有助于。 – mkaes

+0

感谢您的代码,我会尽力解决这个问题。但是,在代码中的评论中,“使用全局”是什么意思? – LBes