Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping a global reference to the JNIEnv environment

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 } 
like image 705
weston Avatar asked Sep 14 '12 08:09

weston


People also ask

What is JNI global references?

A JNI global reference is a reference from "native" code to a Java object managed by the Java garbage collector. Its purpose is to prevent collection of an object that is still in use by native code, but doesn't appear to have any live references in the Java code. A JFrame is a java. awt.

What is JNIEnv?

JNIEnv – a structure containing methods that we can use our native code to access Java elements. JavaVM – a structure that lets us manipulate a running JVM (or even start a new one) adding threads to it, destroying it, etc…

Does JNI use reflection?

Each method that can be called via JNI has a reflection metadata object. The address of this object is used as the method's jmethodID .

What is JNI H?

jni. h is a C/C++ header file included with the JDK that maps Java types to their native counterparts. javah automatically includes this file in the application header files.


1 Answers

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. } 
like image 129
maba Avatar answered Oct 04 '22 01:10

maba