Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 保持对JNIEnv环境的全局引用_C_Java Native Interface_Jnienv - Fatal编程技术网

C 保持对JNIEnv环境的全局引用

C 保持对JNIEnv环境的全局引用,c,java-native-interface,jnienv,C,Java Native Interface,Jnienv,我将offJNIEnv存储在一个全局文件中,以便稍后调用静态java方法。但是,是否有必要像存储任何其他java对象那样存储指向JNIEnv的全局指针,还是不需要这样做的特殊情况 JNIEnv* globalEnvPointer; [JNICALL etc] void init(JNIENv* env, [etc]) { //required? globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env); //

我将off
JNIEnv
存储在一个全局文件中,以便稍后调用静态java方法。但是,是否有必要像存储任何其他java对象那样存储指向
JNIEnv
的全局指针,还是不需要这样做的特殊情况

JNIEnv* globalEnvPointer;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
}
编辑

我在这里有点傻,所有使用
globalEnvPointer
的方法都在我的init中调用,因为我的
init
实际上是我的
c
程序的
main
方法,在程序结束之前不会返回。我也没有在c程序中使用其他线程。我认为这简化了答案

JNIEnv* globalEnvPointer;

[JNICALL etc] void main(JNIENv* env, [etc])
{
   //required?
   globalEnvPointer = (JNIENv*) (env*)->GetGlobalRef(env, env);
   //or is this OK?
   globalEnvPointer = env;
   someMethod();
}

void someMethod()
{
   //use globalEnvPointer here
}

无法缓存
JNIEnv
指针。请阅读:

JNI接口指针(JNIEnv)仅在当前线程中有效。如果另一个线程需要访问Java VM,它必须首先调用AttachCurrentThread()将自身连接到VM并获取JNI接口指针。一旦连接到VM,本机线程的工作方式与在本机方法中运行的普通Java线程类似。本机线程在调用DetachCurrentThread()以分离自身之前一直保持与VM的连接

您可以做的是缓存
JavaVM
指针

static JavaVM *jvm;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   jint rs = (*env)->GetJavaVM(env, &jvm);
   assert (rs == JNI_OK);
}
然后,无论何时,只要您需要
JNIEnv
指针,就可以从未提供该指针的上下文中执行以下操作:

void someCallback() {
    JNIEnv *env;
    jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
    assert (rs == JNI_OK);
    // Use the env pointer...
}
但无论何时从Java调用本机方法,都会给出要使用的env指针:

JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv *env, jobject obj) {
    // just use the env pointer as is.
}

都是一根线,有区别吗?i、 我的
init
是在同一个线程中调用的,这个线程稍后将调用静态java方法?在我看来,将临时数据存储在全局变量中以供其他方法使用是一种反模式。是的,我同意,但我正在尝试使用大量的
c
源代码库,并用java重写100多个汇编方法(如
someCallback
)。我们说的是执行调用的数千个位置。另外,同样的源代码库仍然应该为其原始目标编译,因此传递
JNIEnv
实际上是一个丑陋的解决方案。感谢所有的提示,如果我需要使用线程,我会把它们记在心里。如果已经有通过JavaVM的JNI_OnLoad,我不会创建自己的init函数。@maba:OP可能需要一个单独的init函数,但他也可能根本不知道JNI_OnLoad的存在。它只是扩展了答案。它不是批评,只是一个友好的小扩展提示。我不写我自己的答案,因为我认为你的答案已经很好了,你应该得到分数。然而,也要考虑其他人阅读你的答案,而不仅仅是OP,他们下面有经验丰富和没有经验的人。