1, first lead me to meet a problem (I think first write the question, so the impression deeper engraved a bit):
Android Java layer when calling local JNI code, will maintain a local reference table (maximum length is 512), general JNI function call after the end of the JVM will release this reference, if it is simple function does not pay attention to these problems, let himself release, basically there is no problem, But if there is a loop in the function, then the program will have a crash, such as I have in the project in a Jni method, a queue of the native layer into the Java layer of the list, and then back to the Java layer to use, so, Inevitably in the local method inside the loop operation, and I just some small details did not notice, forget to delete some local applications, start measuring a small amount of data when a little problem did not, then the data scale is big, directly on the collapse, fortunately log log inside the crash log printed out, Then know that the code inside is there is a reference is not released, the specific log is this:
This is probably the case in my Code:
Jobject Collect (jnienv *env)
{
For (...,. ...,..)
{
Jobject obj = dosomething (env, clazz);
Delete Reference
Env->deletelocalref (obj);
Env->deletelocalref (Clazz); If the clazz is not changed, then this code can not write, findclass after all, the performance of the
}
}
Jobject dosomething (jnienv *env, Jclass clazz)
{
Return Env->newobject (Clazz, Env->newstringutf (Str.c_str ()));
}
The above is just the approximate structure of my Code, the meaning of understanding is OK ah, here I actually in the main call function is to delete the local reference, but in the call method when the use of dosomething () such a similar method, you can see, dosomething () Function returned when the generation of a local reference jstring, but did not release, this for the subsequent crash buried hidden trouble, melancholy for a while, let me find the reason, will dosomething () changed to the following wording, the problem to be resolved satisfactorily,
Jobject dosomething (jnienv *env)
{
Jstring test = Env->newsringutf (Str.c_str ());
jobject ret = env->newobject (clazz, test);
Env->deletelocalref (test);
return ret;
}
2, the JNI Quote Summary:
References play an important role in Java programming, where virtual machines manage the life cycle of class instances by tracking references, although virtual machines cannot manage native code, but JNI provides a series of methods that allow local code to accurately manage the reference and lifecycle of classes, JNI supports three types of references, local references (local references), global references (Globals references), virtual global references (weak global references); Well, in short, the reference is a very important thing, the Java GC program is based on whether the class reference is zero to reclaim the class, if the local code holds a reference to Java objects without releasing, then the GC is not able to properly reclaim objects, there is a risk of memory leaks.
. Partial references (local Reference)
Most of the JNI methods return local references, note that local references cannot be cached, local reference lifecycles are confined to local methods, and local references are freed once the local code returns, with a chestnut: Env->findclass () returns a local reference, When the local code returns, it will be released automatically, of course, the local code can also be controlled by the Deletelocalref method to control the release of local references;
Jclass Clazz;
Clazz = Env->findclass ("java/lang/string");
. Global reference (Reference)
A global reference preserves a valid reference until the local method precisely releases it (for example, as a global variable, local static variables are not possible with local references, but global references can), and global references can be initialized with local references through the Newglobalref method (it seems like this is the only way, Pop ~)
Jclass Localclazz;
Jclass Globalclazz;
...
Localclazz = Env->findclass ("java/lang/string");
Globalclazz = Env->newglobalref (Localclazz);
...
Env->deletelocalref (Localclazz);
Spicy? The problem comes, just as local references can be released manually, can global references be released manually? Hey, you can release the global Reference by Env->deleteglobalref ().
. Virtual Global Reference
There is also a global reference that is a virtual global reference, as does the global reference, but the virtual global reference does not prevent the GC from reclaiming the object, and the global reference does not reclaim the GC because it holds the reference to the object. Creates a new virtual function reference through Newweakglobalref.
Jclass Weakglobalclazz;
Weakglobalclazz = Env->newweakglobalref (Localclazz);
Students who like to think this time will find a problem, because the virtual global reference can not prevent the GC collection of objects, then we are swollen to know that the object has been recycled it, acridine, do not worry, JNI has provided a way for the nest
if (Jni_false = = Env->issameobject (Weakglobalclazz, NULL))
{
Object is still live and can used.
}else {
object is garbage collected and cannot be used
}
A method similar to deleting a virtual global reference is: Env->deleteweakglobalref (Weakglobalclazz); This method can be used at any time. The global reference retains a valid reference unless it is precisely released, and can be called in other local methods. Virtual global references are the same, but be aware that the GC has reclaimed the object.
Note:
Virtual machines support running local code under multiple threads, and we need to keep in mind the following when developing native code:
1. Local references are valid until the local method is executed, and local threads cannot be shared multithreaded, only global references can be shared over multiple threads.
2. The JNIEnv interface pointer is valid in other methods of the same thread through the called local method, but it cannot be cached for use by other threads, and the workaround is to get jnienv through the JVM (specifically @ Niang).
NDK Development references (local references, global references, virtual global references)