Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>First of all: <code>myEnv = (*env)-&gt;NewGlobalRef(env,obj);</code> is just wrong. <a href="https://stackoverflow.com/questions/6202621/how-to-create-static-jni-environment-pointer">You mustn't cache this value</a>.</p> <p>What you're allowed to is to cache method IDs, field IDs, class references, ... (but make sure you clean up this stuff afterwards). But caching these values requires special measures. </p> <p><strong>Why?</strong> The problem is that the JVM is allowed to load and unload classes according to the needs of the program. Therefore it could happen that a class is unloaded as soon as the last instance of the class has been destroyed by the garbage collector. As soon as this happens your cached IDs are not valid anymore. It's possible that the IDs will be the same after the JVM loads the class again but this is not guaranteed. </p> <p><strong>Solution:</strong> If you want to cache these IDs you have to tell the JVM that it's not allowed to unload a class. This is exactly what <code>NewGlobalRef</code> does. You just increment the reference for the reference passed to <code>NewGlobalRef</code> so the reference count never drops to zero and grabage collection is not allowed to clean up the referenced element.</p> <p><strong>Attention:</strong> Creating a <code>NewGlobalRef</code> has a serious drawback: Other than in Java you have to make sure that you call <code>DeleteGlobalRef</code> if you don't need this reference anymore in order to reenable the garbage collection of the reference. (As the garbage collecter is not aware of wether you still need this reference or not) Or in other words: You have to make sure that you cleanup your garbage yourself otherwise you'll leave a memory leak.</p> <p>I'd also say it's not a good idea to create a global ref for an object (unless you really want to keep the object alive) as this means the object won't ever get into garbage and therefore never will be freed.</p> <p><strong>Better Variant:</strong> If you want to cache these IDs in order to speedup access to a certain object, keep a global reference for the class (using <code>FindClass</code>) and grab the IDs from the class object <code>FindClass</code> returns. </p> <p>Here's a (incomplete) example of what I mean. I usually create a structure holding all the IDs I need to access a class just to keep my namespaces clean. You can imagine this as follows:</p> <pre><code>/*! \brief Holds cached field IDs for MyClass.java */ typedef struct MyClass { int loaded; /*!&lt; Nonzero if the information are valid */ jclass clazz; /*!&lt; Holds a global ref for the class */ jfieldID aField; /*!&lt; Holds the field ID of aField */ }tMyClass; static tMyClass me = { 0 }; </code></pre> <p>The easiest way is to provide a "connect" function for your object which does the initialization of the structure defined above.</p> <pre><code>/*! \brief This function fetches field IDs for a specific class in order to have faster access elsewhere in the code \param env a valid JNI environment \return - 0 if OK - &lt;0 if an error occured */ int MyClass_connect(JNIEnv *env) { jobject theClass = env-&gt;FindClass("MyClass"); if (theClass == NULL) goto no_class; me.clazz = (jclass) env-&gt;NewGlobalRef(theClass); // make it global to avoid class unloading and therefore // invalidating the references obtained. if (me.clazz == NULL) goto no_memory; me.aField = env-&gt;GetFieldID(me.clazz, "aField", "I") ; if (me.aField == NULL) goto no_aField; me.loaded = 1; return 0; no_aField: env-&gt;DeleteGlobalRef(me.clazz); no_memory: no_class: return -1; } </code></pre> <p>After calling <code>MyClass_connect</code> successfully you can use <code>me.aField</code> to shorten the code to access a the field in your code. Of course you have to provide a disconnect function which is called when MyClass is not required anymore:</p> <pre><code>void MyClass_disconnect(JNIEnv *env) { if (me.loaded == 0) return; env-&gt;DeleteGlobalRef(me.clazz); memset(me, 0, sizeof(tMyClass)); } </code></pre> <p>Sorry for this a bit lengthy posting but I hope this helps to solve your confusion a bit and gives you a bit an insight of the inner workings of JNI together with a little receipe how to deal with this efficiently.</p> <p><strong>Edit:</strong> You can find documentation about JNI calls on <a href="http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/jniTOC.html" rel="nofollow noreferrer">oracle's website</a></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload