保持一个全球参考JNIEnv的环境 [英] Keeping a global reference to the JNIEnv environment

查看:168
本文介绍了保持一个全球参考JNIEnv的环境的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我存储了的JNIEnv 在全球,所以我可以在以后调用静态Java方法。但它是nessasary存储了一个全球性的指针的JNIEnv ,他们的方法之一将与其他Java对象,或者是它不需要这种特殊情况。

 的JNIEnv * globalEnvPointer;[JNICALL等]无效的init(JNIEnv的* ENV [等])
{
   //需要?
   globalEnvPointer =(JNIEnv的*)(ENV *) - GT; GetGlobalRef(ENV,ENV);
   //或者是这个行吗?
   globalEnvPointer = ENV;
}

修改

我兵有点哑这里,所有会使用 globalEnvPointer ,是我的init中调用的方法,因为我的的init 其实是我的 C 程序的方法,该方法将不会返回,直到节目结束。我也用在C程序中没有其他线程。我想,这简化了答案。

 的JNIEnv * globalEnvPointer;[JNICALL等]无效的主要(JNIEnv的* ENV [等])
{
   //需要?
   globalEnvPointer =(JNIEnv的*)(ENV *) - GT; GetGlobalRef(ENV,ENV);
   //或者是这个行吗?
   globalEnvPointer = ENV;
   的someMethod();
}无效的someMethod()
{
   //使用globalEnvPointer这里
}


解决方案

您无法缓存的JNIEnv 指针。你可以了解一下这里


  

JNI接口指针(JNIEnv的)只适用于当前线程。如果另一个线程需要访问Java虚拟机,它必须首先调用AttachCurrentThread()将其自身附加到虚拟机并且获得JNI接口指针。一旦连接到虚拟机之后,本地线程的工作原理就像一个本地方法内运行的普通Java线程。本地线程保持连接到虚拟机,直到它调用DetachCurrentThread()分离本身。


你可以做的是缓存的JavaVM 指针来代替。

 静态的JavaVM * JVM;[JNICALL等]无效的init(JNIEnv的* ENV [等])
{
   jint RS =(* ENV) - GT; GetJavaVM(ENV,&安培; JVM);
   断言(RS == JNI_OK);
}

然后当你从那里没有给出一个上下文需要那么的JNIEnv 指针你这样做:

 无效someCallback(){
    JNIEnv的* ENV;
    jint RS =(* JVM) - GT; AttachCurrentThread(JVM,&安培; ENV,NULL);
    断言(RS == JNI_OK);
    //使用ENV指针...
}

但每当你从Java调用本地方法的ENV指针使用给出:

  JNIEXPORT jint JNICALL Java_package_Class_method(JNIEnv的* ENV,jobject OBJ){
    //只使用ENV指针原样。
}

I am storing off JNIEnv in a global so I can call static java methods later. But is it nessasary to store off a global pointer to the JNIEnv, they way one would with any other java object, or is it a special case that does not require this.

JNIEnv* globalEnvPointer;

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

Edit

I'm bing a bit dumb here, all the methods that will use globalEnvPointer, are invoked within my init because my init is actually my c program's main method, which won't return until the end of the program. I am also using no other threads in the c program. I think this simplifies the answer.

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
}

解决方案

You cannot cache the JNIEnv pointer. Read about it here:

The JNI interface pointer (JNIEnv) is valid only in the current thread. Should another thread need to access the Java VM, it must first call AttachCurrentThread() to attach itself to the VM and obtain a JNI interface pointer. Once attached to the VM, a native thread works just like an ordinary Java thread running inside a native method. The native thread remains attached to the VM until it calls DetachCurrentThread() to detach itself.

What you can do is to cache the JavaVM pointer instead.

static JavaVM *jvm;

[JNICALL etc] void init(JNIENv* env, [etc])
{
   jint rs = (*env)->GetJavaVM(env, &jvm);
   assert (rs == JNI_OK);
}

And then whenever you need then JNIEnv pointer from a context where it is not given you do this:

void someCallback() {
    JNIEnv *env;
    jint rs = (*jvm)->AttachCurrentThread(jvm, &env, NULL);
    assert (rs == JNI_OK);
    // Use the env pointer...
}

But whenever you call a native method from Java the env pointer to use is given:

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

这篇关于保持一个全球参考JNIEnv的环境的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆